Bug 16199 – Looking up string-keyed AA with char[n] compiles but crashes at runtime

Status
RESOLVED
Resolution
WORKSFORME
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2016-06-23T16:17:21Z
Last change time
2022-11-09T21:44:44Z
Keywords
wrong-code
Assigned to
No Owner
Creator
hsteoh

Comments

Comment #0 by hsteoh — 2016-06-23T16:17:21Z
Code: ------ void main() { int[string] aa1; int[char[]] aa2; int[char[4]] aa3; aa1["aa_1"] = 123; aa2["aa_1"] = 234; aa3["aa_1"] = 345; char[4] key; key[] = "aa_1"; if (key in aa1) // CRASHES writeln("yes"); if (key in aa2) // CRASHES writeln("yes"); if (key in aa3) // OK writeln("yes"); } ------ The reason for this is that the compiler accepts char[4] as key for aa1 and aa2, but in _aaInX() (druntime/src/rt/aaA.d around l.404), keyti is the TypeInfo for string (i.e. immutable(char)[]) rather than the typeinfo for char[4] -- because that's the key type for the AA. However, pkey is pointing to char[4], not to a string, so the call to calcHash() will crash when it tries to interpret char[4] as immutable(char)[]. I've a hard time deciding whether the compiler is at fault or druntime, but decided it's the compiler's problem because druntime has no way of knowing what the original type of pkey is, except what is passed in the keyti parameter. The problem is that the incoming key type is different from the AA's key type, so druntime can't possibly do the right thing unless it takes two TypeInfo arguments. It's either that, or the compiler must reject using char[n] as key to a string-keyed AA. My recommendation is for the compiler to reject indexing a string-keyed AA with char[n], probably with a helpful error message to slice the char[n] first. Either that, or the compiler should implicitly emit the slicing operation for the char[n] so that pkey is of a compatible type.
Comment #1 by hsteoh — 2016-06-23T16:18:53Z
Note that writing `key[] in aa1` (with the []) works fine.
Comment #2 by hsteoh — 2016-06-23T16:32:24Z
Note that there's another latent bug here: looking up char[] in int[string] compiles (and works), but the incoming char[] should not implicitly convert to string, because the chars are mutable. However, the AA implementation receives keyti as the TypeInfo for string, i.e., immutable(char)[]. The current implementation, of course, doesn't rely on the immutability of the key, but conceivably it could, in which case it will break immutability when char[] is passed in. I don't know how to solve this within the current AA implementation framework -- it's very messy that the incoming key type can be different but (almost) compatible with the AA's key type. Since a few releases ago the compiler has forced an implicit const on AA key types, but still, that doesn't fully solve the problem, because you could construct a mutable key, e.g., char[], which implicitly converts to the key type const(char)[], but after you insert the key into the AA you can mutate the key via the char[]. This will break the AA, because the stored hash now doesn't match the key, so the inserted entry cannot be found by looking up the key.
Comment #3 by razvan.nitu1305 — 2022-11-09T15:09:45Z
Hi! I cannot reproduce the behavior described in the original bug report. If I compile the code, I get: test.d(15): Error: cannot implicitly convert expression `key` of type `char[4]` to `string` Which is for the first `in` expression. If I test for key.idup then everything works just fine. Should we close this issue?
Comment #4 by hsteoh — 2022-11-09T21:44:44Z
Seems the problem no longer happens on the latest dmd build. Closing.