From df4e12d88947db6ff832bb7caae44927af687eb7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 2 Nov 2019 11:56:06 +0100 Subject: [PATCH] uninit/zeroed lint: warn against NULL vtables --- src/librustc_lint/builtin.rs | 2 ++ src/librustc_lint/lib.rs | 1 + src/test/ui/lint/uninitialized-zeroed.rs | 3 ++ src/test/ui/lint/uninitialized-zeroed.stderr | 36 ++++++++++++++++---- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index e3c3966c2f5..e1c57d8afff 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1949,6 +1949,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { Adt(..) if ty.is_box() => Some((format!("`Box` must be non-null"), None)), FnPtr(..) => Some((format!("Function pointers must be non-null"), None)), Never => Some((format!("The never type (`!`) has no valid value"), None)), + RawPtr(tm) if matches!(tm.ty.kind, Dynamic(..)) => // raw ptr to dyn Trait + Some((format!("The vtable of a wide raw pointer must be non-null"), None)), // Primitive types with other constraints. Bool if init == InitKind::Uninit => Some((format!("Booleans must be `true` or `false`"), None)), diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index b1beef04c59..a47980c5ead 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -15,6 +15,7 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(nll)] +#![feature(matches_macro)] #![recursion_limit="256"] diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs index 5cf62b86912..ccc4e77bc97 100644 --- a/src/test/ui/lint/uninitialized-zeroed.rs +++ b/src/test/ui/lint/uninitialized-zeroed.rs @@ -67,6 +67,9 @@ fn main() { let _val: NonNull = mem::zeroed(); //~ ERROR: does not permit zero-initialization let _val: NonNull = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + let _val: *const dyn Send = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: *const dyn Send = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + // Things that can be zero, but not uninit. let _val: bool = mem::zeroed(); let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index a36a32a39a1..85b1e0aaff0 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -307,8 +307,30 @@ LL | let _val: NonNull = mem::uninitialized(); | = note: std::ptr::NonNull must be non-null +error: the type `*const dyn std::marker::Send` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:70:37 + | +LL | let _val: *const dyn Send = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: The vtable of a wide raw pointer must be non-null + +error: the type `*const dyn std::marker::Send` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:71:37 + | +LL | let _val: *const dyn Send = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: The vtable of a wide raw pointer must be non-null + error: the type `bool` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:72:26 + --> $DIR/uninitialized-zeroed.rs:75:26 | LL | let _val: bool = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -319,7 +341,7 @@ LL | let _val: bool = mem::uninitialized(); = note: Booleans must be `true` or `false` error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:75:32 + --> $DIR/uninitialized-zeroed.rs:78:32 | LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -334,7 +356,7 @@ LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `NonBig` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:78:28 + --> $DIR/uninitialized-zeroed.rs:81:28 | LL | let _val: NonBig = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -345,7 +367,7 @@ LL | let _val: NonBig = mem::uninitialized(); = note: NonBig must be initialized inside its custom valid range error: the type `&'static i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:81:34 + --> $DIR/uninitialized-zeroed.rs:84:34 | LL | let _val: &'static i32 = mem::transmute(0usize); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -356,7 +378,7 @@ LL | let _val: &'static i32 = mem::transmute(0usize); = note: References must be non-null error: the type `&'static [i32]` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:82:36 + --> $DIR/uninitialized-zeroed.rs:85:36 | LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -367,7 +389,7 @@ LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); = note: References must be non-null error: the type `std::num::NonZeroU32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:83:32 + --> $DIR/uninitialized-zeroed.rs:86:32 | LL | let _val: NonZeroU32 = mem::transmute(0); | ^^^^^^^^^^^^^^^^^ @@ -377,5 +399,5 @@ LL | let _val: NonZeroU32 = mem::transmute(0); | = note: std::num::NonZeroU32 must be non-null -error: aborting due to 30 previous errors +error: aborting due to 32 previous errors