On Mon, 14 Apr 2014 23:14:06 -0400, lzzll <[email protected]> wrote:
Let me show some exmaple on c, and two common memory error detect tool.
example 1 (stack overflow):
---
int a = 100;
printf("%p\n", &a);
int *b = &a+1;
printf("%p\n", &b);
*b = 100;
---
import std.stdio;
void main() @safe
{
int a = 100;
writeln(&a); // line 6
int *b = &a+1; // line 8
*b = 100;
}
testsafe.d(6): Error: cannot take address of local a in @safe function main
testsafe.d(6): Error: safe function 'D main' cannot call system function
'std.stdio.writeln!(int*).writeln' (wow, really?)
testsafe.d(8): Error: cannot take address of local a in @safe function main
testsafe.d(8): Error: pointer arithmetic not allowed in @safe functions
@safe prevents memory errors by preventing pointer arithmetic, and taking
addresses of stack locals.
I was not aware that writeln is also unsafe! That must be a bug. Even
writeln!int is unsafe.
valgrind: nothing detected
address sanitizer: ==1996== ERROR: AddressSanitizer:
stack-buffer-overflow on address 0x7fffc976dbc4
example 2 (cross address)
---
int a = 100;
int b = 200;
printf("%p\n", &a);
printf("%p\n", &b);
int *c = &a+(&b-&a);
printf("%p\n", c);
*c = 100;
---
illegal to use c's initializer in @safe code.
Of course it can't be detected.
It's also not a memory corruption :)
optimizer will turn int *c = &a+(&b-&a) to int *c = &b;
example 3 (heap overflow)
---
int *a = (int*) malloc(sizeof(int));
printf("%p\n", a);
int *b = a + 1;
printf("%p\n", b);
*b = 100;
---
illegal to use b's initializer in @safe code. The malloc is allowed, but
only GC.malloc. C's malloc is not @safe as it requires free.
valgrind: Address 0x51f0044 is 0 bytes after a block of size 4 alloc'd
address sanitizer: AddressSanitizer: heap-buffer-overflow on address
0x60040000dff4
It's possible to a certain extent.
Reference:
http://valgrind.org/docs/manual/mc-manual.html#mc-manual.vaddress
http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm
I understand implemented this is hard and it need huge cost.
It still be useful if we only use it to detect memory error and trun it
off when release.
I'll be glad if I can see it on D after some years.
It's impossible to have 100% coverage. Using sentinels and instrumenting
can help find memory errors, but just not allowing memory-unsafe code is
more efficient and guaranteed.
Note that valgrind should be able to instrument D code as well.
-Steve