4 ms·
Zig pointers are non-null. Optionally null pointers must be explicitly unwrapped.
by jibal 1y ago
Zig pointers are non-null. Optionally null pointers must be explicitly unwrapped.
- noitpmeder 1y agoso... references and pointers? What is my_ptr->member but unwrapping an optionally null pointer.
- davemp 1y agoIt’s semantics. Zig can still have dangling references/uaf. You can do something like ‘var foo: *Bar = @intToPtr(0x00)’ but in order to “properly” use the zero address to represent state you have to use ‘var foo: ?*Bar = null’ which is a different type than ‘*Bar’ that the compiler will force you to check before accessing. It’s the whole make it easy to write good code—not impossible to write incorrect code philosophy of the language.
- pjmlp 1y agoThus it would not prevent a CVE like the one being discussed.
- davemp 1y agoJudging from the article, Zig would have prevented the CVE. > This includes memory allocations of type NV01_MEMORY_DEVICELESS which are not associated with any device and therefore have the pGpu field of their corresponding MEMORY_DESCRIPTOR structure set to null This does look like the type of null deref that Zig does prevent. Looking at the second issue in the chain, I believe standard Zig would have prevented that as well. The C code had an error that caused the call to free to be skipped: threadStateInit(&threadState, THREAD_STATE_FLAGS_NONE); status = rmapiMapWithSecInfo(/*…*/); // null deref here threadStateFree(&threadState, THREAD_STATE_FLAGS_NONE); Zig’s use of ‘defer’ would ensure that free is called even if an error occurred: threadStateInit(&threadState, THREAD_STATE_FLAGS_NONE); defer threadStateFree(&threadState, THREAD_STATE_FLAGS_NONE); status = try rmapiMapWithSecInfo(/*…*/); // null deref here
- pjmlp 1y agoAssuming the user would not have forgotten to type the line with defer, and correctly as well, like all great coders. Followed by never touching the variable ever again.
- davemp 1y agoNothing can prevent a sufficiently belligerent programmer from writing bad code. Not even Rust—which I assume you’re advocating for without reading the greater context of this thread.
- tialaramex 1y agoWe're literally in a thread about the famous Onion recurring story. "'No Way to Prevent This,' Says Only Nation Where This Regularly Happens"
- davemp 1y agoI literally replied with “A Way to Prevent This”?
- tialaramex 1y ago"Don't make mistakes" isn't a way to prevent this. We know that doesn't work.
- davemp 1y agoNo, the solutions I spoke about were language features that make it trivial to avoid or impossible to make the mistakes. If your bar for mistakes is “what if you forget to add literally the next line of code in the incredibly common pattern”, I don’t really care to have a discussion about programming languages anymore. You can forget to increment a loop and have your program not terminate so why don’t you program with language of exclusively primitive recursive functions?
- jibal 1y ago> What is my_ptr->member but unwrapping an optionally null pointer. It's a dereference of a pointer that might be null and thereby yield undefined behavior; there's no required unwrapping under an explicit test for null, as is required by Zig. In Zig, my_ptr cannot be null in my_ptr.member -- null is not a valid pointer value. If my_ptr is an optionally null pointer then the pointer value must be unwrapped by first checking whether it is null ... the dereference can only occur in the test branch where the pointer isn't null. Note that the mention of Zig that I responded to was in reference to Tony Hoare's "billion dollar mistake", which was making null a valid value of a pointer type. As I noted, the mistake doesn't occur in Zig because null is not a valid value for a pointer, only an optional pointer, which must be unwrapped with an explicit null test. If you had no idea what I was referring to, you might have asked. Rather, you asked a rhetorical question with no question mark, implying the falsehood that my_ptr->member is "unwrapping an optionally null pointer" when it's nothing of the sort.
- pjmlp 1y agoAssuming they are still valid, Zig doesn't prevent use after free.
- jibal 1y ago> This only happens if you have the worst version of Tony's Billion Dollar Mistake. So C, C++, ==> Zig <==, Odin and so on but not Rust. The billion dollar mistake is making NULL a valid pointer value, not use after free--which has nothing to do with null pointers and which I didn't comment on, as the comment I responded to only mentioned Zig in regard to the billion dollar mistake. The billion dollar mistake doesn't occur in Zig because null is not a valid value for a pointer, only an optional pointer, which must be unwrapped with an explicit null test.
- tialaramex 1y agoI agree that's an error on my part - Zig does not actually have the billion dollar mistake, although I don't think the approach taken is very good it's clearly not just the billion dollar mistake and so I was wrong to say that.
- jibal 1y ago> although I don't think the approach taken is very good The approach taken is the same as in virtually every other language that has avoided the billion dollar mistake -- null is not a valid pointer value, and instead there's an additional union type (called Optional, Maybe, etc.) that can hold Some(pointer) or None. Zig, like some other languages, extends this union beyond pointers to other types.