Module Name:    src
Committed By:   martin
Date:           Tue Aug  1 17:03:54 UTC 2023

Modified Files:
        src/distrib/sets/lists/debug [netbsd-10]: mi
        src/distrib/sets/lists/tests [netbsd-10]: mi
        src/libexec/ld.elf_so [netbsd-10]: Makefile reloc.c rtld.c rtld.h
            symbol.c
        src/tests/libexec/ld.elf_so [netbsd-10]: Makefile
Added Files:
        src/libexec/ld.elf_so [netbsd-10]: hash.c hash.h
        src/tests/libexec/ld.elf_so [netbsd-10]: t_hash.c

Log Message:
Pull up following revision(s) (requested by riastradh in ticket #300):

        libexec/ld.elf_so/rtld.h: revision 1.145
        libexec/ld.elf_so/symbol.c: revision 1.74
        libexec/ld.elf_so/rtld.h: revision 1.147
        libexec/ld.elf_so/symbol.c: revision 1.75
        libexec/ld.elf_so/symbol.c: revision 1.76
        tests/libexec/ld.elf_so/t_hash.c: revision 1.1
        libexec/ld.elf_so/Makefile: revision 1.145
        libexec/ld.elf_so/Makefile: revision 1.146
        libexec/ld.elf_so/Makefile: revision 1.147
        libexec/ld.elf_so/reloc.c: revision 1.118
        distrib/sets/lists/tests/mi: revision 1.1280
        libexec/ld.elf_so/rtld.c: revision 1.215
        tests/libexec/ld.elf_so/Makefile: revision 1.21
        libexec/ld.elf_so/hash.c: revision 1.1
        libexec/ld.elf_so/hash.h: revision 1.1
        distrib/sets/lists/debug/mi: revision 1.409

The SysV ABI specifies that the symbol hash function should return only 32
bits of hash. Unfortunately due to an implementation bug 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.

Oops wrong mask.

ld.elf_so: Split SRCS onto multiple lines.
Makes updates easier.
No functional change intended.

ld.elf_so: Sort SRCS.
No functional change intended.

ld.elf_so: Split hash functions into a separate file.
This way we can test them in isolation.
No functional change intended.

ld.elf_so: Add some known-answer tests for hash functions.

Make sure the testing mechanism detects the traditional overflow bug.


To generate a diff of this commit:
cvs rdiff -u -r1.394.2.1 -r1.394.2.2 src/distrib/sets/lists/debug/mi
cvs rdiff -u -r1.1238.2.1 -r1.1238.2.2 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.144 -r1.144.2.1 src/libexec/ld.elf_so/Makefile
cvs rdiff -u -r0 -r1.1.2.2 src/libexec/ld.elf_so/hash.c \
    src/libexec/ld.elf_so/hash.h
cvs rdiff -u -r1.117 -r1.117.2.1 src/libexec/ld.elf_so/reloc.c
cvs rdiff -u -r1.212.2.2 -r1.212.2.3 src/libexec/ld.elf_so/rtld.c
cvs rdiff -u -r1.144.2.1 -r1.144.2.2 src/libexec/ld.elf_so/rtld.h
cvs rdiff -u -r1.73 -r1.73.8.1 src/libexec/ld.elf_so/symbol.c
cvs rdiff -u -r1.12.4.1 -r1.12.4.2 src/tests/libexec/ld.elf_so/Makefile
cvs rdiff -u -r0 -r1.1.2.2 src/tests/libexec/ld.elf_so/t_hash.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/debug/mi
diff -u src/distrib/sets/lists/debug/mi:1.394.2.1 src/distrib/sets/lists/debug/mi:1.394.2.2
--- src/distrib/sets/lists/debug/mi:1.394.2.1	Tue Aug  1 16:34:57 2023
+++ src/distrib/sets/lists/debug/mi	Tue Aug  1 17:03:54 2023
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.394.2.1 2023/08/01 16:34:57 martin Exp $
+# $NetBSD: mi,v 1.394.2.2 2023/08/01 17:03:54 martin Exp $
 ./etc/mtree/set.debug                           comp-sys-root
 ./usr/lib					comp-sys-usr		compatdir
 ./usr/lib/i18n/libBIG5_g.a			comp-c-debuglib		debuglib,compatfile
@@ -2401,8 +2401,9 @@
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-false.debug	tests-libexec-debug	debug,atf,pic,compattestfile
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlinfo.debug		tests-libexec-debug	debug,atf,pic,compattestfile
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlvsym.debug		tests-libexec-debug	debug,atf,pic,compattestfile
-./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_rtld_r_debug.debug	tests-libexec-debug	debug,atf,pic,compattestfile
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_hash.debug		tests-libexec-debug	debug,atf,pic,compattestfile
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_ifunc.debug	tests-libexec-debug	debug,atf,pic,compattestfile
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_rtld_r_debug.debug	tests-libexec-debug	debug,atf,pic,compattestfile
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_tls_extern.debug	tests-libexec-debug	debug,atf,pic,compattestfile
 ./usr/libdata/debug/usr/tests/net/bpf/t_bpf.debug		tests-net-debug		debug,atf,rump
 ./usr/libdata/debug/usr/tests/net/bpf/t_div-by-zero.debug		tests-net-debug		debug,atf,rump

Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.1238.2.1 src/distrib/sets/lists/tests/mi:1.1238.2.2
--- src/distrib/sets/lists/tests/mi:1.1238.2.1	Tue Aug  1 16:34:56 2023
+++ src/distrib/sets/lists/tests/mi	Tue Aug  1 17:03:53 2023
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1238.2.1 2023/08/01 16:34:56 martin Exp $
+# $NetBSD: mi,v 1.1238.2.2 2023/08/01 17:03:53 martin Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -4093,6 +4093,7 @@
 ./usr/tests/libexec/ld.elf_so/t_dlerror-false		tests-libexec-tests	compattestfile,atf,pic
 ./usr/tests/libexec/ld.elf_so/t_dlinfo			tests-libexec-tests	compattestfile,atf,pic
 ./usr/tests/libexec/ld.elf_so/t_dlvsym			tests-libexec-tests	compattestfile,atf,pic
+./usr/tests/libexec/ld.elf_so/t_hash			tests-libexec-tests	compattestfile,atf,pic
 ./usr/tests/libexec/ld.elf_so/t_ifunc			tests-libexec-tests	compattestfile,atf,pic
 ./usr/tests/libexec/ld.elf_so/t_rtld_r_debug		tests-libexec-tests	compattestfile,atf,pic
 ./usr/tests/libexec/ld.elf_so/t_thread_local_dtor	tests-libexec-tests	compattestfile,atf,pic

Index: src/libexec/ld.elf_so/Makefile
diff -u src/libexec/ld.elf_so/Makefile:1.144 src/libexec/ld.elf_so/Makefile:1.144.2.1
--- src/libexec/ld.elf_so/Makefile:1.144	Sat Dec  4 08:45:56 2021
+++ src/libexec/ld.elf_so/Makefile	Tue Aug  1 17:03:53 2023
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.144 2021/12/04 08:45:56 skrll Exp $
+#	$NetBSD: Makefile,v 1.144.2.1 2023/08/01 17:03:53 martin Exp $
 #
 # NOTE: when changing ld.so, ensure that ldd still compiles.
 #
@@ -72,9 +72,23 @@ PROG=		ld.elf_so
 
 CLIBOBJ!=	cd ${NETBSDSRCDIR}/lib/libc && ${PRINTOBJDIR}
 
-SRCS+=		rtld.c reloc.c symbol.c xmalloc.c xprintf.c debug.c \
-		map_object.c load.c search.c headers.c paths.c expand.c \
-		tls.c symver.c diagassert.c compat.c
+SRCS+=		compat.c
+SRCS+=		debug.c
+SRCS+=		diagassert.c
+SRCS+=		expand.c
+SRCS+=		hash.c
+SRCS+=		headers.c
+SRCS+=		load.c
+SRCS+=		map_object.c
+SRCS+=		paths.c
+SRCS+=		reloc.c
+SRCS+=		rtld.c
+SRCS+=		search.c
+SRCS+=		symbol.c
+SRCS+=		symver.c
+SRCS+=		tls.c
+SRCS+=		xmalloc.c
+SRCS+=		xprintf.c
 
 .if ${USE_FORT} == "yes"
 .PATH.c: ${NETBSDSRCDIR}/lib/libc/misc

Index: src/libexec/ld.elf_so/reloc.c
diff -u src/libexec/ld.elf_so/reloc.c:1.117 src/libexec/ld.elf_so/reloc.c:1.117.2.1
--- src/libexec/ld.elf_so/reloc.c:1.117	Sat Dec  4 08:53:34 2021
+++ src/libexec/ld.elf_so/reloc.c	Tue Aug  1 17:03:53 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: reloc.c,v 1.117 2021/12/04 08:53:34 skrll Exp $	 */
+/*	$NetBSD: reloc.c,v 1.117.2.1 2023/08/01 17:03:53 martin Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -39,7 +39,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: reloc.c,v 1.117 2021/12/04 08:53:34 skrll Exp $");
+__RCSID("$NetBSD: reloc.c,v 1.117.2.1 2023/08/01 17:03:53 martin Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -56,6 +56,7 @@ __RCSID("$NetBSD: reloc.c,v 1.117 2021/1
 #include <dirent.h>
 
 #include "debug.h"
+#include "hash.h"
 #include "rtld.h"
 
 #ifndef RTLD_INHIBIT_COPY_RELOCS

Index: src/libexec/ld.elf_so/rtld.c
diff -u src/libexec/ld.elf_so/rtld.c:1.212.2.2 src/libexec/ld.elf_so/rtld.c:1.212.2.3
--- src/libexec/ld.elf_so/rtld.c:1.212.2.2	Tue Aug  1 16:34:56 2023
+++ src/libexec/ld.elf_so/rtld.c	Tue Aug  1 17:03:53 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtld.c,v 1.212.2.2 2023/08/01 16:34:56 martin Exp $	 */
+/*	$NetBSD: rtld.c,v 1.212.2.3 2023/08/01 17:03:53 martin Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.212.2.2 2023/08/01 16:34:56 martin Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.212.2.3 2023/08/01 17:03:53 martin Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -60,7 +60,9 @@ __RCSID("$NetBSD: rtld.c,v 1.212.2.2 202
 #include <ctype.h>
 
 #include <dlfcn.h>
+
 #include "debug.h"
+#include "hash.h"
 #include "rtld.h"
 
 #if !defined(lint)

Index: src/libexec/ld.elf_so/rtld.h
diff -u src/libexec/ld.elf_so/rtld.h:1.144.2.1 src/libexec/ld.elf_so/rtld.h:1.144.2.2
--- src/libexec/ld.elf_so/rtld.h:1.144.2.1	Tue Aug  1 16:34:56 2023
+++ src/libexec/ld.elf_so/rtld.h	Tue Aug  1 17:03:53 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: rtld.h,v 1.144.2.1 2023/08/01 16:34:56 martin Exp $	 */
+/*	$NetBSD: rtld.h,v 1.144.2.2 2023/08/01 17:03:53 martin Exp $	 */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -442,8 +442,6 @@ void _rtld_call_ifunc(Obj_Entry *, sigse
 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 *);
 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 *,

Index: src/libexec/ld.elf_so/symbol.c
diff -u src/libexec/ld.elf_so/symbol.c:1.73 src/libexec/ld.elf_so/symbol.c:1.73.8.1
--- src/libexec/ld.elf_so/symbol.c:1.73	Sat Feb 29 18:45:20 2020
+++ src/libexec/ld.elf_so/symbol.c	Tue Aug  1 17:03:53 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: symbol.c,v 1.73 2020/02/29 18:45:20 kamil Exp $	 */
+/*	$NetBSD: symbol.c,v 1.73.8.1 2023/08/01 17:03:53 martin 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.73.8.1 2023/08/01 17:03:53 martin Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -57,6 +57,7 @@ __RCSID("$NetBSD: symbol.c,v 1.73 2020/0
 #include <dirent.h>
 
 #include "debug.h"
+#include "hash.h"
 #include "rtld.h"
 
 /*
@@ -80,45 +81,6 @@ _rtld_donelist_check(DoneList *dlp, cons
 	return false;
 }
 
-/*
- * Hash function for symbol table lookup.  Don't even think about changing
- * this.  It is specified by the System V ABI.
- */
-unsigned long
-_rtld_sysv_hash(const char *name)
-{
-	const unsigned char *p = (const unsigned char *) name;
-	unsigned long   h = 0;
-	unsigned long   g;
-	unsigned long   c;
-
-	for (; __predict_true((c = *p) != '\0'); p++) {
-		h <<= 4;
-		h += c;
-		if ((g = h & 0xf0000000) != 0) {
-			h ^= g;
-			h ^= g >> 24;
-		}
-	}
-	return (h);
-}
-
-/*
- * Hash function for symbol table lookup.  Don't even think about changing
- * this.  It is specified by the GNU toolchain ABI.
- */
-unsigned long
-_rtld_gnu_hash(const char *name)
-{
-	const unsigned char *p = (const unsigned char *) name;
-	uint_fast32_t h = 5381;
-	unsigned char c;
-
-	for (c = *p; c != '\0'; c = *++p)
-		h = h * 33 + c;
-	return (unsigned long)h;
-}
-
 const Elf_Sym *
 _rtld_symlook_list(const char *name, Elf_Hash *hash, const Objlist *objlist,
     const Obj_Entry **defobj_out, u_int flags, const Ver_Entry *ventry,

Index: src/tests/libexec/ld.elf_so/Makefile
diff -u src/tests/libexec/ld.elf_so/Makefile:1.12.4.1 src/tests/libexec/ld.elf_so/Makefile:1.12.4.2
--- src/tests/libexec/ld.elf_so/Makefile:1.12.4.1	Tue Aug  1 16:34:58 2023
+++ src/tests/libexec/ld.elf_so/Makefile	Tue Aug  1 17:03:53 2023
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.12.4.1 2023/08/01 16:34:58 martin Exp $
+# $NetBSD: Makefile,v 1.12.4.2 2023/08/01 17:03:53 martin Exp $
 #
 
 NOMAN=		# defined
@@ -30,6 +30,12 @@ TESTSDIR=	${TESTSBASE}/libexec/ld.elf_so
 TESTS_C+=	t_dlerror-cleared t_dlerror-false t_dlinfo t_dlvsym t_ifunc
 TESTS_C+=	t_rtld_r_debug
 TESTS_C+=	t_tls_extern
+TESTS_C+=	t_hash
+
+.PATH:	${NETBSDSRCDIR}/libexec/ld.elf_so
+SRCS.t_hash+=	t_hash.c
+SRCS.t_hash+=	hash.c
+CPPFLAGS.t_hash.c+=	-I${NETBSDSRCDIR}/libexec/ld.elf_so
 
 COPTS.t_rtld_r_debug.c += ${${ACTIVE_CC} == "gcc" :? -Wno-maybe-uninitialized :}
 

Added files:

Index: src/libexec/ld.elf_so/hash.c
diff -u /dev/null src/libexec/ld.elf_so/hash.c:1.1.2.2
--- /dev/null	Tue Aug  1 17:03:54 2023
+++ src/libexec/ld.elf_so/hash.c	Tue Aug  1 17:03:53 2023
@@ -0,0 +1,81 @@
+/*	$NetBSD: hash.c,v 1.1.2.2 2023/08/01 17:03:53 martin Exp $	 */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <m...@3am-software.com>
+ * Copyright 2002 Charles M. Hannum <r...@ihack.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Dynamic linker for ELF.
+ *
+ * John Polstra <j...@polstra.com>.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: hash.c,v 1.1.2.2 2023/08/01 17:03:53 martin Exp $");
+#endif /* not lint */
+
+#include <stdint.h>
+
+#include "hash.h"
+
+/*
+ * SysV hash function for symbol table lookup.  It is a slightly optimized
+ * version of the hash specified by the System V ABI.
+ */
+Elf32_Word
+_rtld_sysv_hash(const char *name)
+{
+	const unsigned char *p = (const unsigned char *) name;
+	Elf32_Word h = 0;
+
+	while (__predict_true(*p != '\0')) {
+		h = (h << 4) + *p++;
+		h ^= (h >> 24) & 0xf0;
+	}
+	return (h & 0x0fffffff);
+}
+
+/*
+ * Hash function for symbol table lookup.  Don't even think about changing
+ * this.  It is specified by the GNU toolchain ABI.
+ */
+Elf32_Word
+_rtld_gnu_hash(const char *name)
+{
+	const unsigned char *p = (const unsigned char *) name;
+	uint_fast32_t h = 5381;
+	unsigned char c;
+
+	for (c = *p; c != '\0'; c = *++p)
+		h = h * 33 + c;
+	return (h & 0xffffffff);
+}
Index: src/libexec/ld.elf_so/hash.h
diff -u /dev/null src/libexec/ld.elf_so/hash.h:1.1.2.2
--- /dev/null	Tue Aug  1 17:03:54 2023
+++ src/libexec/ld.elf_so/hash.h	Tue Aug  1 17:03:53 2023
@@ -0,0 +1,42 @@
+/*	$NetBSD: hash.h,v 1.1.2.2 2023/08/01 17:03:53 martin Exp $	 */
+
+/*
+ * Copyright 1996 John D. Polstra.
+ * Copyright 1996 Matt Thomas <m...@3am-software.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by John Polstra.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef	RTLD_HASH_H
+#define	RTLD_HASH_H
+
+#include <sys/exec_elf.h>
+
+Elf32_Word _rtld_sysv_hash(const char *);
+Elf32_Word _rtld_gnu_hash(const char *);
+
+#endif	/* RTLD_HASH_H */

Index: src/tests/libexec/ld.elf_so/t_hash.c
diff -u /dev/null src/tests/libexec/ld.elf_so/t_hash.c:1.1.2.2
--- /dev/null	Tue Aug  1 17:03:54 2023
+++ src/tests/libexec/ld.elf_so/t_hash.c	Tue Aug  1 17:03:53 2023
@@ -0,0 +1,218 @@
+/*	$NetBSD: t_hash.c,v 1.1.2.2 2023/08/01 17:03:53 martin Exp $	*/
+
+/*-
+ * Copyright (c) 2023 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <atf-c.h>
+#include <stdint.h>
+
+#include "hash.h"
+
+/* known-answer tests */
+struct kat {
+	const char *in;
+	unsigned long long out;
+};
+
+/*
+ * From the SysV spec, with uint64_t instead of unsigned long to
+ * illustrate the problem on all systems, not just LP64 ones.
+ *
+ * https://www.sco.com/developers/devspecs/gabi41.pdf#page=95
+ */
+static uint64_t
+sysv_broken_hash(const char *name)
+{
+	uint64_t h = 0, g;
+
+	while (*name) {
+		h = (h << 4) + *name++;
+		if ((g = h & 0xf0000000) != 0)
+			h ^= g >> 24;
+		h &= ~g;
+	}
+
+	return h;
+}
+
+ATF_TC(sysv);
+ATF_TC_HEAD(sysv, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "SysV hash (32-bit)");
+}
+ATF_TC_BODY(sysv, tc)
+{
+	static const struct kat kat[] = {
+		{ "", 0x00000000 },
+		{ "a", 0x00000061 },
+		{ "aa", 0x00000671 },
+		{ "aaa", 0x00006771 },
+		{ "aaaa", 0x00067771 },
+		{ "aaaaa", 0x00677771 },
+		{ "aaaaaa", 0x06777771 },
+		{ "aaaaaaa", 0x07777711 },
+		{ "aaaaaaaa", 0x07777101 },
+		{ "aaaaaaaaa", 0x07771001 },
+		{ "ab", 0x00000672 },
+		{ "abc", 0x00006783 },
+		{ "abcd", 0x00067894 },
+		{ "abcde", 0x006789a5 },
+		{ "abcdef", 0x06789ab6 },
+		{ "abcdefg", 0x0789aba7 },
+		{ "abcdefgh", 0x089abaa8 },
+		{ "abcdefghi", 0x09abaa69 },
+		/* https://maskray.me/blog/2023-04-12-elf-hash-function */
+		{ "Z", 0x0000005a },
+		{ "ZZ", 0x000005fa },
+		{ "ZZZ", 0x00005ffa },
+		{ "ZZZZ", 0x0005fffa },
+		{ "ZZZZZ", 0x005ffffa },
+		{ "ZZZZZW", 0x05fffff7 },
+		{ "ZZZZZW9", 0x0ffffff9 },
+		{ "ZZZZZW9p", 0x00000000 },
+		{ "pneumonoultramicroscopicsilicovolcanoconiosis",
+		  0x051706b3 },
+	};
+	unsigned i;
+
+	for (i = 0; i < __arraycount(kat); i++) {
+		unsigned long long h = _rtld_sysv_hash(kat[i].in);
+
+		ATF_CHECK_EQ_MSG(h, kat[i].out,
+		    "[%u] _rtld_hash_sysv(\"%s\") = 0x%08llx != 0x%08llx",
+		    i, kat[i].in, h, kat[i].out);
+	}
+}
+
+ATF_TC(sysv_broken);
+ATF_TC_HEAD(sysv_broken, tc)
+{
+	atf_tc_set_md_var(tc, "descr",
+	    "SysV hash (broken with 64-bit unsigned long)");
+}
+ATF_TC_BODY(sysv_broken, tc)
+{
+	static const struct kat kat[] = {
+		{ "", 0x00000000 },
+		{ "a", 0x00000061 },
+		{ "aa", 0x00000671 },
+		{ "aaa", 0x00006771 },
+		{ "aaaa", 0x00067771 },
+		{ "aaaaa", 0x00677771 },
+		{ "aaaaaa", 0x06777771 },
+		{ "aaaaaaa", 0x07777711 },
+		{ "aaaaaaaa", 0x07777101 },
+		{ "aaaaaaaaa", 0x07771001 },
+		{ "ab", 0x00000672 },
+		{ "abc", 0x00006783 },
+		{ "abcd", 0x00067894 },
+		{ "abcde", 0x006789a5 },
+		{ "abcdef", 0x06789ab6 },
+		{ "abcdefg", 0x0789aba7 },
+		{ "abcdefgh", 0x089abaa8 },
+		{ "abcdefghi", 0x09abaa69 },
+		/* https://maskray.me/blog/2023-04-12-elf-hash-function */
+		{ "Z", 0x0000005a },
+		{ "ZZ", 0x000005fa },
+		{ "ZZZ", 0x00005ffa },
+		{ "ZZZZ", 0x0005fffa },
+		{ "ZZZZZ", 0x005ffffa },
+		{ "ZZZZZW", 0x05fffff7 },
+		{ "ZZZZZW9", 0x0ffffff9 },
+		{ "ZZZZZW9p", 0x100000000 },
+		{ "pneumonoultramicroscopicsilicovolcanoconiosis",
+		  0x051706b3 },
+	};
+	unsigned i;
+
+	for (i = 0; i < __arraycount(kat); i++) {
+		unsigned long long h = sysv_broken_hash(kat[i].in);
+
+		ATF_CHECK_EQ_MSG(h, kat[i].out,
+		    "[%u] sysv_broken_hash(\"%s\") = 0x%08llx != 0x%08llx",
+		    i, kat[i].in, h, kat[i].out);
+	}
+}
+
+ATF_TC(gnu);
+ATF_TC_HEAD(gnu, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "GNU hash (djb2)");
+}
+ATF_TC_BODY(gnu, tc)
+{
+	static const struct kat kat[] = {
+		{ """", 0x00001505 },
+		{ "a", 0x0002b606 },
+		{ "aa", 0x00597727 },
+		{ "aaa", 0x0b885c68 },
+		{ "aaaa", 0x7c93e9c9 },
+		{ "aaaaa", 0x0f11234a },
+		{ "aaaaaa", 0xf1358ceb },
+		{ "aaaaaaa", 0x17e72aac },
+		{ "aaaaaaaa", 0x14cc808d },
+		{ "aaaaaaaaa", 0xae5c928e },
+		{ "ab", 0x00597728 },
+		{ "abc", 0x0b885c8b },
+		{ "abcd", 0x7c93ee4f },
+		{ "abcde", 0x0f11b894 },
+		{ "abcdef", 0xf148cb7a },
+		{ "abcdefg", 0x1a623b21 },
+		{ "abcdefgh", 0x66a99fa9 },
+		{ "abcdefghi", 0x3bdd9532 },
+		{ "Z", 0x0002b5ff },
+		{ "ZZ", 0x00597639 },
+		{ "ZZZ", 0x0b883db3 },
+		{ "ZZZZ", 0x7c8ff46d },
+		{ "ZZZZZ", 0x0e8e8267 },
+		{ "ZZZZZW", 0xe05ecf9e },
+		{ "ZZZZZW9", 0xec38c397 },
+		{ "ZZZZZW9p", 0x735136e7 },
+		{ "pneumonoultramicroscopicsilicovolcanoconiosis",
+		  0xee6245b5 },
+	};
+	unsigned i;
+
+	for (i = 0; i < __arraycount(kat); i++) {
+		unsigned long long h = _rtld_gnu_hash(kat[i].in);
+
+		ATF_CHECK_EQ_MSG(h, kat[i].out,
+		    "[%u] _rtld_gnu_hash(\"%s\") = 0x%08llx != 0x%08llx",
+		    i, kat[i].in, h, kat[i].out);
+	}
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+	ATF_TP_ADD_TC(tp, gnu);
+	ATF_TP_ADD_TC(tp, sysv);
+	ATF_TP_ADD_TC(tp, sysv_broken);
+
+	return atf_no_error();
+}

Reply via email to