September 14, 2019
https://issues.dlang.org/show_bug.cgi?id=20214

          Issue ID: 20214
           Summary: GC: realloc can result in false pointers if address
                    doesn't change
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P1
         Component: druntime
          Assignee: nobody@puremagic.com
          Reporter: r.sagitario@gmx.de

If GC.realloc doesn't change the address of the allocation (either by shrinking or extending in place), the non-allocated area can contain false pointers:

import core.memory;
import core.stdc.stdio;

void main()
{
        // allocate from large pool
        auto o = GC.malloc(10);
        auto p = (cast(void**)GC.malloc(4096 * (void*).sizeof))[0 .. 4096];
        auto q = (cast(void**)GC.malloc(4096 * (void*).sizeof))[0 .. 4096];
        if (p.ptr + p.length is q.ptr)
        {
                q[] = o; // fill with pointers

                // shrink, unused area cleared?
                auto nq = (cast(void**)GC.realloc(q.ptr, 4000 *
(void*).sizeof))[0 .. 4000];
                assert(q.ptr is nq.ptr);
                assert(q.ptr[4095] !is o);

                GC.free(q.ptr);
                // expected to extend in place
                auto np = (cast(void**)GC.realloc(p.ptr, 4200 *
(void*).sizeof))[0 .. 4200];
                assert(p.ptr is np.ptr);
                assert(q.ptr[4200] !is o);
        }
        else
                printf("unexpected pointers %p and %p\n", p.ptr, q.ptr);
}

--