-
Notifications
You must be signed in to change notification settings - Fork 254
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
analyze: null pointer support #816
Comments
I'm not sure about this. C I think there's two cases here:
|
Also, similar to |
It would be legal under our definition of correctness (in which we either preserve behavior exactly or introduce a panic) to assert after every
I think these are covered by the discussion on the |
) - Fixes the first step of #816. This adds `PermissionSet::NON_NULL` and precise docs explaining its meaning and intended usage, but doesn't contain any actual implementation or use of `NON_NULL`.
We should add support to
c2rust-analyze
for tracking (possibly) null pointers.First, we should add a new pointer permission:
PermissionSet::NON_NULL
. A pointer with this permission is known to never be null at run time.NON_NULL
is set (or not) when the pointer is created, and it flows forward along dataflow edges. The results ofRvalue::Ref
andRvalue::AddressOf
should have theNON_NULL
permission set;ptr::null()
,ptr::null_mut()
, and casting the constant 0 to a pointer type do not set the permission; and casting other integers to pointer types is (still) unsupported and therefore panics.The permission is
NON_NULL
rather thanNULL
because we allow dropping permissions in any assignment. This means removing a permission from a pointer'sPermissionSet
must allow the pointer to take on more values, not restrict it to fewer values.The reason to continue rejecting nonzero constant integer-to-pointer casts like
3 as *const u8
is to avoid losing information and potentially changing program behavior. The result of3 as *const u8
can't be a value of type&u8
because it's not a valid pointer, and it can't beNone
because that would lose the fact that the value is 3 and not 0. We don't want0 as *const u8 == 3 as *const u8
to be rewritten intoNone == None
and wrongly evaluate totrue
.Second, we'll need to update the
type_desc
andrewrite::ty
modules to recognize the lack ofNON_NULL
and useOption<_>
when needed.Third,
rewrite::expr
will need to insertSome(_)
,None
, and_.unwrap()
as needed. Casts fromNON_NULL
to nullable pointers will need to wrap the pointer expression inSome(_)
. Operations that produce null pointers should be replaced withNone
. And dereferences of nullable pointers should call_.unwrap()
first.Some operations may need special handling. I think
offset
should require a non-null pointer (meaningrewrite::expr
shouldunwrap()
the input if it's nullable, like it does for deref), since it's UB to call it on invalid pointers. This meansoffset
can unconditionally returnNON_NULL
regardless of its input. Andis_null
can be converted tois_some()
if the pointer is nullable or replaced with literaltrue
if it'sNON_NULL
. (Convertingif p.is_null() { ... }
toif let Some(p) = p { ... }
would be nice to have, but isn't essential and would probably be a bit tricky.It might be safe for us to define
malloc
and related functions to returnNON_NULL
, which would let us eliminate a lot ofOption
s, because the Rust translations of those functions (Box::new
/Vec::new
) abort on OOM instead of returning null.The text was updated successfully, but these errors were encountered: