I think ReleaseSafe just adds bound checking and panics on unreachable code.
I don't think Zig offers any temporal memory safety.
I think ReleaseSafe just adds bound checking and panics on unreachable code.
I don't think Zig offers any temporal memory safety.
https://ziglang.org/documentation/master/std/#src/std/heap/d...
For higher level code, "generation-counted index handles" might be the better solution to provide temporal runtime memory safety, not part of Zig the stdlib though.
Or even better: never use dynamic memory allocation and make all lifetimes 'static' :)
To clarify, is that to say that you have to use the `std.heap.page_allocator` as its backing allocator?
The bug was around passing a slice to OpenGL which referenced memory outside of its lifetime. Since the memory location had no owner, vertices would still exist in Dev builds and everything would work fine, but in ReleaseSafe the application would run and just have nothing to render.
Since OpenGL was trying to read the memory, there was no panic from Zig, but it was a cool look into how the different build modes handle memory.
This is the commit where I fixed the issue: https://github.com/quot/donut/commit/8fff107e76278c4bf55007c...
Link: https://zig.guide/standard-library/allocators/
Text:
> The Zig standard library also has a general-purpose debug allocator. This is a safe allocator that can prevent double-free, use-after-free and can detect leaks.
For more detail, see:
https://github.com/ziglang/zig/issues/3180#issuecomment-5284...
Here's the code: https://codeberg.org/ziglang/zig/src/commit/e44e927d33d37c44...
The closest callout in the doc comment is:
>Never reuses memory addresses, making it easier for Zig to detect branch on undefined values in case of dangling pointers. This relies on the backing allocator to also not reuse addresses.
But it's not really clear what this means. "branch on undefined values" would I think indicate that maybe they're doing a fill pattern that the compiler can detect at runtime when dereferenced? But I don't see it in the `free` path. It's not clear if this is deterministic or not either.
Or, rather, you can use a value after freeing it, but it will not be exploitable, because it will contain valid data of the right type. This is the same idea as Type-After-Type,
https://dl.acm.org/doi/10.1145/3274694.3274705
(Also similar to when you use indexes to an array in Rust and happen to read from a wrong but in-bounds index.)