On 7/28/23 11:15 AM, IchorDev wrote:
On Friday, 28 July 2023 at 11:15:31 UTC, Steven Schveighoffer wrote:
All `__gshared` does is give you storage that is accessible from all threads,

"All __gshared does is give you [a live bomb, ready to go off at any moment]"
!!

It seems like it's not __gshared at all, but misusing malloc with GC pointers.


On Friday, 28 July 2023 at 14:10:16 UTC, Kagamin wrote:
Your error is using allocating the object with malloc. Since gc doesn't see your AA, the AA is freed and you get UAF.

Friend, I think you nailed it. After adding this I haven't been able to reproduce the segfault again:
```d
this(long n){
     (){
         cache = new typeof(cache);
         assert(cache);
         import core.memory;
         core.memory.GC.addRoot(cast(void*)cache);
     }();
     // ...
```
It did always happen at random, so perhaps I haven't spent enough time testing it yet, but I've gone far longer without it segfaulting than ever before.

This is the wrong approach, it's the allocating call that should add the root (actually a range).

For instance, the mutex is not added, that might be collected. Or if you add more GC-pointing things into the class, that could be a problem.

What I'd do is:

```d
T alloc(T, A...)(auto ref A args){
    enum classSize = __traits(classInstanceSize, T);
    void* mem = core.stdc.stdlib.malloc(classSize);
    assert(mem !is null, "Out of memory");
    core.memory.GC.addRange(mem[0 .. classSize]);
    scope(failure) {
       core.memory.GC.removeRange(mem[0 .. classSize]);
       core.stdc.stdlib.free(mem);
    }
    T inst = cast(T)mem;
    inst.emplace(__traits(parameters));
    return inst;
}
```

And of course, a `dealloc` that removes the range should also be added.

-Steve

Reply via email to