[Issue 12417] `toStringz` is fundamentally broken

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Tue Mar 24 07:56:12 PDT 2015


https://issues.dlang.org/show_bug.cgi?id=12417

John Colvin <john.loughran.colvin at gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |john.loughran.colvin at gmail.
                   |                            |com

--- Comment #3 from John Colvin <john.loughran.colvin at gmail.com> ---
You mean something like this?

//D

extern(C) void foo(int* a);

void main()
{
    foo(new int);
}

//C

#include<stdlib.h>

void gc_collect();

// I solemnly swear this function does not
// hold any references to `a`
void foo(int* a)
{
    int** m = (int**)malloc(sizeof(int*));
    *m = a;
    a = 0;

    //Doesn't have to be explicit, could be from
    //another thread or triggered in a D callback
    gc_collect();

    int b = **m; //oops!

    free(m);
}


The question is, are you always guaranteed to have a reference on the caller
side? If not, then I think we have a problem.

E.g. what DMD and clang spit out without optimisations (edited):

__Dmain:
0000000100001610    pushq    %rbp
0000000100001611    movq    %rsp, %rbp
0000000100001614    movq    0x199e5(%rip), %rdi     ## literal pool symbol
address: _D11TypeInfo_Pi6__initZ
000000010000161b    callq    0x1000199d0             ## symbol stub for:
__d_newitemT
0000000100001620    movq    %rax, %rdi
    # only references to the memory are in %rax and %rdi
0000000100001623    callq    _foo
0000000100001628    xorl    %eax, %eax
000000010000162a    popq    %rbp
000000010000162b    retq

_foo:
0000000100001650    pushq    %rbp
0000000100001651    movq    %rsp, %rbp
0000000100001654    subq    $0x20, %rsp
0000000100001658    movabsq    $0x8, %rax
    # %rax has been overwritten, only references is in %rdi
0000000100001662    movq    %rdi, -0x8(%rbp)
    # %rdi and %rbp-8
0000000100001666    movq    %rax, %rdi
    # %rbp-8
0000000100001669    callq    0x100019b56             ## symbol stub for:
_malloc
000000010000166e    movq    %rax, -0x10(%rbp)
0000000100001672    movq    -0x8(%rbp), %rax
    # %rax and %rbp-8
0000000100001676    movq    -0x10(%rbp), %rdi
000000010000167a    movq    %rax, (%rdi)
    # %rax, %rbp-8 and on C heap at (%rdi)
000000010000167d    movq    $0x0, -0x8(%rbp)
    # %rax and on C heap at (%rdi)
0000000100001685    movb    $0x0, %al
    # %rax lowest byte stomped, only reference on C heap at (%rdi)
0000000100001687    callq    0x10001987a             ## symbol stub for:
_gc_collect
    # GC has no references it can see, frees the memory
000000010000168c    movq    -0x10(%rbp), %rdi
0000000100001690    movq    (%rdi), %rdi
    # %rdi is now dangling pointer
0000000100001693    movl    (%rdi), %ecx
    # BOOM!
0000000100001695    movl    %ecx, -0x14(%rbp)
0000000100001698    movq    -0x10(%rbp), %rdi
000000010000169c    callq    0x100019b3e             ## symbol stub for: _free
00000001000016a1    addq    $0x20, %rsp
00000001000016a5    popq    %rbp
00000001000016a6    retq


Am I reading that right? I think it might be OK in this example because of the
remaining bytes of %rax but I don't see why we can rely on that.

--


More information about the Digitalmars-d-bugs mailing list