diff mbox series

Add test of ELF hash collisions

Message ID d54866a0-016c-60cf-70ff-bea780b27436@redhat.com
State New
Headers show
Series Add test of ELF hash collisions | expand

Commit Message

Joseph Myers Oct. 25, 2024, 11:28 p.m. UTC
Add tests that the dynamic linker works correctly with symbol names
involving hash collisions, for both choices of hash style (and
--hash-style=both as well).  I note that there weren't actually any
previous tests using --hash-style (so tests would only cover the
default linker configuration in that regard).

I propose to add such a test for hash collisions for symbol version
names separately.

Tested for x86_64.

Comments

Florian Weimer Oct. 28, 2024, 11:54 a.m. UTC | #1
* Joseph Myers:

> Add tests that the dynamic linker works correctly with symbol names
> involving hash collisions, for both choices of hash style (and
> --hash-style=both as well).  I note that there weren't actually any
> previous tests using --hash-style (so tests would only cover the
> default linker configuration in that regard).
>
> I propose to add such a test for hash collisions for symbol version
> names separately.

Would it make sense to have a test with the symbols in separate DSOs,
too?

What about testing collisions for specific hash values such as
-2147483648, -2147483647, -2, -1, 0, 1, 2, 2147483646, 2147483647?
I think that's an area where the symbol version hash implementation has
a problems (bug 29190).

Thanks,
Florian
Joseph Myers Oct. 31, 2024, 11:23 p.m. UTC | #2
On Mon, 28 Oct 2024, Florian Weimer wrote:

> * Joseph Myers:
> 
> > Add tests that the dynamic linker works correctly with symbol names
> > involving hash collisions, for both choices of hash style (and
> > --hash-style=both as well).  I note that there weren't actually any
> > previous tests using --hash-style (so tests would only cover the
> > default linker configuration in that regard).
> >
> > I propose to add such a test for hash collisions for symbol version
> > names separately.
> 
> Would it make sense to have a test with the symbols in separate DSOs,
> too?
> 
> What about testing collisions for specific hash values such as
> -2147483648, -2147483647, -2, -1, 0, 1, 2, 2147483646, 2147483647?
> I think that's an area where the symbol version hash implementation has
> a problems (bug 29190).

This version adds a test with two DSOs, as well as tests with specific 
hash values.  (Note that most of the values you gave aren't possible for 
the classic ELF hash as it's essentially a 28-bit hash.)


Add test of ELF hash collisions

Add tests that the dynamic linker works correctly with symbol names
involving hash collisions, for both choices of hash style (and
--hash-style=both as well).  I note that there weren't actually any
previous tests using --hash-style (so tests would only cover the
default linker configuration in that regard).

I propose to add such a test for hash collisions for symbol version
names separately.

Tested for x86_64.

---

Changed in v2: also test collisions various specific values of the
hashes and a case with more than one shared object involved.

diff --git a/elf/Makefile b/elf/Makefile
index fda796f6d5..9cb16d95ac 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -433,6 +433,12 @@ tests += \
   tst-global1 \
   tst-global2 \
   tst-gnu2-tls2 \
+  tst-hash-collision1 \
+  tst-hash-collision1-gnu \
+  tst-hash-collision1-sysv \
+  tst-hash-collision2 \
+  tst-hash-collision2-gnu \
+  tst-hash-collision2-sysv \
   tst-initfinilazyfail \
   tst-initorder \
   tst-initorder2 \
@@ -885,6 +891,15 @@ modules-names += \
   tst-gnu2-tls2mod0 \
   tst-gnu2-tls2mod1 \
   tst-gnu2-tls2mod2 \
+  tst-hash-collision1-mod \
+  tst-hash-collision1-mod-gnu \
+  tst-hash-collision1-mod-sysv \
+  tst-hash-collision2-mod1 \
+  tst-hash-collision2-mod1-gnu \
+  tst-hash-collision2-mod1-sysv \
+  tst-hash-collision2-mod2 \
+  tst-hash-collision2-mod2-gnu \
+  tst-hash-collision2-mod2-sysv \
   tst-initlazyfailmod \
   tst-initorder2a \
   tst-initorder2b \
@@ -3160,3 +3175,22 @@ tst-dlopen-tlsreinit4-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
 tst-dlopen-auditdup-ENV = LD_AUDIT=$(objpfx)tst-dlopen-auditdup-auditmod.so
 $(objpfx)tst-dlopen-auditdup.out: \
   $(objpfx)tst-dlopen-auditdupmod.so $(objpfx)tst-dlopen-auditdup-auditmod.so
+
+LDFLAGS-tst-hash-collision1-mod.so = -Wl,--hash-style=both
+$(objpfx)tst-hash-collision1: $(objpfx)tst-hash-collision1-mod.so
+LDFLAGS-tst-hash-collision1-mod-gnu.so = -Wl,--hash-style=gnu
+$(objpfx)tst-hash-collision1-gnu: $(objpfx)tst-hash-collision1-mod-gnu.so
+LDFLAGS-tst-hash-collision1-mod-sysv.so = -Wl,--hash-style=sysv
+$(objpfx)tst-hash-collision1-sysv: $(objpfx)tst-hash-collision1-mod-sysv.so
+LDFLAGS-tst-hash-collision2-mod1.so = -Wl,--hash-style=both
+LDFLAGS-tst-hash-collision2-mod2.so = -Wl,--hash-style=both
+$(objpfx)tst-hash-collision2: $(objpfx)tst-hash-collision2-mod1.so \
+  $(objpfx)tst-hash-collision2-mod2.so
+LDFLAGS-tst-hash-collision2-mod1-gnu.so = -Wl,--hash-style=gnu
+LDFLAGS-tst-hash-collision2-mod2-gnu.so = -Wl,--hash-style=gnu
+$(objpfx)tst-hash-collision2-gnu: $(objpfx)tst-hash-collision2-mod1-gnu.so \
+  $(objpfx)tst-hash-collision2-mod2-gnu.so
+LDFLAGS-tst-hash-collision2-mod1-sysv.so = -Wl,--hash-style=sysv
+LDFLAGS-tst-hash-collision2-mod2-sysv.so = -Wl,--hash-style=sysv
+$(objpfx)tst-hash-collision2-sysv: $(objpfx)tst-hash-collision2-mod1-sysv.so \
+  $(objpfx)tst-hash-collision2-mod2-sysv.so
diff --git a/elf/tst-hash-collision1-gnu.c b/elf/tst-hash-collision1-gnu.c
new file mode 100644
index 0000000000..92f0862e91
--- /dev/null
+++ b/elf/tst-hash-collision1-gnu.c
@@ -0,0 +1 @@
+#include "tst-hash-collision1.c"
diff --git a/elf/tst-hash-collision1-mod-gnu.c b/elf/tst-hash-collision1-mod-gnu.c
new file mode 100644
index 0000000000..e4d03dd9bf
--- /dev/null
+++ b/elf/tst-hash-collision1-mod-gnu.c
@@ -0,0 +1 @@
+#include "tst-hash-collision1-mod.c"
diff --git a/elf/tst-hash-collision1-mod-sysv.c b/elf/tst-hash-collision1-mod-sysv.c
new file mode 100644
index 0000000000..e4d03dd9bf
--- /dev/null
+++ b/elf/tst-hash-collision1-mod-sysv.c
@@ -0,0 +1 @@
+#include "tst-hash-collision1-mod.c"
diff --git a/elf/tst-hash-collision1-mod.c b/elf/tst-hash-collision1-mod.c
new file mode 100644
index 0000000000..c848af8ae1
--- /dev/null
+++ b/elf/tst-hash-collision1-mod.c
@@ -0,0 +1,448 @@
+/* Test ELF hash collisions: shared object.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+
+/* Names with hash collisions for classic ELF hash.  */
+
+int
+foo (void)
+{
+  return 1;
+}
+
+int
+Hxxxynpfoo (void)
+{
+  return 2;
+}
+
+int
+HxxxynpHxxxynpfoo (void)
+{
+  return 3;
+}
+
+int
+HxxxynpHxxxynpHxxxynpfoo (void)
+{
+  return 4;
+}
+
+int
+HxxxynpHxxxynpHxxxynpHxxxynpfoo (void)
+{
+  return 5;
+}
+
+
+/* Names with hash collisions for GNU hash.  */
+
+int
+bar (void)
+{
+  return 10;
+}
+
+int
+gliinmbar (void)
+{
+  return 9;
+}
+
+int
+gliinmgliinmbar (void)
+{
+  return 8;
+}
+
+int
+gliinmgliinmgliinmbar (void)
+{
+  return 7;
+}
+
+int
+gliinmgliinmgliinmgliinmbar (void)
+{
+  return 6;
+}
+
+
+/* Names with specific hash values for each hash (see
+   tst-hash-collision1.c for details).  */
+
+int
+Hxxxynp (void)
+{
+  return 11;
+}
+
+int
+HxxxypP (void)
+{
+  return 12;
+}
+
+int
+Hxxyinp (void)
+{
+  return 13;
+}
+
+int
+HxxyipP (void)
+{
+  return 14;
+}
+
+int
+HxxykNp (void)
+{
+  return 15;
+}
+
+int
+Hxxxyoa (void)
+{
+  return 16;
+}
+
+int
+HxxxypQ (void)
+{
+  return 17;
+}
+
+int
+HxxxyqA (void)
+{
+  return 18;
+}
+
+int
+HxxxzaA (void)
+{
+  return 19;
+}
+
+int
+Hxxxz_a (void)
+{
+  return 20;
+}
+
+int
+Hxxxyob (void)
+{
+  return 21;
+}
+
+int
+HxxxypR (void)
+{
+  return 22;
+}
+
+int
+HxxxyqB (void)
+{
+  return 23;
+}
+
+int
+HxxxzaB (void)
+{
+  return 24;
+}
+
+int
+Hxxxz_b (void)
+{
+  return 25;
+}
+
+int
+glidpk (void)
+{
+  return 26;
+}
+
+int
+glidqJ (void)
+{
+  return 27;
+}
+
+int
+glieOk (void)
+{
+  return 28;
+}
+
+int
+gliePJ (void)
+{
+  return 29;
+}
+
+int
+gljCpk (void)
+{
+  return 30;
+}
+
+int
+glidpl (void)
+{
+  return 31;
+}
+
+int
+glidqK (void)
+{
+  return 32;
+}
+
+int
+glieOl (void)
+{
+  return 33;
+}
+
+int
+gliePK (void)
+{
+  return 34;
+}
+
+int
+gljCpl (void)
+{
+  return 35;
+}
+
+int
+glidpm (void)
+{
+  return 36;
+}
+
+int
+glidqL (void)
+{
+  return 37;
+}
+
+int
+glieOm (void)
+{
+  return 38;
+}
+
+int
+gliePL (void)
+{
+  return 39;
+}
+
+int
+gljCpm (void)
+{
+  return 40;
+}
+
+int
+AdfmZru (void)
+{
+  return 41;
+}
+
+int
+AdfmZsT (void)
+{
+  return 42;
+}
+
+int
+AdfmZt3 (void)
+{
+  return 43;
+}
+
+int
+Adfn9ru (void)
+{
+  return 44;
+}
+
+int
+Adfn9sT (void)
+{
+  return 45;
+}
+
+int
+AdfmZrv (void)
+{
+  return 46;
+}
+
+int
+AdfmZsU (void)
+{
+  return 47;
+}
+
+int
+AdfmZt4 (void)
+{
+  return 48;
+}
+
+int
+Adfn9rv (void)
+{
+  return 49;
+}
+
+int
+Adfn9sU (void)
+{
+  return 50;
+}
+
+int
+AdfmZrw (void)
+{
+  return 51;
+}
+
+int
+AdfmZsV (void)
+{
+  return 52;
+}
+
+int
+AdfmZt5 (void)
+{
+  return 53;
+}
+
+int
+Adfn9rw (void)
+{
+  return 54;
+}
+
+int
+Adfn9sV (void)
+{
+  return 55;
+}
+
+int
+AdfmZrx (void)
+{
+  return 56;
+}
+
+int
+AdfmZsW (void)
+{
+  return 57;
+}
+
+int
+AdfmZt6 (void)
+{
+  return 58;
+}
+
+int
+Adfn9rx (void)
+{
+  return 59;
+}
+
+int
+Adfn9sW (void)
+{
+  return 60;
+}
+
+int
+glidpi (void)
+{
+  return 61;
+}
+
+int
+glidqH (void)
+{
+  return 62;
+}
+
+int
+glieOi (void)
+{
+  return 63;
+}
+
+int
+gliePH (void)
+{
+  return 64;
+}
+
+int
+gljCpi (void)
+{
+  return 65;
+}
+
+int
+glidpj (void)
+{
+  return 66;
+}
+
+int
+glidqI (void)
+{
+  return 67;
+}
+
+int
+glieOj (void)
+{
+  return 68;
+}
+
+int
+gliePI (void)
+{
+  return 69;
+}
+
+int
+gljCpj (void)
+{
+  return 70;
+}
diff --git a/elf/tst-hash-collision1-sysv.c b/elf/tst-hash-collision1-sysv.c
new file mode 100644
index 0000000000..92f0862e91
--- /dev/null
+++ b/elf/tst-hash-collision1-sysv.c
@@ -0,0 +1 @@
+#include "tst-hash-collision1.c"
diff --git a/elf/tst-hash-collision1.c b/elf/tst-hash-collision1.c
new file mode 100644
index 0000000000..80ab0da8f5
--- /dev/null
+++ b/elf/tst-hash-collision1.c
@@ -0,0 +1,196 @@
+/* Test ELF hash collisions.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+
+/* Names with hash collisions for classic ELF hash.  */
+extern int foo (void);
+extern int Hxxxynpfoo (void);
+extern int HxxxynpHxxxynpfoo (void);
+extern int HxxxynpHxxxynpHxxxynpfoo (void);
+extern int HxxxynpHxxxynpHxxxynpHxxxynpfoo (void);
+
+/* Names with hash collisions for GNU hash.  */
+extern int bar (void);
+extern int gliinmbar (void);
+extern int gliinmgliinmbar (void);
+extern int gliinmgliinmgliinmbar (void);
+extern int gliinmgliinmgliinmgliinmbar (void);
+
+/* Classic ELF hash 0.  */
+extern int Hxxxynp (void);
+extern int HxxxypP (void);
+extern int Hxxyinp (void);
+extern int HxxyipP (void);
+extern int HxxykNp (void);
+
+/* Classic ELF hash 1.  */
+extern int Hxxxyoa (void);
+extern int HxxxypQ (void);
+extern int HxxxyqA (void);
+extern int HxxxzaA (void);
+extern int Hxxxz_a (void);
+
+/* Classic ELF hash 2.  */
+extern int Hxxxyob (void);
+extern int HxxxypR (void);
+extern int HxxxyqB (void);
+extern int HxxxzaB (void);
+extern int Hxxxz_b (void);
+
+/* GNU hash 0.  */
+extern int glidpk (void);
+extern int glidqJ (void);
+extern int glieOk (void);
+extern int gliePJ (void);
+extern int gljCpk (void);
+
+/* GNU hash 1.  */
+extern int glidpl (void);
+extern int glidqK (void);
+extern int glieOl (void);
+extern int gliePK (void);
+extern int gljCpl (void);
+
+/* GNU hash 2.  */
+extern int glidpm (void);
+extern int glidqL (void);
+extern int glieOm (void);
+extern int gliePL (void);
+extern int gljCpm (void);
+
+/* GNU hash 0x7ffffffe.  */
+extern int AdfmZru (void);
+extern int AdfmZsT (void);
+extern int AdfmZt3 (void);
+extern int Adfn9ru (void);
+extern int Adfn9sT (void);
+
+/* GNU hash 0x7fffffff.  */
+extern int AdfmZrv (void);
+extern int AdfmZsU (void);
+extern int AdfmZt4 (void);
+extern int Adfn9rv (void);
+extern int Adfn9sU (void);
+
+/* GNU hash 0x80000000.  */
+extern int AdfmZrw (void);
+extern int AdfmZsV (void);
+extern int AdfmZt5 (void);
+extern int Adfn9rw (void);
+extern int Adfn9sV (void);
+
+/* GNU hash 0x80000001.  */
+extern int AdfmZrx (void);
+extern int AdfmZsW (void);
+extern int AdfmZt6 (void);
+extern int Adfn9rx (void);
+extern int Adfn9sW (void);
+
+/* GNU hash 0xfffffffe.  */
+extern int glidpi (void);
+extern int glidqH (void);
+extern int glieOi (void);
+extern int gliePH (void);
+extern int gljCpi (void);
+
+/* GNU hash 0xffffffff.  */
+extern int glidpj (void);
+extern int glidqI (void);
+extern int glieOj (void);
+extern int gliePI (void);
+extern int gljCpj (void);
+
+
+int
+do_test (void)
+{
+  TEST_COMPARE (foo (), 1);
+  TEST_COMPARE (Hxxxynpfoo (), 2);
+  TEST_COMPARE (HxxxynpHxxxynpfoo (), 3);
+  TEST_COMPARE (HxxxynpHxxxynpHxxxynpfoo (), 4);
+  TEST_COMPARE (HxxxynpHxxxynpHxxxynpHxxxynpfoo (), 5);
+  TEST_COMPARE (gliinmgliinmgliinmgliinmbar (), 6);
+  TEST_COMPARE (gliinmgliinmgliinmbar (), 7);
+  TEST_COMPARE (gliinmgliinmbar (), 8);
+  TEST_COMPARE (gliinmbar (), 9);
+  TEST_COMPARE (bar (), 10);
+  TEST_COMPARE (Hxxxynp (), 11);
+  TEST_COMPARE (HxxxypP (), 12);
+  TEST_COMPARE (Hxxyinp (), 13);
+  TEST_COMPARE (HxxyipP (), 14);
+  TEST_COMPARE (HxxykNp (), 15);
+  TEST_COMPARE (Hxxxyoa (), 16);
+  TEST_COMPARE (HxxxypQ (), 17);
+  TEST_COMPARE (HxxxyqA (), 18);
+  TEST_COMPARE (HxxxzaA (), 19);
+  TEST_COMPARE (Hxxxz_a (), 20);
+  TEST_COMPARE (Hxxxyob (), 21);
+  TEST_COMPARE (HxxxypR (), 22);
+  TEST_COMPARE (HxxxyqB (), 23);
+  TEST_COMPARE (HxxxzaB (), 24);
+  TEST_COMPARE (Hxxxz_b (), 25);
+  TEST_COMPARE (glidpk (), 26);
+  TEST_COMPARE (glidqJ (), 27);
+  TEST_COMPARE (glieOk (), 28);
+  TEST_COMPARE (gliePJ (), 29);
+  TEST_COMPARE (gljCpk (), 30);
+  TEST_COMPARE (glidpl (), 31);
+  TEST_COMPARE (glidqK (), 32);
+  TEST_COMPARE (glieOl (), 33);
+  TEST_COMPARE (gliePK (), 34);
+  TEST_COMPARE (gljCpl (), 35);
+  TEST_COMPARE (glidpm (), 36);
+  TEST_COMPARE (glidqL (), 37);
+  TEST_COMPARE (glieOm (), 38);
+  TEST_COMPARE (gliePL (), 39);
+  TEST_COMPARE (gljCpm (), 40);
+  TEST_COMPARE (AdfmZru (), 41);
+  TEST_COMPARE (AdfmZsT (), 42);
+  TEST_COMPARE (AdfmZt3 (), 43);
+  TEST_COMPARE (Adfn9ru (), 44);
+  TEST_COMPARE (Adfn9sT (), 45);
+  TEST_COMPARE (AdfmZrv (), 46);
+  TEST_COMPARE (AdfmZsU (), 47);
+  TEST_COMPARE (AdfmZt4 (), 48);
+  TEST_COMPARE (Adfn9rv (), 49);
+  TEST_COMPARE (Adfn9sU (), 50);
+  TEST_COMPARE (AdfmZrw (), 51);
+  TEST_COMPARE (AdfmZsV (), 52);
+  TEST_COMPARE (AdfmZt5 (), 53);
+  TEST_COMPARE (Adfn9rw (), 54);
+  TEST_COMPARE (Adfn9sV (), 55);
+  TEST_COMPARE (AdfmZrx (), 56);
+  TEST_COMPARE (AdfmZsW (), 57);
+  TEST_COMPARE (AdfmZt6 (), 58);
+  TEST_COMPARE (Adfn9rx (), 59);
+  TEST_COMPARE (Adfn9sW (), 60);
+  TEST_COMPARE (glidpi (), 61);
+  TEST_COMPARE (glidqH (), 62);
+  TEST_COMPARE (glieOi (), 63);
+  TEST_COMPARE (gliePH (), 64);
+  TEST_COMPARE (gljCpi (), 65);
+  TEST_COMPARE (glidpj (), 66);
+  TEST_COMPARE (glidqI (), 67);
+  TEST_COMPARE (glieOj (), 68);
+  TEST_COMPARE (gliePI (), 69);
+  TEST_COMPARE (gljCpj (), 70);
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-hash-collision2-gnu.c b/elf/tst-hash-collision2-gnu.c
new file mode 100644
index 0000000000..92f0862e91
--- /dev/null
+++ b/elf/tst-hash-collision2-gnu.c
@@ -0,0 +1 @@
+#include "tst-hash-collision1.c"
diff --git a/elf/tst-hash-collision2-mod1-gnu.c b/elf/tst-hash-collision2-mod1-gnu.c
new file mode 100644
index 0000000000..9aa5cc1477
--- /dev/null
+++ b/elf/tst-hash-collision2-mod1-gnu.c
@@ -0,0 +1 @@
+#include "tst-hash-collision2-mod1.c"
diff --git a/elf/tst-hash-collision2-mod1-sysv.c b/elf/tst-hash-collision2-mod1-sysv.c
new file mode 100644
index 0000000000..9aa5cc1477
--- /dev/null
+++ b/elf/tst-hash-collision2-mod1-sysv.c
@@ -0,0 +1 @@
+#include "tst-hash-collision2-mod1.c"
diff --git a/elf/tst-hash-collision2-mod1.c b/elf/tst-hash-collision2-mod1.c
new file mode 100644
index 0000000000..6adf75eb35
--- /dev/null
+++ b/elf/tst-hash-collision2-mod1.c
@@ -0,0 +1,280 @@
+/* Test ELF hash collisions: shared object 1.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+
+/* Names with hash collisions for classic ELF hash.  */
+
+int
+foo (void)
+{
+  return 1;
+}
+
+int
+Hxxxynpfoo (void)
+{
+  return 2;
+}
+
+int
+HxxxynpHxxxynpfoo (void)
+{
+  return 3;
+}
+
+
+/* Names with hash collisions for GNU hash.  */
+
+int
+bar (void)
+{
+  return 10;
+}
+
+int
+gliinmbar (void)
+{
+  return 9;
+}
+
+int
+gliinmgliinmbar (void)
+{
+  return 8;
+}
+
+
+/* Names with specific hash values for each hash (see
+   tst-hash-collision1.c for details).  */
+
+int
+Hxxxynp (void)
+{
+  return 11;
+}
+
+int
+HxxxypP (void)
+{
+  return 12;
+}
+
+int
+Hxxyinp (void)
+{
+  return 13;
+}
+
+int
+Hxxxyoa (void)
+{
+  return 16;
+}
+
+int
+HxxxypQ (void)
+{
+  return 17;
+}
+
+int
+HxxxyqA (void)
+{
+  return 18;
+}
+
+int
+Hxxxyob (void)
+{
+  return 21;
+}
+
+int
+HxxxypR (void)
+{
+  return 22;
+}
+
+int
+HxxxyqB (void)
+{
+  return 23;
+}
+
+int
+glidpk (void)
+{
+  return 26;
+}
+
+int
+glidqJ (void)
+{
+  return 27;
+}
+
+int
+glieOk (void)
+{
+  return 28;
+}
+
+int
+glidpl (void)
+{
+  return 31;
+}
+
+int
+glidqK (void)
+{
+  return 32;
+}
+
+int
+glieOl (void)
+{
+  return 33;
+}
+
+int
+glidpm (void)
+{
+  return 36;
+}
+
+int
+glidqL (void)
+{
+  return 37;
+}
+
+int
+glieOm (void)
+{
+  return 38;
+}
+
+int
+AdfmZru (void)
+{
+  return 41;
+}
+
+int
+AdfmZsT (void)
+{
+  return 42;
+}
+
+int
+AdfmZt3 (void)
+{
+  return 43;
+}
+
+int
+AdfmZrv (void)
+{
+  return 46;
+}
+
+int
+AdfmZsU (void)
+{
+  return 47;
+}
+
+int
+AdfmZt4 (void)
+{
+  return 48;
+}
+
+int
+AdfmZrw (void)
+{
+  return 51;
+}
+
+int
+AdfmZsV (void)
+{
+  return 52;
+}
+
+int
+AdfmZt5 (void)
+{
+  return 53;
+}
+
+int
+AdfmZrx (void)
+{
+  return 56;
+}
+
+int
+AdfmZsW (void)
+{
+  return 57;
+}
+
+int
+AdfmZt6 (void)
+{
+  return 58;
+}
+
+int
+glidpi (void)
+{
+  return 61;
+}
+
+int
+glidqH (void)
+{
+  return 62;
+}
+
+int
+glieOi (void)
+{
+  return 63;
+}
+
+int
+glidpj (void)
+{
+  return 66;
+}
+
+int
+glidqI (void)
+{
+  return 67;
+}
+
+int
+glieOj (void)
+{
+  return 68;
+}
diff --git a/elf/tst-hash-collision2-mod2-gnu.c b/elf/tst-hash-collision2-mod2-gnu.c
new file mode 100644
index 0000000000..39579f6736
--- /dev/null
+++ b/elf/tst-hash-collision2-mod2-gnu.c
@@ -0,0 +1 @@
+#include "tst-hash-collision2-mod2.c"
diff --git a/elf/tst-hash-collision2-mod2-sysv.c b/elf/tst-hash-collision2-mod2-sysv.c
new file mode 100644
index 0000000000..39579f6736
--- /dev/null
+++ b/elf/tst-hash-collision2-mod2-sysv.c
@@ -0,0 +1 @@
+#include "tst-hash-collision2-mod2.c"
diff --git a/elf/tst-hash-collision2-mod2.c b/elf/tst-hash-collision2-mod2.c
new file mode 100644
index 0000000000..e0bb90e60b
--- /dev/null
+++ b/elf/tst-hash-collision2-mod2.c
@@ -0,0 +1,196 @@
+/* Test ELF hash collisions: shared object 2.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+
+/* Names with hash collisions for classic ELF hash.  */
+
+int
+HxxxynpHxxxynpHxxxynpfoo (void)
+{
+  return 4;
+}
+
+int
+HxxxynpHxxxynpHxxxynpHxxxynpfoo (void)
+{
+  return 5;
+}
+
+
+/* Names with hash collisions for GNU hash.  */
+
+int
+gliinmgliinmgliinmbar (void)
+{
+  return 7;
+}
+
+int
+gliinmgliinmgliinmgliinmbar (void)
+{
+  return 6;
+}
+
+
+/* Names with specific hash values for each hash (see
+   tst-hash-collision1.c for details).  */
+
+int
+HxxyipP (void)
+{
+  return 14;
+}
+
+int
+HxxykNp (void)
+{
+  return 15;
+}
+
+int
+HxxxzaA (void)
+{
+  return 19;
+}
+
+int
+Hxxxz_a (void)
+{
+  return 20;
+}
+
+int
+HxxxzaB (void)
+{
+  return 24;
+}
+
+int
+Hxxxz_b (void)
+{
+  return 25;
+}
+
+int
+gliePJ (void)
+{
+  return 29;
+}
+
+int
+gljCpk (void)
+{
+  return 30;
+}
+
+int
+gliePK (void)
+{
+  return 34;
+}
+
+int
+gljCpl (void)
+{
+  return 35;
+}
+
+int
+gliePL (void)
+{
+  return 39;
+}
+
+int
+gljCpm (void)
+{
+  return 40;
+}
+
+int
+Adfn9ru (void)
+{
+  return 44;
+}
+
+int
+Adfn9sT (void)
+{
+  return 45;
+}
+
+int
+Adfn9rv (void)
+{
+  return 49;
+}
+
+int
+Adfn9sU (void)
+{
+  return 50;
+}
+
+int
+Adfn9rw (void)
+{
+  return 54;
+}
+
+int
+Adfn9sV (void)
+{
+  return 55;
+}
+
+int
+Adfn9rx (void)
+{
+  return 59;
+}
+
+int
+Adfn9sW (void)
+{
+  return 60;
+}
+
+int
+gliePH (void)
+{
+  return 64;
+}
+
+int
+gljCpi (void)
+{
+  return 65;
+}
+
+int
+gliePI (void)
+{
+  return 69;
+}
+
+int
+gljCpj (void)
+{
+  return 70;
+}
diff --git a/elf/tst-hash-collision2-sysv.c b/elf/tst-hash-collision2-sysv.c
new file mode 100644
index 0000000000..92f0862e91
--- /dev/null
+++ b/elf/tst-hash-collision2-sysv.c
@@ -0,0 +1 @@
+#include "tst-hash-collision1.c"
diff --git a/elf/tst-hash-collision2.c b/elf/tst-hash-collision2.c
new file mode 100644
index 0000000000..92f0862e91
--- /dev/null
+++ b/elf/tst-hash-collision2.c
@@ -0,0 +1 @@
+#include "tst-hash-collision1.c"
diff mbox series

Patch

diff --git a/elf/Makefile b/elf/Makefile
index 9cfe738919..9666107dc7 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -434,6 +434,9 @@  tests += \
   tst-global1 \
   tst-global2 \
   tst-gnu2-tls2 \
+  tst-hash-collision \
+  tst-hash-collision-gnu \
+  tst-hash-collision-sysv \
   tst-initfinilazyfail \
   tst-initorder \
   tst-initorder2 \
@@ -888,6 +891,9 @@  modules-names += \
   tst-gnu2-tls2mod0 \
   tst-gnu2-tls2mod1 \
   tst-gnu2-tls2mod2 \
+  tst-hash-collision-mod \
+  tst-hash-collision-mod-gnu \
+  tst-hash-collision-mod-sysv \
   tst-initlazyfailmod \
   tst-initorder2a \
   tst-initorder2b \
@@ -3165,3 +3171,10 @@  $(objpfx)tst-dlopen-recursemod1.so: $(objpfx)tst-dlopen-recursemod2.so
 tst-dlopen-auditdup-ENV = LD_AUDIT=$(objpfx)tst-dlopen-auditdup-auditmod.so
 $(objpfx)tst-dlopen-auditdup.out: \
   $(objpfx)tst-dlopen-auditdupmod.so $(objpfx)tst-dlopen-auditdup-auditmod.so
+
+LDFLAGS-tst-hash-collision-mod.so = -Wl,--hash-style=both
+$(objpfx)tst-hash-collision: $(objpfx)tst-hash-collision-mod.so
+LDFLAGS-tst-hash-collision-mod-gnu.so = -Wl,--hash-style=gnu
+$(objpfx)tst-hash-collision-gnu: $(objpfx)tst-hash-collision-mod-gnu.so
+LDFLAGS-tst-hash-collision-mod-sysv.so = -Wl,--hash-style=sysv
+$(objpfx)tst-hash-collision-sysv: $(objpfx)tst-hash-collision-mod-sysv.so
diff --git a/elf/tst-hash-collision-gnu.c b/elf/tst-hash-collision-gnu.c
new file mode 100644
index 0000000000..f265b33e52
--- /dev/null
+++ b/elf/tst-hash-collision-gnu.c
@@ -0,0 +1 @@ 
+#include "tst-hash-collision.c"
diff --git a/elf/tst-hash-collision-mod-gnu.c b/elf/tst-hash-collision-mod-gnu.c
new file mode 100644
index 0000000000..db40bc5325
--- /dev/null
+++ b/elf/tst-hash-collision-mod-gnu.c
@@ -0,0 +1 @@ 
+#include "tst-hash-collision-mod.c"
diff --git a/elf/tst-hash-collision-mod-sysv.c b/elf/tst-hash-collision-mod-sysv.c
new file mode 100644
index 0000000000..db40bc5325
--- /dev/null
+++ b/elf/tst-hash-collision-mod-sysv.c
@@ -0,0 +1 @@ 
+#include "tst-hash-collision-mod.c"
diff --git a/elf/tst-hash-collision-mod.c b/elf/tst-hash-collision-mod.c
new file mode 100644
index 0000000000..9bf738f3d1
--- /dev/null
+++ b/elf/tst-hash-collision-mod.c
@@ -0,0 +1,84 @@ 
+/* Test ELF hash collisions: shared object.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+
+/* Names with hash collisions for classic ELF hash.  */
+
+int
+foo (void)
+{
+  return 1;
+}
+
+int
+Hxxxynpfoo (void)
+{
+  return 2;
+}
+
+int
+HxxxynpHxxxynpfoo (void)
+{
+  return 3;
+}
+
+int
+HxxxynpHxxxynpHxxxynpfoo (void)
+{
+  return 4;
+}
+
+int
+HxxxynpHxxxynpHxxxynpHxxxynpfoo (void)
+{
+  return 5;
+}
+
+
+/* Names with hash collisions for GNU hash.  */
+
+int
+bar (void)
+{
+  return 10;
+}
+
+int
+gliinmbar (void)
+{
+  return 9;
+}
+
+int
+gliinmgliinmbar (void)
+{
+  return 8;
+}
+
+int
+gliinmgliinmgliinmbar (void)
+{
+  return 7;
+}
+
+int
+gliinmgliinmgliinmgliinmbar (void)
+{
+  return 6;
+}
diff --git a/elf/tst-hash-collision-sysv.c b/elf/tst-hash-collision-sysv.c
new file mode 100644
index 0000000000..f265b33e52
--- /dev/null
+++ b/elf/tst-hash-collision-sysv.c
@@ -0,0 +1 @@ 
+#include "tst-hash-collision.c"
diff --git a/elf/tst-hash-collision.c b/elf/tst-hash-collision.c
new file mode 100644
index 0000000000..d46cc7dfa4
--- /dev/null
+++ b/elf/tst-hash-collision.c
@@ -0,0 +1,51 @@ 
+/* Test ELF hash collisions.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+
+/* Names with hash collisions for classic ELF hash.  */
+extern int foo (void);
+extern int Hxxxynpfoo (void);
+extern int HxxxynpHxxxynpfoo (void);
+extern int HxxxynpHxxxynpHxxxynpfoo (void);
+extern int HxxxynpHxxxynpHxxxynpHxxxynpfoo (void);
+
+/* Names with hash collisions for GNU hash.  */
+extern int bar (void);
+extern int gliinmbar (void);
+extern int gliinmgliinmbar (void);
+extern int gliinmgliinmgliinmbar (void);
+extern int gliinmgliinmgliinmgliinmbar (void);
+
+int
+do_test (void)
+{
+  TEST_COMPARE (foo (), 1);
+  TEST_COMPARE (Hxxxynpfoo (), 2);
+  TEST_COMPARE (HxxxynpHxxxynpfoo (), 3);
+  TEST_COMPARE (HxxxynpHxxxynpHxxxynpfoo (), 4);
+  TEST_COMPARE (HxxxynpHxxxynpHxxxynpHxxxynpfoo (), 5);
+  TEST_COMPARE (gliinmgliinmgliinmgliinmbar (), 6);
+  TEST_COMPARE (gliinmgliinmgliinmbar (), 7);
+  TEST_COMPARE (gliinmgliinmbar (), 8);
+  TEST_COMPARE (gliinmbar (), 9);
+  TEST_COMPARE (bar (), 10);
+  return 0;
+}
+
+#include <support/test-driver.c>