August 05 [Issue 24696] New: Lack of null reference checking enables full access to arbitrary memory locations in @safe | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=24696 Issue ID: 24696 Summary: Lack of null reference checking enables full access to arbitrary memory locations in @safe Product: D Version: D2 Hardware: All OS: All Status: NEW Keywords: safe Severity: critical Priority: P1 Component: dmd Assignee: nobody@puremagic.com Reporter: elpenguino+D@gmail.com Consider the following program, compiled with -m32: ``` struct RawMemoryAccess { private enum limit = 16 * 1024 * 1024; static foreach (i; 0 .. 255) { mixin("ubyte[limit] array", i, ";"); } ref ubyte opIndex(size_t index) @safe return { switch (index >> 24) { static foreach (i; 0 .. 255) { case i: return this.tupleof[i][index % limit]; } default: assert(0); } } } void main() @safe { RawMemoryAccess* f; int* i = new int(4); (*f)[cast(size_t)i] = 42; // muahahaha assert(*i == 4); } ``` Thanks to relying completely on hardware for null-reference checking, we can get away with completely memory-safe arbitrary memory access with a simple struct the same size of the entire memory space. Limiting static arrays to 16MB makes it trickier, but still quite trivial to bypass. Although this example only functions with -m32, it can be adapted to 64-bit builds as well, though it would require either pushing CTFE well beyond its current limits or the submission of a 36TB+ .d module, neither of which are reasonable. -- |
Copyright © 1999-2021 by the D Language Foundation