validation: better error when the enum discriminant is Undef
This commit is contained in:
parent
4ec0ba9545
commit
ffb6ba0828
@ -15,7 +15,7 @@ use ty::{Ty, layout};
|
|||||||
use ty::layout::{Size, Align, LayoutError};
|
use ty::layout::{Size, Align, LayoutError};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use super::{Pointer, Scalar};
|
use super::{Pointer, ScalarMaybeUndef};
|
||||||
|
|
||||||
use backtrace::Backtrace;
|
use backtrace::Backtrace;
|
||||||
|
|
||||||
@ -240,7 +240,7 @@ pub enum EvalErrorKind<'tcx, O> {
|
|||||||
InvalidMemoryAccess,
|
InvalidMemoryAccess,
|
||||||
InvalidFunctionPointer,
|
InvalidFunctionPointer,
|
||||||
InvalidBool,
|
InvalidBool,
|
||||||
InvalidDiscriminant(Scalar),
|
InvalidDiscriminant(ScalarMaybeUndef),
|
||||||
PointerOutOfBounds {
|
PointerOutOfBounds {
|
||||||
ptr: Pointer,
|
ptr: Pointer,
|
||||||
access: bool,
|
access: bool,
|
||||||
|
@ -601,7 +601,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
|||||||
// read raw discriminant value
|
// read raw discriminant value
|
||||||
let discr_op = self.operand_field(rval, 0)?;
|
let discr_op = self.operand_field(rval, 0)?;
|
||||||
let discr_val = self.read_immediate(discr_op)?;
|
let discr_val = self.read_immediate(discr_op)?;
|
||||||
let raw_discr = discr_val.to_scalar()?;
|
let raw_discr = discr_val.to_scalar_or_undef();
|
||||||
trace!("discr value: {:?}", raw_discr);
|
trace!("discr value: {:?}", raw_discr);
|
||||||
// post-process
|
// post-process
|
||||||
Ok(match rval.layout.variants {
|
Ok(match rval.layout.variants {
|
||||||
@ -647,13 +647,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
|||||||
let variants_start = niche_variants.start().as_u32() as u128;
|
let variants_start = niche_variants.start().as_u32() as u128;
|
||||||
let variants_end = niche_variants.end().as_u32() as u128;
|
let variants_end = niche_variants.end().as_u32() as u128;
|
||||||
match raw_discr {
|
match raw_discr {
|
||||||
Scalar::Ptr(_) => {
|
ScalarMaybeUndef::Scalar(Scalar::Ptr(_)) => {
|
||||||
// The niche must be just 0 (which a pointer value never is)
|
// The niche must be just 0 (which a pointer value never is)
|
||||||
assert!(niche_start == 0);
|
assert!(niche_start == 0);
|
||||||
assert!(variants_start == variants_end);
|
assert!(variants_start == variants_end);
|
||||||
(dataful_variant.as_u32() as u128, dataful_variant)
|
(dataful_variant.as_u32() as u128, dataful_variant)
|
||||||
},
|
},
|
||||||
Scalar::Bits { bits: raw_discr, size } => {
|
ScalarMaybeUndef::Scalar(Scalar::Bits { bits: raw_discr, size }) => {
|
||||||
assert_eq!(size as u64, discr_val.layout.size.bytes());
|
assert_eq!(size as u64, discr_val.layout.size.bytes());
|
||||||
let discr = raw_discr.wrapping_sub(niche_start)
|
let discr = raw_discr.wrapping_sub(niche_start)
|
||||||
.wrapping_add(variants_start);
|
.wrapping_add(variants_start);
|
||||||
@ -669,6 +669,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
|||||||
(dataful_variant.as_u32() as u128, dataful_variant)
|
(dataful_variant.as_u32() as u128, dataful_variant)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
ScalarMaybeUndef::Undef =>
|
||||||
|
return err!(InvalidDiscriminant(ScalarMaybeUndef::Undef)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -274,7 +274,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
|
|||||||
),
|
),
|
||||||
EvalErrorKind::ReadPointerAsBytes =>
|
EvalErrorKind::ReadPointerAsBytes =>
|
||||||
validation_failure!(
|
validation_failure!(
|
||||||
"a pointer", self.path, "plain bytes"
|
"a pointer", self.path, "plain (non-pointer) bytes"
|
||||||
),
|
),
|
||||||
_ => Err(err),
|
_ => Err(err),
|
||||||
}
|
}
|
||||||
@ -304,7 +304,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
|
|||||||
if self.const_mode {
|
if self.const_mode {
|
||||||
// Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
|
// Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
|
||||||
try_validation!(value.to_bits(size),
|
try_validation!(value.to_bits(size),
|
||||||
value, self.path, "initialized plain bits");
|
value, self.path, "initialized plain (non-pointer) bytes");
|
||||||
} else {
|
} else {
|
||||||
// At run-time, for now, we accept *anything* for these types, including
|
// At run-time, for now, we accept *anything* for these types, including
|
||||||
// undef. We should fix that, but let's start low.
|
// undef. We should fix that, but let's start low.
|
||||||
|
@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
|
|||||||
--> $DIR/const-pointer-values-in-various-types.rs:24:5
|
--> $DIR/const-pointer-values-in-various-types.rs:24:5
|
||||||
|
|
|
|
||||||
LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
|
LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ error[E0080]: it is undefined behavior to use this value
|
|||||||
--> $DIR/const-pointer-values-in-various-types.rs:36:5
|
--> $DIR/const-pointer-values-in-various-types.rs:36:5
|
||||||
|
|
|
|
||||||
LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
|
LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ error[E0080]: it is undefined behavior to use this value
|
|||||||
--> $DIR/const-pointer-values-in-various-types.rs:51:5
|
--> $DIR/const-pointer-values-in-various-types.rs:51:5
|
||||||
|
|
|
|
||||||
LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
|
LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ error[E0080]: it is undefined behavior to use this value
|
|||||||
--> $DIR/const-pointer-values-in-various-types.rs:60:5
|
--> $DIR/const-pointer-values-in-various-types.rs:60:5
|
||||||
|
|
|
|
||||||
LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
|
LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ error[E0080]: it is undefined behavior to use this value
|
|||||||
--> $DIR/const-pointer-values-in-various-types.rs:78:5
|
--> $DIR/const-pointer-values-in-various-types.rs:78:5
|
||||||
|
|
|
|
||||||
LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
|
LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
@ -184,7 +184,7 @@ error[E0080]: it is undefined behavior to use this value
|
|||||||
--> $DIR/const-pointer-values-in-various-types.rs:93:5
|
--> $DIR/const-pointer-values-in-various-types.rs:93:5
|
||||||
|
|
|
|
||||||
LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
|
LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ error[E0080]: it is undefined behavior to use this value
|
|||||||
--> $DIR/const-pointer-values-in-various-types.rs:102:5
|
--> $DIR/const-pointer-values-in-various-types.rs:102:5
|
||||||
|
|
|
|
||||||
LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
|
LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ error[E0080]: it is undefined behavior to use this value
|
|||||||
--> $DIR/issue-52442.rs:12:11
|
--> $DIR/issue-52442.rs:12:11
|
||||||
|
|
|
|
||||||
LL | [(); { &loop { break } as *const _ as usize } ]; //~ ERROR unimplemented expression type
|
LL | [(); { &loop { break } as *const _ as usize } ]; //~ ERROR unimplemented expression type
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
|
|||||||
--> $DIR/ref_to_int_match.rs:33:1
|
--> $DIR/ref_to_int_match.rs:33:1
|
||||||
|
|
|
|
||||||
LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; //~ ERROR it is undefined behavior to use this value
|
LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; //~ ERROR it is undefined behavior to use this value
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ error[E0080]: it is undefined behavior to use this value
|
|||||||
--> $DIR/ub-enum.rs:51:1
|
--> $DIR/ub-enum.rs:51:1
|
||||||
|
|
|
|
||||||
LL | const BAD_ENUM_UNDEF: [Enum2; 2] = [unsafe { TransmuteEnum2 { in3: () }.out1 }; 2];
|
LL | const BAD_ENUM_UNDEF: [Enum2; 2] = [unsafe { TransmuteEnum2 { in3: () }.out1 }; 2];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to read undefined bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at [0], but expected a valid enum discriminant
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value
|
|||||||
--> $DIR/ub-ref.rs:22:1
|
--> $DIR/ub-ref.rs:22:1
|
||||||
|
|
|
|
||||||
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
|
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ error[E0080]: it is undefined behavior to use this value
|
|||||||
--> $DIR/ub-ref.rs:25:1
|
--> $DIR/ub-ref.rs:25:1
|
||||||
|
|
|
|
||||||
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, but expected plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ LL | / const FIELD_PATH: Struct = Struct { //~ ERROR it is undefined behavior to
|
|||||||
LL | | a: 42,
|
LL | | a: 42,
|
||||||
LL | | b: unsafe { UNION.field3 },
|
LL | | b: unsafe { UNION.field3 },
|
||||||
LL | | };
|
LL | | };
|
||||||
| |__^ type validation failed: encountered uninitialized bytes at .b, but expected initialized plain bits
|
| |__^ type validation failed: encountered uninitialized bytes at .b, but expected initialized plain (non-pointer) bytes
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user