-
Notifications
You must be signed in to change notification settings - Fork 15
Unitialized memory #42
Comments
I would this one to your list:
Ideally, it would be nice to ensure that simply moving/copying an uninitialized value is fine, as long as you don't "use" it. This includes passing it as a parameter to another function, again as long as that function doesn't "use" the value. |
What counts as using, then? Writing to a TCP socket for example is fundamentally a copy. |
Yeah, that would still be a copy, provided the socket is operating in cooked packet mode. In raw mode the OS will inspect at least the contents of the TCP header. |
So here's what miri implements; IMHO that's a good starting point and it should be mostly compatible with LLVM... Every byte (we ignore bit-wise accesses for now; anyway Rust doesn't have bitfields) is either some value (0 <= x < 256) or "undefined" (or call it unitialized or whatever you like). Loading four undef bytes into a I invite you to play around with miri and run your toy examples though it; if you run into missing functionality, just report a bug. :) My goal is for miri to explicitly be a tool to test such questions; of course, there's still a long way to go. Now, when we are talking abut safe code, I think this is related to #12 (comment). I would also like to propose that passing some safe external function that expects a |
AFAIK that's |
I was referring to miri's undef, which indeed in LLVM is closest to posion. |
So it sounds like branching is key to triggering UB, but arithmetic "merely" propagates poisoned values?
I’m worried about this distinction. How is it defined? In an implementation of |
That's a difference between LLVM poison and miri undef -- the latter is UB on arithmetic.
Good question. We haven't figured out all the details yet. Notice however that most of the time, thse functions assume additional invariants on top of what the type says, which would be fine with a model that checks if at least the normal type interpretation holds. |
Paraphrasing http://shape-of-code.coding-guidelines.com/2017/06/18/how-indeterminate-is-an-indeterminate-value/ for brevity:
|
@SimonSapin Instead of XOR one could also use |
The story of |
Under what conditions is it valid to use any of these?
let x: T = std::mem::uninitialized();
on the stackBox::new(std::mem::uninitialized())
Vec
between.len()
and.capacity()
alloc::heap::allocate()
without first writing to itLet’s assume
!Drop
(or that we usestd::mem::forget
and are being very careful about panic-safety), and types (likeu32
) for which all bit patterns are valid.Reading uninitialized memory is Bad and should be avoided, but what’s the worst that could happen? Undefined values might fine in many cases. Or is it Undefined Behavior of the “the optimizer is allowed to eat your lunch and elide half your program” kind?
As a concrete example, consider
reallocate
which when copying reads from the source pointer. That data is not necessarily entirely initialized:Vec::with_capacity(10).reserve(100)
The text was updated successfully, but these errors were encountered: