Skip to content

Commit 8f79b5a

Browse files
committed
Add option to disable validity invariant generation
1 parent c24ef46 commit 8f79b5a

File tree

5 files changed

+98
-36
lines changed

5 files changed

+98
-36
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc_middle::ty::subst::SubstsRef;
1717
use rustc_middle::ty::{Ty, TyCtxt};
1818
use rustc_span::symbol::{sym, Symbol};
1919
use rustc_target::abi::{Abi, Align, InitKind, Primitive, Size};
20+
use rustc_target::spec::SanitizerSet;
2021

2122
use super::{
2223
util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
@@ -106,8 +107,20 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
106107
| ty::Error(_) => ConstValue::from_machine_usize(0u64, &tcx),
107108
},
108109
sym::validity_invariants_of => {
110+
let msan = tcx.sess.opts.debugging_opts.sanitizer.contains(SanitizerSet::MEMORY);
111+
let disable = tcx.sess.opts.debugging_opts.no_validity_invariant_checks;
112+
113+
let strictness = if disable {
114+
validity_invariants_of::InvariantStrictness::Disable
115+
} else if msan {
116+
validity_invariants_of::InvariantStrictness::All
117+
} else {
118+
validity_invariants_of::InvariantStrictness::Normal
119+
};
120+
109121
ensure_monomorphic_enough(tcx, tp_ty)?;
110-
let (data, length) = validity_invariants_of::alloc_validity_invariants_of(tcx, tp_ty);
122+
let (data, length) =
123+
validity_invariants_of::alloc_validity_invariants_of(tcx, tp_ty, strictness);
111124
ConstValue::CustomSlice { data, length }
112125
}
113126
other => bug!("`{}` is not a zero arg intrinsic", other),

compiler/rustc_const_eval/src/interpret/intrinsics/validity_invariants_of.rs

+22-6
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ fn add_invariants<'tcx>(
3232
ty: Ty<'tcx>,
3333
invs: &mut FxHashMap<InvariantKey, WrappingRange>,
3434
offset: Size,
35+
strictness: InvariantStrictness,
3536
) {
37+
if strictness == InvariantStrictness::Disable {
38+
return;
39+
}
40+
3641
let x = tcx.layout_of(ParamEnvAnd { param_env: ParamEnv::reveal_all(), value: ty });
3742

3843
if let Ok(layout) = x {
@@ -48,9 +53,12 @@ fn add_invariants<'tcx>(
4853
Primitive::Pointer => InvariantSize::Pointer,
4954
};
5055

51-
// Pick the first scalar we see, this means NonZeroU8(u8) ends up with only one
52-
// invariant, the stricter one.
53-
let _: Result<_, _> = invs.try_insert(InvariantKey { offset, size }, valid_range);
56+
if !valid_range.is_full_for(value.size(&tcx)) || strictness == InvariantStrictness::All
57+
{
58+
// Pick the first scalar we see, this means NonZeroU8(u8) ends up with only one
59+
// invariant, the stricter one.
60+
let _: Result<_, _> = invs.try_insert(InvariantKey { offset, size }, valid_range);
61+
}
5462
}
5563

5664
//dbg!(&ty, &layout);
@@ -71,7 +79,7 @@ fn add_invariants<'tcx>(
7179
for idx in 0..*count {
7280
let off = offset + *stride * idx;
7381
let f = layout.field(&layout_cx, idx as usize);
74-
add_invariants(tcx, f.ty, invs, off);
82+
add_invariants(tcx, f.ty, invs, off, strictness);
7583
}
7684
}
7785
FieldsShape::Arbitrary { offsets, .. } => {
@@ -82,7 +90,7 @@ fn add_invariants<'tcx>(
8290
// &mut [T]
8391
// Easy solution is to just not recurse then.
8492
} else {
85-
add_invariants(tcx, f.ty, invs, offset + field_offset);
93+
add_invariants(tcx, f.ty, invs, offset + field_offset, strictness);
8694
}
8795
}
8896
}
@@ -99,17 +107,25 @@ fn get_layout_of_invariant<'tcx>(tcx: TyCtxt<'tcx>) -> TyAndLayout<'tcx, Ty<'tcx
99107
layout
100108
}
101109

110+
#[derive(PartialEq, Clone, Copy, Eq)]
111+
pub(crate) enum InvariantStrictness {
112+
Disable,
113+
Normal,
114+
All,
115+
}
116+
102117
/// Directly returns a `ConstAllocation` containing a list of validity invariants of the given type.
103118
pub(crate) fn alloc_validity_invariants_of<'tcx>(
104119
tcx: TyCtxt<'tcx>,
105120
ty: Ty<'tcx>,
121+
strictness: InvariantStrictness,
106122
) -> (ConstAllocation<'tcx>, usize) {
107123
let mut invs = FxHashMap::default();
108124

109125
let layout = tcx.data_layout();
110126
let validity_invariant = get_layout_of_invariant(tcx);
111127

112-
add_invariants(tcx, ty, &mut invs, Size::ZERO);
128+
add_invariants(tcx, ty, &mut invs, Size::ZERO, strictness);
113129

114130
let allocation_size = validity_invariant.layout.size() * invs.len() as u64;
115131
let mut alloc =

compiler/rustc_session/src/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1380,6 +1380,8 @@ options! {
13801380
"run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
13811381
no_unique_section_names: bool = (false, parse_bool, [TRACKED],
13821382
"do not use unique names for text and data sections when -Z function-sections is used"),
1383+
no_validity_invariant_checks: bool = (false, parse_bool, [TRACKED],
1384+
"do not generate any validity invariants in the validity_invariants_of intrinsic"),
13831385
no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED],
13841386
"prevent automatic injection of the profiler_builtins crate"),
13851387
normalize_docs: bool = (false, parse_bool, [TRACKED],

src/test/ui/intrinsics/validity_invariants_of.rs

+57-28
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
// run-pass
2+
// revisions: disabled normal sanitized
3+
// [disabled]compile-flags: -Zno-validity-invariant-checks
4+
// [sanitized]compile-flags: -Z sanitizer=memory
25
#![feature(core_intrinsics, const_intrinsic_validity_invariants_of)]
36

47
use std::mem::MaybeUninit;
@@ -20,40 +23,66 @@ fn main() {
2023

2124
invs.sort_by_key(|x| x.offset);
2225

23-
assert_eq!(&invs, &[
24-
Invariant {
25-
offset: 0,
26-
size: InvariantSize::U16,
27-
valid_range_start: 1,
28-
valid_range_end: 65535
29-
},
30-
Invariant {
31-
offset: 2,
32-
size: InvariantSize::U8,
33-
valid_range_start: 0,
34-
valid_range_end: 255
35-
},
36-
Invariant {
37-
offset: 3,
38-
size: InvariantSize::U8,
39-
valid_range_start: 0,
40-
valid_range_end: 1
41-
},
42-
]);
26+
if cfg!(disabled) {
27+
assert_eq!(&invs, &[]);
28+
} else if cfg!(normal) {
29+
assert_eq!(&invs, &[
30+
Invariant {
31+
offset: 0,
32+
size: InvariantSize::U16,
33+
valid_range_start: 1,
34+
valid_range_end: 65535
35+
},
36+
Invariant {
37+
offset: 3,
38+
size: InvariantSize::U8,
39+
valid_range_start: 0,
40+
valid_range_end: 1
41+
},
42+
]);
43+
} else {
44+
assert!(cfg!(sanitized));
45+
46+
assert_eq!(&invs, &[
47+
Invariant {
48+
offset: 0,
49+
size: InvariantSize::U16,
50+
valid_range_start: 1,
51+
valid_range_end: 65535
52+
},
53+
Invariant {
54+
offset: 2,
55+
size: InvariantSize::U8,
56+
valid_range_start: 0,
57+
valid_range_end: 255
58+
},
59+
Invariant {
60+
offset: 3,
61+
size: InvariantSize::U8,
62+
valid_range_start: 0,
63+
valid_range_end: 1
64+
},
65+
]);
66+
}
67+
4368

4469
unsafe {
4570
let v = MyStruct { a: NonZeroU16::new(1).unwrap(), b: 2, c: true };
4671
assert!(assert_validity_of(&v as *const _));
4772
}
4873

49-
assert_eq!(OPTION_INVARIANTS, &[
50-
Invariant {
51-
offset: 0,
52-
size: InvariantSize::Pointer,
53-
valid_range_start: 1,
54-
valid_range_end: 0,
55-
},
56-
]);
74+
if cfg!(sanitized) {
75+
assert_eq!(OPTION_INVARIANTS, &[
76+
Invariant {
77+
offset: 0,
78+
size: InvariantSize::Pointer,
79+
valid_range_start: 1,
80+
valid_range_end: 0,
81+
},
82+
]);
83+
} else {
84+
assert_eq!(OPTION_INVARIANTS, &[]);
85+
}
5786

5887

5988
unsafe {

src/test/ui/sanitize/memory.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// needs-sanitizer-support
22
// needs-sanitizer-memory
33
//
4-
// compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O
4+
// compile-flags: -Z sanitizer=memory -Zno-validity-invariant-checks -Zsanitizer-memory-track-origins -O
55
//
66
// run-fail
77
// error-pattern: MemorySanitizer: use-of-uninitialized-value
@@ -10,6 +10,8 @@
1010
//
1111
// This test case intentionally limits the usage of the std,
1212
// since it will be linked with an uninstrumented version of it.
13+
//
14+
// -Zno-validity-invariant-checks is needed in order to not fail inside the assume_init
1315

1416
#![feature(core_intrinsics)]
1517
#![feature(start)]

0 commit comments

Comments
 (0)