Bug 14038 – [REG2.067a] Non-mutable AA initialization segfaults in runtime
Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2015-01-24T22:42:00Z
Last change time
2015-01-25T00:34:25Z
Keywords
pull, wrong-code
Assigned to
nobody
Creator
k.hara.pg
Comments
Comment #0 by k.hara.pg — 2015-01-24T22:42:48Z
From: http://forum.dlang.org/thread/[email protected]
With git-head, this code segfaults in runtime.
static immutable words = [ `zero`, `one`, `two` ];
static immutable ubyte[string] wordsAA;
static this()
{
foreach (ubyte i, e; words) { wordsAA[e] = i; }
}
The regression had introduced by the combination of:
https://github.com/D-Programming-Language/dmd/pull/4159https://github.com/D-Programming-Language/druntime/pull/1037
The core issue is in dmd e2ir.c around lien 4570.
void visit(IndexExp *ie)
{
...
Type *t1 = ie->e1->type->toBasetype();
if (t1->ty == Taarray)
{
// set to:
// *aaGetY(aa, aati, valuesize, &key);
// or
// *aaGetRvalueX(aa, keyti, valuesize, &key);
TypeAArray *taa = (TypeAArray *)t1;
...
elem* ti;
if (ie->modifiable)
{
n1 = el_una(OPaddr, TYnptr, n1);
s = aaGetSymbol(taa, "GetY", 1);
ti = toElem(getInternalTypeInfo(taa, NULL), irs); // <---
}
else
{
s = aaGetSymbol(taa, "GetRvalueX", 1);
ti = toElem(getInternalTypeInfo(taa->index, NULL), irs);
}
//printf("taa->index = %s\n", taa->index->toChars());
//printf("ti:\n"); elem_print(ti);
elem* ep = el_params(n2, valuesize, ti, n1, NULL);
If ie->modifiable (the IndexExp appears in left hand side of an assignment expression), typeid(taa) is set to the 2nd argument of _aaGetY(). But, if taa is not mutable, it will be a TypeInfo_Const reference that points TypeInfo_AssociativeArray.
On the other hand, the _aaGetY() function is defined as:
void* _aaGetY(AA* aa, const TypeInfo_AssociativeArray ti, in size_t valuesize, in void* pkey)
{
if (aa.impl is null)
{
aa.impl = new Impl();
aa.impl.buckets = aa.impl.binit[];
aa.impl.firstUsedBucket = aa.impl.buckets.length;
aa.impl._keyti = cast() ti.key; // <-----
}
return _aaGetImpl(aa, ti.key, valuesize, pkey);
}
And ti does not point an instance of TypeInfo_AssociativeArray, so will cause segfault at the ti.key access.
Comment #1 by k.hara.pg — 2015-01-24T22:45:52Z
More better test case:
class C
{
immutable ubyte[string] wordsAA;
this()
{
wordsAA["zero"] = 0; // segfaults
}
}
void main()
{
auto c = new C();
}
The original code is initializing immutable AA inside foreach loop. I think it would be a multiple variable initialization and essentially should be disallowed.
Comment #2 by k.hara.pg — 2015-01-24T22:50:01Z
(In reply to Kenji Hara from comment #1)
More close to the original:
static immutable ubyte[string] wordsAA;
static this()
{
wordsAA["zero"] = 0;
}
void main() {}