Bug 24696 – Lack of null reference checking enables full access to arbitrary memory locations in @safe

Status
RESOLVED
Resolution
DUPLICATE
Severity
critical
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2024-08-05T21:08:26Z
Last change time
2024-08-06T12:07:37Z
Keywords
safe
Assigned to
No Owner
Creator
elpenguino+D

Comments

Comment #0 by elpenguino+D — 2024-08-05T21:08:26Z
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.
Comment #1 by razvan.nitu1305 — 2024-08-06T12:07:37Z
This is a known issue reported a long time ago: https://issues.dlang.org/show_bug.cgi?id=5176 *** This issue has been marked as a duplicate of issue 5176 ***