Skip to content

Commit 7ff57ed

Browse files
committed
also identiy MaybeUninit::uninit().assume_init() as dangerous
1 parent df4e12d commit 7ff57ed

File tree

5 files changed

+68
-3
lines changed

5 files changed

+68
-3
lines changed

src/librustc/lint/context.rs

+3
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,9 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
699699

700700
/// Check if a `DefId`'s path matches the given absolute type path usage.
701701
///
702+
/// Anonymous scopes such as `extern` imports are matched with `kw::Invalid`;
703+
/// inherent `impl` blocks are matched with the name of the type.
704+
///
702705
/// # Examples
703706
///
704707
/// ```rust,ignore (no context or def id available)

src/librustc_lint/builtin.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -1911,8 +1911,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
19111911
// `Invalid` represents the empty string and matches that.
19121912
const TRANSMUTE_PATH: &[Symbol] =
19131913
&[sym::core, sym::intrinsics, kw::Invalid, sym::transmute];
1914+
const MU_ZEROED_PATH: &[Symbol] =
1915+
&[sym::core, sym::mem, sym::maybe_uninit, sym::MaybeUninit, sym::zeroed];
1916+
const MU_UNINIT_PATH: &[Symbol] =
1917+
&[sym::core, sym::mem, sym::maybe_uninit, sym::MaybeUninit, sym::uninit];
19141918

19151919
if let hir::ExprKind::Call(ref path_expr, ref args) = expr.kind {
1920+
// Find calls to `mem::{uninitialized,zeroed}` methods.
19161921
if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
19171922
let def_id = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
19181923

@@ -1927,8 +1932,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
19271932
return Some(InitKind::Zeroed);
19281933
}
19291934
}
1930-
// FIXME: Also detect `MaybeUninit::zeroed().assume_init()` and
1931-
// `MaybeUninit::uninit().assume_init()`.
1935+
}
1936+
} else if let hir::ExprKind::MethodCall(ref path, _, ref args) = expr.kind {
1937+
// Find problematic calls to `MaybeUninit::assume_init`.
1938+
if path.ident.name == sym::assume_init {
1939+
// This is a call to *some* method named `assume_init`.
1940+
// See if the `self` parameter is one of the dangerous constructors.
1941+
if let hir::ExprKind::Call(ref path_expr, _) = args[0].kind {
1942+
if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
1943+
let def_id = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
1944+
if cx.match_def_path(def_id, MU_ZEROED_PATH) {
1945+
return Some(InitKind::Zeroed);
1946+
} else if cx.match_def_path(def_id, MU_UNINIT_PATH) {
1947+
return Some(InitKind::Uninit);
1948+
}
1949+
}
1950+
}
19321951
}
19331952
}
19341953

src/libsyntax_pos/symbol.rs

+4
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ symbols! {
148148
associated_type_bounds,
149149
associated_type_defaults,
150150
associated_types,
151+
assume_init,
151152
async_await,
152153
async_closure,
153154
attr,
@@ -417,6 +418,8 @@ symbols! {
417418
match_beginning_vert,
418419
match_default_bindings,
419420
may_dangle,
421+
maybe_uninit,
422+
MaybeUninit,
420423
mem,
421424
member_constraints,
422425
message,
@@ -709,6 +712,7 @@ symbols! {
709712
underscore_imports,
710713
underscore_lifetimes,
711714
uniform_paths,
715+
uninit,
712716
uninitialized,
713717
universal_impl_trait,
714718
unmarked_api,

src/test/ui/lint/uninitialized-zeroed.rs

+6
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,16 @@ fn main() {
8585
let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization
8686
let _val: NonZeroU32 = mem::transmute(0); //~ ERROR: does not permit zero-initialization
8787

88+
// `MaybeUninit` cases
89+
let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init(); //~ ERROR: does not permit zero-initialization
90+
let _val: NonNull<i32> = MaybeUninit::uninit().assume_init(); //~ ERROR: does not permit being left uninitialized
91+
let _val: bool = MaybeUninit::uninit().assume_init(); //~ ERROR: does not permit being left uninitialized
92+
8893
// Some more types that should work just fine.
8994
let _val: Option<&'static i32> = mem::zeroed();
9095
let _val: Option<fn()> = mem::zeroed();
9196
let _val: MaybeUninit<&'static i32> = mem::zeroed();
9297
let _val: i32 = mem::zeroed();
98+
let _val: bool = MaybeUninit::zeroed().assume_init();
9399
}
94100
}

src/test/ui/lint/uninitialized-zeroed.stderr

+34-1
Original file line numberDiff line numberDiff line change
@@ -399,5 +399,38 @@ LL | let _val: NonZeroU32 = mem::transmute(0);
399399
|
400400
= note: std::num::NonZeroU32 must be non-null
401401

402-
error: aborting due to 32 previous errors
402+
error: the type `std::ptr::NonNull<i32>` does not permit zero-initialization
403+
--> $DIR/uninitialized-zeroed.rs:89:34
404+
|
405+
LL | let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init();
406+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
407+
| |
408+
| this code causes undefined behavior when executed
409+
| help: use `MaybeUninit<T>` instead
410+
|
411+
= note: std::ptr::NonNull<i32> must be non-null
412+
413+
error: the type `std::ptr::NonNull<i32>` does not permit being left uninitialized
414+
--> $DIR/uninitialized-zeroed.rs:90:34
415+
|
416+
LL | let _val: NonNull<i32> = MaybeUninit::uninit().assume_init();
417+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
418+
| |
419+
| this code causes undefined behavior when executed
420+
| help: use `MaybeUninit<T>` instead
421+
|
422+
= note: std::ptr::NonNull<i32> must be non-null
423+
424+
error: the type `bool` does not permit being left uninitialized
425+
--> $DIR/uninitialized-zeroed.rs:91:26
426+
|
427+
LL | let _val: bool = MaybeUninit::uninit().assume_init();
428+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
429+
| |
430+
| this code causes undefined behavior when executed
431+
| help: use `MaybeUninit<T>` instead
432+
|
433+
= note: Booleans must be `true` or `false`
434+
435+
error: aborting due to 35 previous errors
403436

0 commit comments

Comments
 (0)