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