commit 4da900cbb88bb5bb53246dc96a550d16f52b3481 (tree)
parent be50c806b82d78ff6bc836a972ba1a837677a70b
Author: Motiejus <motiejus@jakstys.lt>
Date: Tue, 3 Mar 2026 08:43:16 +0000
stage0: fix enum_literal to store string index, not djb2 hash
zirEnumLiteral was storing simpleStringHash(name) — a djb2 hash — as the
enum_literal IP key field. Upstream Zig stores a NullTerminatedString index
(getOrPutString). All three read sites treat the field as a string table
index and dereference it into ip->string_bytes, so the hash value caused
silent out-of-bounds reads whenever enum_literal coercion, callconv, or
signedness parsing were exercised.
Replace simpleStringHash with ipGetOrPutString, matching upstream exactly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat:
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -17,16 +17,6 @@
} \
} while (0)
-// Simple djb2 hash for enum literal names.
-static uint32_t simpleStringHash(const char* s) {
- uint32_t h = 5381;
- while (*s) {
- h = h * 33 + (uint8_t)*s;
- s++;
- }
- return h;
-}
-
#define SEMA_AIR_INITIAL_CAP 256
#define SEMA_AIR_EXTRA_INITIAL_CAP 256
#define INST_MAP_INITIAL_CAP 32
@@ -9976,7 +9966,7 @@ static AirInstRef zirEnumLiteral(Sema* sema, uint32_t inst) {
InternPoolKey key;
memset(&key, 0, sizeof(key));
key.tag = IP_KEY_ENUM_LITERAL;
- key.data.enum_literal = simpleStringHash(name);
+ key.data.enum_literal = ipGetOrPutString(sema->ip, name);
return AIR_REF_FROM_IP(ipIntern(sema->ip, key));
}