[GHC] #15906: Stable name allocation causes heap corruption when GC is triggered in the primop
GHC
ghc-devs at haskell.org
Fri Nov 16 11:52:26 UTC 2018
#15906: Stable name allocation causes heap corruption when GC is triggered in the
primop
-------------------------------------+-------------------------------------
Reporter: osa1 | Owner: (none)
Type: bug | Status: new
Priority: highest | Milestone: 8.6.3
Component: Runtime | Version: 8.7
System |
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: None/Unknown
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
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.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15906>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list