Stable name allocation causes heap corruption when GC is triggered in the primop
The error is originally reported in #15241, and is caught by the test memo001
when run with -debug
(which only happens in sanity way currently).
Here's the problem. mkStableName# is defined like this:
stg_makeStableNamezh ( P_ obj )
{
W_ index, sn_obj;
(index) = ccall lookupStableName(obj "ptr");
/* Is there already a StableName for this heap object?
* stable_name_table is a pointer to an array of snEntry structs.
*/
if ( snEntry_sn_obj(W_[stable_name_table] + index*SIZEOF_snEntry) == NULL ) {
ALLOC_PRIM (SIZEOF_StgStableName); <------------ PROBLEM HERE ----------
sn_obj = Hp - SIZEOF_StgStableName + WDS(1);
SET_HDR(sn_obj, stg_STABLE_NAME_info, CCCS);
StgStableName_sn(sn_obj) = index;
snEntry_sn_obj(W_[stable_name_table] + index*SIZEOF_snEntry) = sn_obj;
} else {
sn_obj = snEntry_sn_obj(W_[stable_name_table] + index*SIZEOF_snEntry);
}
return (sn_obj);
}
There's a problem in the annotated line: if we allocate a snEntry
in the
stable name table, but run out of heap to actually allocate the StgStableName
we call GC with incorrect snEntry
contents. As a reminder, this is snEntry
:
typedef struct {
StgPtr addr; // Haskell object when entry is in use, next free
// entry (NULL when this is the last free entry)
// otherwise. May be NULL temporarily during GC (when
// pointee dies).
StgPtr old; // Old Haskell object, used during GC
StgClosure *sn_obj; // The StableName object, or NULL when the entry is
// free
} snEntry;
In summary, sn_obj == NULL
means the entry is free. When we trigger the GC
after allocating the snEntry
but before allocating the StgStableName
, we end
up calling the GC with sn_obj == NULL
even though the snEntry
is not
actually free. In particular, the addr
field should be updated by
gcStableNameTable
, but it's currently not because gcStableNameTable
sees
sn_obj
as NULL and skips the entry.
The is caught by memo001 when run with -debug.
I already have a fix and will submit a patch soon.
Trac metadata
Trac field | Value |
---|---|
Version | 8.7 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | highest |
Resolution | Unresolved |
Component | Runtime System |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |