The SysV ABI specifies that the symbol hash function should return only 32

bits of hash. Unfortunately due to an implementation bu and the fact that
the return type is unsigned long which is 64 bits in LP64, this can fail
in some cases: "\xff\x0f\x0f\x0f\x0f\x0f\x12". See:
    https://maskray.me/blog/2023-04-12-elf-hash-function
From Ed Maste @ FreeBSD:
    https://cgit.freebsd.org/src/commit/\
	?id=29e3a06510823edbb91667d21f530d3ec778116d
Need to write Unit Tests for this.
This commit is contained in:
christos 2023-04-18 16:48:45 +00:00
parent e92b04bbd5
commit 5eb593004f
2 changed files with 15 additions and 21 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtld.h,v 1.144 2022/06/21 06:52:17 skrll Exp $ */
/* $NetBSD: rtld.h,v 1.145 2023/04/18 16:48:45 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -440,8 +440,8 @@ void _rtld_call_ifunc(Obj_Entry *, sigset_t *, u_int);
Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int);
/* symbol.c */
unsigned long _rtld_sysv_hash(const char *);
unsigned long _rtld_gnu_hash(const char *);
Elf32_Word _rtld_sysv_hash(const char *);
Elf32_Word _rtld_gnu_hash(const char *);
const Elf_Sym *_rtld_symlook_obj(const char *, Elf_Hash *,
const Obj_Entry *, u_int, const Ver_Entry *);
const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *,

View File

@ -1,4 +1,4 @@
/* $NetBSD: symbol.c,v 1.73 2020/02/29 18:45:20 kamil Exp $ */
/* $NetBSD: symbol.c,v 1.74 2023/04/18 16:48:45 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: symbol.c,v 1.73 2020/02/29 18:45:20 kamil Exp $");
__RCSID("$NetBSD: symbol.c,v 1.74 2023/04/18 16:48:45 christos Exp $");
#endif /* not lint */
#include <err.h>
@ -81,33 +81,27 @@ _rtld_donelist_check(DoneList *dlp, const Obj_Entry *obj)
}
/*
* Hash function for symbol table lookup. Don't even think about changing
* this. It is specified by the System V ABI.
* SysV hash function for symbol table lookup. It is a slightly optimized
* version of the hash specified by the System V ABI.
*/
unsigned long
Elf32_Word
_rtld_sysv_hash(const char *name)
{
const unsigned char *p = (const unsigned char *) name;
unsigned long h = 0;
unsigned long g;
unsigned long c;
Elf32_Word h = 0;
for (; __predict_true((c = *p) != '\0'); p++) {
h <<= 4;
h += c;
if ((g = h & 0xf0000000) != 0) {
h ^= g;
h ^= g >> 24;
}
while (__predict_true(*p != '\0')) {
h = (h << 4) + *p++;
h ^= (h >> 24) & 0xf0;
}
return (h);
return (h & 0xffffffff);
}
/*
* Hash function for symbol table lookup. Don't even think about changing
* this. It is specified by the GNU toolchain ABI.
*/
unsigned long
Elf32_Word
_rtld_gnu_hash(const char *name)
{
const unsigned char *p = (const unsigned char *) name;
@ -116,7 +110,7 @@ _rtld_gnu_hash(const char *name)
for (c = *p; c != '\0'; c = *++p)
h = h * 33 + c;
return (unsigned long)h;
return (h & 0xffffffff);
}
const Elf_Sym *