[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