t_hash.c revision 1.1.6.2 1 1.1.6.2 sborrill /* $NetBSD: t_hash.c,v 1.1.6.2 2023/08/11 12:13:10 sborrill Exp $ */
2 1.1.6.2 sborrill
3 1.1.6.2 sborrill /*-
4 1.1.6.2 sborrill * Copyright (c) 2023 The NetBSD Foundation, Inc.
5 1.1.6.2 sborrill * All rights reserved.
6 1.1.6.2 sborrill *
7 1.1.6.2 sborrill * Redistribution and use in source and binary forms, with or without
8 1.1.6.2 sborrill * modification, are permitted provided that the following conditions
9 1.1.6.2 sborrill * are met:
10 1.1.6.2 sborrill * 1. Redistributions of source code must retain the above copyright
11 1.1.6.2 sborrill * notice, this list of conditions and the following disclaimer.
12 1.1.6.2 sborrill * 2. Redistributions in binary form must reproduce the above copyright
13 1.1.6.2 sborrill * notice, this list of conditions and the following disclaimer in the
14 1.1.6.2 sborrill * documentation and/or other materials provided with the distribution.
15 1.1.6.2 sborrill *
16 1.1.6.2 sborrill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 1.1.6.2 sborrill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 1.1.6.2 sborrill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.1.6.2 sborrill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 1.1.6.2 sborrill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 1.1.6.2 sborrill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 1.1.6.2 sborrill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.1.6.2 sborrill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 1.1.6.2 sborrill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 1.1.6.2 sborrill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 1.1.6.2 sborrill * POSSIBILITY OF SUCH DAMAGE.
27 1.1.6.2 sborrill */
28 1.1.6.2 sborrill
29 1.1.6.2 sborrill #include <sys/cdefs.h>
30 1.1.6.2 sborrill
31 1.1.6.2 sborrill #include <atf-c.h>
32 1.1.6.2 sborrill #include <stdint.h>
33 1.1.6.2 sborrill
34 1.1.6.2 sborrill #include "hash.h"
35 1.1.6.2 sborrill
36 1.1.6.2 sborrill /* known-answer tests */
37 1.1.6.2 sborrill struct kat {
38 1.1.6.2 sborrill const char *in;
39 1.1.6.2 sborrill unsigned long long out;
40 1.1.6.2 sborrill };
41 1.1.6.2 sborrill
42 1.1.6.2 sborrill /*
43 1.1.6.2 sborrill * From the SysV spec, with uint64_t instead of unsigned long to
44 1.1.6.2 sborrill * illustrate the problem on all systems, not just LP64 ones.
45 1.1.6.2 sborrill *
46 1.1.6.2 sborrill * https://www.sco.com/developers/devspecs/gabi41.pdf#page=95
47 1.1.6.2 sborrill */
48 1.1.6.2 sborrill static uint64_t
49 1.1.6.2 sborrill sysv_broken_hash(const char *name)
50 1.1.6.2 sborrill {
51 1.1.6.2 sborrill uint64_t h = 0, g;
52 1.1.6.2 sborrill
53 1.1.6.2 sborrill while (*name) {
54 1.1.6.2 sborrill h = (h << 4) + *name++;
55 1.1.6.2 sborrill if ((g = h & 0xf0000000) != 0)
56 1.1.6.2 sborrill h ^= g >> 24;
57 1.1.6.2 sborrill h &= ~g;
58 1.1.6.2 sborrill }
59 1.1.6.2 sborrill
60 1.1.6.2 sborrill return h;
61 1.1.6.2 sborrill }
62 1.1.6.2 sborrill
63 1.1.6.2 sborrill ATF_TC(sysv);
64 1.1.6.2 sborrill ATF_TC_HEAD(sysv, tc)
65 1.1.6.2 sborrill {
66 1.1.6.2 sborrill atf_tc_set_md_var(tc, "descr", "SysV hash (32-bit)");
67 1.1.6.2 sborrill }
68 1.1.6.2 sborrill ATF_TC_BODY(sysv, tc)
69 1.1.6.2 sborrill {
70 1.1.6.2 sborrill static const struct kat kat[] = {
71 1.1.6.2 sborrill { "", 0x00000000 },
72 1.1.6.2 sborrill { "a", 0x00000061 },
73 1.1.6.2 sborrill { "aa", 0x00000671 },
74 1.1.6.2 sborrill { "aaa", 0x00006771 },
75 1.1.6.2 sborrill { "aaaa", 0x00067771 },
76 1.1.6.2 sborrill { "aaaaa", 0x00677771 },
77 1.1.6.2 sborrill { "aaaaaa", 0x06777771 },
78 1.1.6.2 sborrill { "aaaaaaa", 0x07777711 },
79 1.1.6.2 sborrill { "aaaaaaaa", 0x07777101 },
80 1.1.6.2 sborrill { "aaaaaaaaa", 0x07771001 },
81 1.1.6.2 sborrill { "ab", 0x00000672 },
82 1.1.6.2 sborrill { "abc", 0x00006783 },
83 1.1.6.2 sborrill { "abcd", 0x00067894 },
84 1.1.6.2 sborrill { "abcde", 0x006789a5 },
85 1.1.6.2 sborrill { "abcdef", 0x06789ab6 },
86 1.1.6.2 sborrill { "abcdefg", 0x0789aba7 },
87 1.1.6.2 sborrill { "abcdefgh", 0x089abaa8 },
88 1.1.6.2 sborrill { "abcdefghi", 0x09abaa69 },
89 1.1.6.2 sborrill /* https://maskray.me/blog/2023-04-12-elf-hash-function */
90 1.1.6.2 sborrill { "Z", 0x0000005a },
91 1.1.6.2 sborrill { "ZZ", 0x000005fa },
92 1.1.6.2 sborrill { "ZZZ", 0x00005ffa },
93 1.1.6.2 sborrill { "ZZZZ", 0x0005fffa },
94 1.1.6.2 sborrill { "ZZZZZ", 0x005ffffa },
95 1.1.6.2 sborrill { "ZZZZZW", 0x05fffff7 },
96 1.1.6.2 sborrill { "ZZZZZW9", 0x0ffffff9 },
97 1.1.6.2 sborrill { "ZZZZZW9p", 0x00000000 },
98 1.1.6.2 sborrill { "pneumonoultramicroscopicsilicovolcanoconiosis",
99 1.1.6.2 sborrill 0x051706b3 },
100 1.1.6.2 sborrill };
101 1.1.6.2 sborrill unsigned i;
102 1.1.6.2 sborrill
103 1.1.6.2 sborrill for (i = 0; i < __arraycount(kat); i++) {
104 1.1.6.2 sborrill unsigned long long h = _rtld_elf_hash(kat[i].in);
105 1.1.6.2 sborrill
106 1.1.6.2 sborrill ATF_CHECK_EQ_MSG(h, kat[i].out,
107 1.1.6.2 sborrill "[%u] _rtld_elf_hash(\"%s\") = 0x%08llx != 0x%08llx",
108 1.1.6.2 sborrill i, kat[i].in, h, kat[i].out);
109 1.1.6.2 sborrill }
110 1.1.6.2 sborrill }
111 1.1.6.2 sborrill
112 1.1.6.2 sborrill ATF_TC(sysv_broken);
113 1.1.6.2 sborrill ATF_TC_HEAD(sysv_broken, tc)
114 1.1.6.2 sborrill {
115 1.1.6.2 sborrill atf_tc_set_md_var(tc, "descr",
116 1.1.6.2 sborrill "SysV hash (broken with 64-bit unsigned long)");
117 1.1.6.2 sborrill }
118 1.1.6.2 sborrill ATF_TC_BODY(sysv_broken, tc)
119 1.1.6.2 sborrill {
120 1.1.6.2 sborrill static const struct kat kat[] = {
121 1.1.6.2 sborrill { "", 0x00000000 },
122 1.1.6.2 sborrill { "a", 0x00000061 },
123 1.1.6.2 sborrill { "aa", 0x00000671 },
124 1.1.6.2 sborrill { "aaa", 0x00006771 },
125 1.1.6.2 sborrill { "aaaa", 0x00067771 },
126 1.1.6.2 sborrill { "aaaaa", 0x00677771 },
127 1.1.6.2 sborrill { "aaaaaa", 0x06777771 },
128 1.1.6.2 sborrill { "aaaaaaa", 0x07777711 },
129 1.1.6.2 sborrill { "aaaaaaaa", 0x07777101 },
130 1.1.6.2 sborrill { "aaaaaaaaa", 0x07771001 },
131 1.1.6.2 sborrill { "ab", 0x00000672 },
132 1.1.6.2 sborrill { "abc", 0x00006783 },
133 1.1.6.2 sborrill { "abcd", 0x00067894 },
134 1.1.6.2 sborrill { "abcde", 0x006789a5 },
135 1.1.6.2 sborrill { "abcdef", 0x06789ab6 },
136 1.1.6.2 sborrill { "abcdefg", 0x0789aba7 },
137 1.1.6.2 sborrill { "abcdefgh", 0x089abaa8 },
138 1.1.6.2 sborrill { "abcdefghi", 0x09abaa69 },
139 1.1.6.2 sborrill /* https://maskray.me/blog/2023-04-12-elf-hash-function */
140 1.1.6.2 sborrill { "Z", 0x0000005a },
141 1.1.6.2 sborrill { "ZZ", 0x000005fa },
142 1.1.6.2 sborrill { "ZZZ", 0x00005ffa },
143 1.1.6.2 sborrill { "ZZZZ", 0x0005fffa },
144 1.1.6.2 sborrill { "ZZZZZ", 0x005ffffa },
145 1.1.6.2 sborrill { "ZZZZZW", 0x05fffff7 },
146 1.1.6.2 sborrill { "ZZZZZW9", 0x0ffffff9 },
147 1.1.6.2 sborrill { "ZZZZZW9p", 0x100000000 }, /* XXX */
148 1.1.6.2 sborrill { "pneumonoultramicroscopicsilicovolcanoconiosis",
149 1.1.6.2 sborrill 0x051706b3 },
150 1.1.6.2 sborrill };
151 1.1.6.2 sborrill unsigned i;
152 1.1.6.2 sborrill
153 1.1.6.2 sborrill for (i = 0; i < __arraycount(kat); i++) {
154 1.1.6.2 sborrill unsigned long long h = sysv_broken_hash(kat[i].in);
155 1.1.6.2 sborrill
156 1.1.6.2 sborrill ATF_CHECK_EQ_MSG(h, kat[i].out,
157 1.1.6.2 sborrill "[%u] sysv_broken_hash(\"%s\") = 0x%08llx != 0x%08llx",
158 1.1.6.2 sborrill i, kat[i].in, h, kat[i].out);
159 1.1.6.2 sborrill }
160 1.1.6.2 sborrill }
161 1.1.6.2 sborrill
162 1.1.6.2 sborrill ATF_TP_ADD_TCS(tp)
163 1.1.6.2 sborrill {
164 1.1.6.2 sborrill
165 1.1.6.2 sborrill ATF_TP_ADD_TC(tp, sysv);
166 1.1.6.2 sborrill ATF_TP_ADD_TC(tp, sysv_broken);
167 1.1.6.2 sborrill
168 1.1.6.2 sborrill return atf_no_error();
169 1.1.6.2 sborrill }
170