1
Fork 0

const validation: point at where we found a pointer but expected an integer

This commit is contained in:
Ralf Jung 2023-08-02 16:14:36 +02:00
parent 7637653b9f
commit 7767cbb3b0
34 changed files with 544 additions and 408 deletions

View file

@ -15,9 +15,6 @@ const_eval_await_non_const =
cannot convert `{$ty}` into a future in {const_eval_const_context}s
const_eval_bounds_check_failed =
indexing out of bounds: the len is {$len} but the index is {$index}
const_eval_box_to_mut = {$front_matter}: encountered a box pointing to mutable memory in a constant
const_eval_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant
const_eval_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty}
const_eval_call_nonzero_intrinsic =
`{$name}` called on 0
@ -41,18 +38,12 @@ const_eval_const_context = {$kind ->
const_eval_copy_nonoverlapping_overlapping =
`copy_nonoverlapping` called on overlapping ranges
const_eval_dangling_box_no_provenance = {$front_matter}: encountered a dangling box ({$pointer} has no provenance)
const_eval_dangling_box_out_of_bounds = {$front_matter}: encountered a dangling box (going beyond the bounds of its allocation)
const_eval_dangling_box_use_after_free = {$front_matter}: encountered a dangling box (use-after-free)
const_eval_dangling_int_pointer =
{$bad_pointer_message}: {$pointer} is a dangling pointer (it has no provenance)
const_eval_dangling_null_pointer =
{$bad_pointer_message}: null pointer is a dangling pointer (it has no provenance)
const_eval_dangling_ptr_in_final = encountered dangling pointer in final constant
const_eval_dangling_ref_no_provenance = {$front_matter}: encountered a dangling reference ({$pointer} has no provenance)
const_eval_dangling_ref_out_of_bounds = {$front_matter}: encountered a dangling reference (going beyond the bounds of its allocation)
const_eval_dangling_ref_use_after_free = {$front_matter}: encountered a dangling reference (use-after-free)
const_eval_dead_local =
accessing a dead local variable
const_eval_dealloc_immutable =
@ -105,7 +96,6 @@ const_eval_error = {$error_kind ->
const_eval_exact_div_has_remainder =
exact_div: {$a} cannot be divided by {$b} without remainder
const_eval_expected_non_ptr = {$front_matter}: encountered `{$value}`, but expected plain (non-pointer) bytes
const_eval_fn_ptr_call =
function pointers need an RFC before allowed to be called in {const_eval_const_context}s
const_eval_for_loop_into_iter_non_const =
@ -156,8 +146,6 @@ const_eval_invalid_align_details =
const_eval_invalid_bool =
interpreting an invalid 8-bit value as a bool: 0x{$value}
const_eval_invalid_box_meta = {$front_matter}: encountered invalid box metadata: total size is bigger than largest supported object
const_eval_invalid_box_slice_meta = {$front_matter}: encountered invalid box metadata: slice is bigger than largest supported object
const_eval_invalid_char =
interpreting an invalid 32-bit value as a char: 0x{$value}
const_eval_invalid_dealloc =
@ -168,16 +156,12 @@ const_eval_invalid_dealloc =
*[other] {""}
}
const_eval_invalid_enum_tag = {$front_matter}: encountered {$value}, but expected a valid enum tag
const_eval_invalid_fn_ptr = {$front_matter}: encountered {$value}, but expected a function pointer
const_eval_invalid_function_pointer =
using {$pointer} as function pointer but it does not point to a function
const_eval_invalid_meta =
invalid metadata in wide pointer: total size is bigger than largest supported object
const_eval_invalid_meta_slice =
invalid metadata in wide pointer: slice is bigger than largest supported object
const_eval_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
const_eval_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
const_eval_invalid_str =
this string is not valid UTF-8: {$err}
const_eval_invalid_tag =
@ -189,14 +173,10 @@ const_eval_invalid_uninit_bytes =
reading memory at {$alloc}{$access}, but memory is uninitialized at {$uninit}, and this operation requires initialized memory
const_eval_invalid_uninit_bytes_unknown =
using uninitialized data, but this operation requires initialized memory
const_eval_invalid_value = constructing invalid value
const_eval_invalid_value_with_path = constructing invalid value at {$path}
## The `front_matter`s here refer to either `middle_invalid_value` or `middle_invalid_value_with_path`.
const_eval_invalid_vtable_pointer =
using {$pointer} as vtable pointer but it does not point to a vtable
const_eval_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
const_eval_live_drop =
destructor of `{$dropped_ty}` cannot be evaluated at compile-time
@ -218,14 +198,13 @@ const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant
const_eval_memory_access_test = memory access failed
const_eval_memory_exhausted =
tried to allocate more memory than available to compiler
const_eval_modified_global =
modifying a static's initial value from another static's initializer
const_eval_mut_deref =
mutation through a reference is not allowed in {const_eval_const_context}s
const_eval_mutable_ref_in_const = {$front_matter}: encountered mutable reference in a `const`
const_eval_never_val = {$front_matter}: encountered a value of the never type `!`
const_eval_non_const_fmt_macro_call =
cannot call non-const formatting macro in {const_eval_const_context}s
@ -241,10 +220,6 @@ const_eval_noreturn_asm_returned =
const_eval_not_enough_caller_args =
calling a function with fewer arguments than it requires
const_eval_null_box = {$front_matter}: encountered a null box
const_eval_null_fn_ptr = {$front_matter}: encountered a null function pointer
const_eval_null_ref = {$front_matter}: encountered a null reference
const_eval_nullable_ptr_out_of_range = {$front_matter}: encountered a potentially null pointer, but expected something that cannot possibly fail to be {$in_range}
const_eval_nullary_intrinsic_fail =
could not evaluate nullary intrinsic
@ -257,7 +232,6 @@ const_eval_offset_from_underflow =
const_eval_operator_non_const =
cannot call non-const operator in {const_eval_const_context}s
const_eval_out_of_range = {$front_matter}: encountered {$value}, but expected something {$in_range}
const_eval_overflow =
overflow executing `{$name}`
@ -287,7 +261,6 @@ const_eval_ptr_as_bytes_1 =
this code performed an operation that depends on the underlying bytes representing a pointer
const_eval_ptr_as_bytes_2 =
the absolute address of a pointer is not known at compile-time, so such operations are not supported
const_eval_ptr_out_of_range = {$front_matter}: encountered a pointer, but expected something that cannot possibly fail to be {$in_range}
const_eval_question_branch_non_const =
`?` cannot determine the branch of `{$ty}` in {const_eval_const_context}s
@ -315,8 +288,8 @@ const_eval_raw_ptr_to_int =
const_eval_read_extern_static =
cannot read from extern static ({$did})
const_eval_read_pointer_as_bytes =
unable to turn pointer into raw bytes
const_eval_read_pointer_as_int =
unable to turn pointer into integer
const_eval_realloc_or_alloc_with_offset =
{$kind ->
[dealloc] deallocating
@ -324,9 +297,6 @@ const_eval_realloc_or_alloc_with_offset =
*[other] {""}
} {$ptr} which does not point to the beginning of an object
const_eval_ref_to_mut = {$front_matter}: encountered a reference pointing to mutable memory in a constant
const_eval_ref_to_static = {$front_matter}: encountered a reference pointing to a static variable in a constant
const_eval_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty}
const_eval_remainder_by_zero =
calculating the remainder with a divisor of zero
const_eval_remainder_overflow =
@ -363,8 +333,6 @@ const_eval_transient_mut_borrow_raw = raw mutable references are not allowed in
const_eval_try_block_from_output_non_const =
`try` block cannot convert `{$ty}` to the result in {const_eval_const_context}s
const_eval_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})
const_eval_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})
const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {const_eval_const_context}s
const_eval_unallowed_heap_allocations =
@ -408,29 +376,14 @@ const_eval_undefined_behavior =
const_eval_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 rustc repository if you believe it should not be considered undefined behavior.
const_eval_uninhabited_enum_tag = {$front_matter}: encountered an uninhabited enum variant
const_eval_uninhabited_enum_variant_read =
read discriminant of an uninhabited enum variant
const_eval_uninhabited_enum_variant_written =
writing discriminant of an uninhabited enum variant
const_eval_uninhabited_val = {$front_matter}: encountered a value of uninhabited type `{$ty}`
const_eval_uninit = {$front_matter}: encountered uninitialized bytes
const_eval_uninit_bool = {$front_matter}: encountered uninitialized memory, but expected a boolean
const_eval_uninit_box = {$front_matter}: encountered uninitialized memory, but expected a box
const_eval_uninit_char = {$front_matter}: encountered uninitialized memory, but expected a unicode scalar value
const_eval_uninit_enum_tag = {$front_matter}: encountered uninitialized bytes, but expected a valid enum tag
const_eval_uninit_float = {$front_matter}: encountered uninitialized memory, but expected a floating point number
const_eval_uninit_fn_ptr = {$front_matter}: encountered uninitialized memory, but expected a function pointer
const_eval_uninit_init_scalar = {$front_matter}: encountered uninitialized memory, but expected initialized scalar value
const_eval_uninit_int = {$front_matter}: encountered uninitialized memory, but expected an integer
const_eval_uninit_raw_ptr = {$front_matter}: encountered uninitialized memory, but expected a raw pointer
const_eval_uninit_ref = {$front_matter}: encountered uninitialized memory, but expected a reference
const_eval_uninit_str = {$front_matter}: encountered uninitialized data in `str`
const_eval_unreachable = entering unreachable code
const_eval_unreachable_unwind =
unwinding past a stack frame that does not allow unwinding
const_eval_unsafe_cell = {$front_matter}: encountered `UnsafeCell` in a `const`
const_eval_unsigned_offset_from_overflow =
`ptr_offset_from_unsigned` called when first pointer has smaller offset than second: {$a_offset} < {$b_offset}
@ -453,8 +406,63 @@ const_eval_unwind_past_top =
const_eval_upcast_mismatch =
upcast on a pointer whose vtable does not match its type
## The `front_matter`s here refer to either `const_eval_front_matter_invalid_value` or `const_eval_front_matter_invalid_value_with_path`.
## (We'd love to sort this differently to make that more clear but tidy won't let us...)
const_eval_validation_box_to_mut = {$front_matter}: encountered a box pointing to mutable memory in a constant
const_eval_validation_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant
const_eval_validation_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty}
const_eval_validation_dangling_box_no_provenance = {$front_matter}: encountered a dangling box ({$pointer} has no provenance)
const_eval_validation_dangling_box_out_of_bounds = {$front_matter}: encountered a dangling box (going beyond the bounds of its allocation)
const_eval_validation_dangling_box_use_after_free = {$front_matter}: encountered a dangling box (use-after-free)
const_eval_validation_dangling_ref_no_provenance = {$front_matter}: encountered a dangling reference ({$pointer} has no provenance)
const_eval_validation_dangling_ref_out_of_bounds = {$front_matter}: encountered a dangling reference (going beyond the bounds of its allocation)
const_eval_validation_dangling_ref_use_after_free = {$front_matter}: encountered a dangling reference (use-after-free)
const_eval_validation_expected_bool = expected a boolean
const_eval_validation_expected_box = expected a box
const_eval_validation_expected_char = expected a unicode scalar value
const_eval_validation_expected_enum_tag = expected a valid enum tag
const_eval_validation_expected_float = expected a floating point number
const_eval_validation_expected_fn_ptr = expected a function pointer
const_eval_validation_expected_init_scalar = expected initialized scalar value
const_eval_validation_expected_int = expected an integer
const_eval_validation_expected_raw_ptr = expected a raw pointer
const_eval_validation_expected_ref = expected a reference
const_eval_validation_expected_str = expected a string
const_eval_validation_front_matter_invalid_value = constructing invalid value
const_eval_validation_front_matter_invalid_value_with_path = constructing invalid value at {$path}
const_eval_validation_invalid_bool = {$front_matter}: encountered {$value}, but expected a boolean
const_eval_validation_invalid_box_meta = {$front_matter}: encountered invalid box metadata: total size is bigger than largest supported object
const_eval_validation_invalid_box_slice_meta = {$front_matter}: encountered invalid box metadata: slice is bigger than largest supported object
const_eval_validation_invalid_char = {$front_matter}: encountered {$value}, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
const_eval_validation_invalid_enum_tag = {$front_matter}: encountered {$value}, but expected a valid enum tag
const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, but expected a function pointer
const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
const_eval_validation_mutable_ref_in_const = {$front_matter}: encountered mutable reference in a `const`
const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!`
const_eval_validation_null_box = {$front_matter}: encountered a null box
const_eval_validation_null_fn_ptr = {$front_matter}: encountered a null function pointer
const_eval_validation_null_ref = {$front_matter}: encountered a null reference
const_eval_validation_nullable_ptr_out_of_range = {$front_matter}: encountered a potentially null pointer, but expected something that cannot possibly fail to be {$in_range}
const_eval_validation_out_of_range = {$front_matter}: encountered {$value}, but expected something {$in_range}
const_eval_validation_partial_pointer = {$front_matter}: encountered a partial pointer or a mix of pointers
const_eval_validation_pointer_as_int = {$front_matter}: encountered a pointer, but {$expected}
const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer, but expected something that cannot possibly fail to be {$in_range}
const_eval_validation_ref_to_mut = {$front_matter}: encountered a reference pointing to mutable memory in a constant
const_eval_validation_ref_to_static = {$front_matter}: encountered a reference pointing to a static variable in a constant
const_eval_validation_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty}
const_eval_validation_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})
const_eval_validation_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})
const_eval_validation_uninhabited_enum_variant = {$front_matter}: encountered an uninhabited enum variant
const_eval_validation_uninhabited_val = {$front_matter}: encountered a value of uninhabited type `{$ty}`
const_eval_validation_uninit = {$front_matter}: encountered uninitialized memory, but {$expected}
const_eval_validation_unsafe_cell = {$front_matter}: encountered `UnsafeCell` in a `const`
const_eval_write_to_read_only =
writing to {$allocation} which is read-only
const_eval_zst_pointer_out_of_bounds =

View file

@ -513,7 +513,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch,
UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written,
UninhabitedEnumVariantRead(_) => const_eval_uninhabited_enum_variant_read,
Validation(e) => e.diagnostic_message(),
ValidationError(e) => e.diagnostic_message(),
Custom(x) => (x.msg)(),
}
}
@ -587,13 +587,13 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
InvalidUninitBytes(Some((alloc, info))) => {
builder.set_arg("alloc", alloc);
builder.set_arg("access", info.access);
builder.set_arg("uninit", info.uninit);
builder.set_arg("uninit", info.bad);
}
ScalarSizeMismatch(info) => {
builder.set_arg("target_size", info.target_size);
builder.set_arg("data_size", info.data_size);
}
Validation(e) => e.add_args(handler, builder),
ValidationError(e) => e.add_args(handler, builder),
Custom(custom) => {
(custom.add_args)(&mut |name, value| {
builder.set_arg(name, value);
@ -608,74 +608,72 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
use crate::fluent_generated::*;
use rustc_middle::mir::interpret::ValidationErrorKind::*;
match self.kind {
PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => const_eval_box_to_uninhabited,
PtrToUninhabited { ptr_kind: PointerKind::Ref, .. } => const_eval_ref_to_uninhabited,
PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => {
const_eval_validation_box_to_uninhabited
}
PtrToUninhabited { ptr_kind: PointerKind::Ref, .. } => {
const_eval_validation_ref_to_uninhabited
}
PtrToStatic { ptr_kind: PointerKind::Box } => const_eval_box_to_static,
PtrToStatic { ptr_kind: PointerKind::Ref } => const_eval_ref_to_static,
PtrToStatic { ptr_kind: PointerKind::Box } => const_eval_validation_box_to_static,
PtrToStatic { ptr_kind: PointerKind::Ref } => const_eval_validation_ref_to_static,
PtrToMut { ptr_kind: PointerKind::Box } => const_eval_box_to_mut,
PtrToMut { ptr_kind: PointerKind::Ref } => const_eval_ref_to_mut,
PtrToMut { ptr_kind: PointerKind::Box } => const_eval_validation_box_to_mut,
PtrToMut { ptr_kind: PointerKind::Ref } => const_eval_validation_ref_to_mut,
ExpectedNonPtr { .. } => const_eval_expected_non_ptr,
MutableRefInConst => const_eval_mutable_ref_in_const,
NullFnPtr => const_eval_null_fn_ptr,
NeverVal => const_eval_never_val,
NullablePtrOutOfRange { .. } => const_eval_nullable_ptr_out_of_range,
PtrOutOfRange { .. } => const_eval_ptr_out_of_range,
OutOfRange { .. } => const_eval_out_of_range,
UnsafeCell => const_eval_unsafe_cell,
UninhabitedVal { .. } => const_eval_uninhabited_val,
InvalidEnumTag { .. } => const_eval_invalid_enum_tag,
UninhabitedEnumTag => const_eval_uninhabited_enum_tag,
UninitEnumTag => const_eval_uninit_enum_tag,
UninitStr => const_eval_uninit_str,
Uninit { expected: ExpectedKind::Bool } => const_eval_uninit_bool,
Uninit { expected: ExpectedKind::Reference } => const_eval_uninit_ref,
Uninit { expected: ExpectedKind::Box } => const_eval_uninit_box,
Uninit { expected: ExpectedKind::RawPtr } => const_eval_uninit_raw_ptr,
Uninit { expected: ExpectedKind::InitScalar } => const_eval_uninit_init_scalar,
Uninit { expected: ExpectedKind::Char } => const_eval_uninit_char,
Uninit { expected: ExpectedKind::Float } => const_eval_uninit_float,
Uninit { expected: ExpectedKind::Int } => const_eval_uninit_int,
Uninit { expected: ExpectedKind::FnPtr } => const_eval_uninit_fn_ptr,
UninitVal => const_eval_uninit,
InvalidVTablePtr { .. } => const_eval_invalid_vtable_ptr,
PointerAsInt { .. } => const_eval_validation_pointer_as_int,
PartialPointer => const_eval_validation_partial_pointer,
MutableRefInConst => const_eval_validation_mutable_ref_in_const,
NullFnPtr => const_eval_validation_null_fn_ptr,
NeverVal => const_eval_validation_never_val,
NullablePtrOutOfRange { .. } => const_eval_validation_nullable_ptr_out_of_range,
PtrOutOfRange { .. } => const_eval_validation_ptr_out_of_range,
OutOfRange { .. } => const_eval_validation_out_of_range,
UnsafeCell => const_eval_validation_unsafe_cell,
UninhabitedVal { .. } => const_eval_validation_uninhabited_val,
InvalidEnumTag { .. } => const_eval_validation_invalid_enum_tag,
UninhabitedEnumVariant => const_eval_validation_uninhabited_enum_variant,
Uninit { .. } => const_eval_validation_uninit,
InvalidVTablePtr { .. } => const_eval_validation_invalid_vtable_ptr,
InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => {
const_eval_invalid_box_slice_meta
const_eval_validation_invalid_box_slice_meta
}
InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Ref } => {
const_eval_invalid_ref_slice_meta
const_eval_validation_invalid_ref_slice_meta
}
InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => const_eval_invalid_box_meta,
InvalidMetaTooLarge { ptr_kind: PointerKind::Ref } => const_eval_invalid_ref_meta,
UnalignedPtr { ptr_kind: PointerKind::Ref, .. } => const_eval_unaligned_ref,
UnalignedPtr { ptr_kind: PointerKind::Box, .. } => const_eval_unaligned_box,
InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => {
const_eval_validation_invalid_box_meta
}
InvalidMetaTooLarge { ptr_kind: PointerKind::Ref } => {
const_eval_validation_invalid_ref_meta
}
UnalignedPtr { ptr_kind: PointerKind::Ref, .. } => const_eval_validation_unaligned_ref,
UnalignedPtr { ptr_kind: PointerKind::Box, .. } => const_eval_validation_unaligned_box,
NullPtr { ptr_kind: PointerKind::Box } => const_eval_null_box,
NullPtr { ptr_kind: PointerKind::Ref } => const_eval_null_ref,
NullPtr { ptr_kind: PointerKind::Box } => const_eval_validation_null_box,
NullPtr { ptr_kind: PointerKind::Ref } => const_eval_validation_null_ref,
DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => {
const_eval_dangling_box_no_provenance
const_eval_validation_dangling_box_no_provenance
}
DanglingPtrNoProvenance { ptr_kind: PointerKind::Ref, .. } => {
const_eval_dangling_ref_no_provenance
const_eval_validation_dangling_ref_no_provenance
}
DanglingPtrOutOfBounds { ptr_kind: PointerKind::Box } => {
const_eval_dangling_box_out_of_bounds
const_eval_validation_dangling_box_out_of_bounds
}
DanglingPtrOutOfBounds { ptr_kind: PointerKind::Ref } => {
const_eval_dangling_ref_out_of_bounds
const_eval_validation_dangling_ref_out_of_bounds
}
DanglingPtrUseAfterFree { ptr_kind: PointerKind::Box } => {
const_eval_dangling_box_use_after_free
const_eval_validation_dangling_box_use_after_free
}
DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref } => {
const_eval_dangling_ref_use_after_free
const_eval_validation_dangling_ref_use_after_free
}
InvalidBool { .. } => const_eval_validation_invalid_bool,
InvalidChar { .. } => const_eval_validation_invalid_char,
InvalidFnPtr { .. } => const_eval_invalid_fn_ptr,
InvalidFnPtr { .. } => const_eval_validation_invalid_fn_ptr,
}
}
@ -683,13 +681,21 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
use crate::fluent_generated as fluent;
use rustc_middle::mir::interpret::ValidationErrorKind::*;
if let PointerAsInt { .. } | PartialPointer = self.kind {
err.help(fluent::const_eval_ptr_as_bytes_1);
err.help(fluent::const_eval_ptr_as_bytes_2);
}
let message = if let Some(path) = self.path {
handler.eagerly_translate_to_string(
fluent::const_eval_invalid_value_with_path,
fluent::const_eval_validation_front_matter_invalid_value_with_path,
[("path".into(), DiagnosticArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)),
)
} else {
handler.eagerly_translate_to_string(fluent::const_eval_invalid_value, [].into_iter())
handler.eagerly_translate_to_string(
fluent::const_eval_validation_front_matter_invalid_value,
[].into_iter(),
)
};
err.set_arg("front_matter", message);
@ -729,8 +735,24 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
PtrToUninhabited { ty, .. } | UninhabitedVal { ty } => {
err.set_arg("ty", ty);
}
ExpectedNonPtr { value }
| InvalidEnumTag { value }
PointerAsInt { expected } | Uninit { expected } => {
let msg = match expected {
ExpectedKind::Reference => fluent::const_eval_validation_expected_ref,
ExpectedKind::Box => fluent::const_eval_validation_expected_box,
ExpectedKind::RawPtr => fluent::const_eval_validation_expected_raw_ptr,
ExpectedKind::InitScalar => fluent::const_eval_validation_expected_init_scalar,
ExpectedKind::Bool => fluent::const_eval_validation_expected_bool,
ExpectedKind::Char => fluent::const_eval_validation_expected_char,
ExpectedKind::Float => fluent::const_eval_validation_expected_float,
ExpectedKind::Int => fluent::const_eval_validation_expected_int,
ExpectedKind::FnPtr => fluent::const_eval_validation_expected_fn_ptr,
ExpectedKind::EnumTag => fluent::const_eval_validation_expected_enum_tag,
ExpectedKind::Str => fluent::const_eval_validation_expected_str,
};
let msg = handler.eagerly_translate_to_string(msg, [].into_iter());
err.set_arg("expected", msg);
}
InvalidEnumTag { value }
| InvalidVTablePtr { value }
| InvalidBool { value }
| InvalidChar { value }
@ -758,15 +780,12 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
| NullFnPtr
| NeverVal
| UnsafeCell
| UninitEnumTag
| UninitStr
| Uninit { .. }
| UninitVal
| InvalidMetaSliceTooLarge { .. }
| InvalidMetaTooLarge { .. }
| DanglingPtrUseAfterFree { .. }
| DanglingPtrOutOfBounds { .. }
| UninhabitedEnumTag => {}
| UninhabitedEnumVariant
| PartialPointer => {}
}
}
}
@ -776,9 +795,9 @@ impl ReportErrorExt for UnsupportedOpInfo {
use crate::fluent_generated::*;
match self {
UnsupportedOpInfo::Unsupported(s) => s.clone().into(),
UnsupportedOpInfo::PartialPointerOverwrite(_) => const_eval_partial_pointer_overwrite,
UnsupportedOpInfo::PartialPointerCopy(_) => const_eval_partial_pointer_copy,
UnsupportedOpInfo::ReadPointerAsBytes => const_eval_read_pointer_as_bytes,
UnsupportedOpInfo::OverwritePartialPointer(_) => const_eval_partial_pointer_overwrite,
UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_copy,
UnsupportedOpInfo::ReadPointerAsInt(_) => const_eval_read_pointer_as_int,
UnsupportedOpInfo::ThreadLocalStatic(_) => const_eval_thread_local_static,
UnsupportedOpInfo::ReadExternStatic(_) => const_eval_read_extern_static,
}
@ -787,13 +806,16 @@ impl ReportErrorExt for UnsupportedOpInfo {
use crate::fluent_generated::*;
use UnsupportedOpInfo::*;
if let ReadPointerAsBytes | PartialPointerOverwrite(_) | PartialPointerCopy(_) = self {
if let ReadPointerAsInt(_) | OverwritePartialPointer(_) | ReadPartialPointer(_) = self {
builder.help(const_eval_ptr_as_bytes_1);
builder.help(const_eval_ptr_as_bytes_2);
}
match self {
Unsupported(_) | ReadPointerAsBytes => {}
PartialPointerOverwrite(ptr) | PartialPointerCopy(ptr) => {
// `ReadPointerAsInt(Some(info))` is never printed anyway, it only serves as an error to
// be further processed by validity checking which then turns it into something nice to
// print. So it's not worth the effort of having diagnostics that can print the `info`.
Unsupported(_) | ReadPointerAsInt(_) => {}
OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => {
builder.set_arg("ptr", ptr);
}
ThreadLocalStatic(did) | ReadExternStatic(did) => {

View file

@ -25,13 +25,17 @@ use rustc_target::abi::{
use std::hash::Hash;
// for the validation errors
use super::UndefinedBehaviorInfo::*;
use super::{
AllocId, CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy,
Machine, MemPlaceMeta, OpTy, Pointer, Projectable, Scalar, ValueVisitor,
};
// for the validation errors
use super::InterpError::UndefinedBehavior as Ub;
use super::InterpError::Unsupported as Unsup;
use super::UndefinedBehaviorInfo::*;
use super::UnsupportedOpInfo::*;
macro_rules! throw_validation_failure {
($where:expr, $kind: expr) => {{
let where_ = &$where;
@ -43,7 +47,7 @@ macro_rules! throw_validation_failure {
None
};
throw_ub!(Validation(ValidationErrorInfo { path, kind: $kind }))
throw_ub!(ValidationError(ValidationErrorInfo { path, kind: $kind }))
}};
}
@ -85,16 +89,16 @@ macro_rules! try_validation {
Ok(x) => x,
// We catch the error and turn it into a validation failure. We are okay with
// allocation here as this can only slow down builds that fail anyway.
Err(e) => match e.into_parts() {
Err(e) => match e.kind() {
$(
(InterpError::UndefinedBehavior($($p)|+), _) =>
$($p)|+ =>
throw_validation_failure!(
$where,
$kind
)
),+,
#[allow(unreachable_patterns)]
(e, rest) => Err::<!, _>($crate::interpret::InterpErrorInfo::from_parts(e, rest))?,
_ => Err::<!, _>(e)?,
}
}
}};
@ -294,7 +298,13 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
Ok(try_validation!(
self.ecx.read_immediate(op),
self.path,
InvalidUninitBytes(None) => Uninit { expected }
Ub(InvalidUninitBytes(None)) =>
Uninit { expected },
// The `Unsup` cases can only occur during CTFE
Unsup(ReadPointerAsInt(_)) =>
PointerAsInt { expected },
Unsup(ReadPartialPointer(_)) =>
PartialPointer,
))
}
@ -319,8 +329,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
let (_ty, _trait) = try_validation!(
self.ecx.get_ptr_vtable(vtable),
self.path,
DanglingIntPointer(..) |
InvalidVTablePointer(..) => InvalidVTablePtr { value: format!("{vtable}") }
Ub(DanglingIntPointer(..) | InvalidVTablePointer(..)) =>
InvalidVTablePtr { value: format!("{vtable}") }
);
// FIXME: check if the type/trait match what ty::Dynamic says?
}
@ -356,7 +366,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
let size_and_align = try_validation!(
self.ecx.size_and_align_of_mplace(&place),
self.path,
InvalidMeta(msg) => match msg {
Ub(InvalidMeta(msg)) => match msg {
InvalidMetaKind::SliceTooBig => InvalidMetaSliceTooLarge { ptr_kind },
InvalidMetaKind::TooBig => InvalidMetaTooLarge { ptr_kind },
}
@ -375,23 +385,23 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
CheckInAllocMsg::InboundsTest, // will anyway be replaced by validity message
),
self.path,
AlignmentCheckFailed { required, has } => UnalignedPtr {
Ub(AlignmentCheckFailed { required, has }) => UnalignedPtr {
ptr_kind,
required_bytes: required.bytes(),
found_bytes: has.bytes()
},
DanglingIntPointer(0, _) => NullPtr { ptr_kind },
DanglingIntPointer(i, _) => DanglingPtrNoProvenance {
Ub(DanglingIntPointer(0, _)) => NullPtr { ptr_kind },
Ub(DanglingIntPointer(i, _)) => DanglingPtrNoProvenance {
ptr_kind,
// FIXME this says "null pointer" when null but we need translate
pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(i))
pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(*i))
},
PointerOutOfBounds { .. } => DanglingPtrOutOfBounds {
Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds {
ptr_kind
},
// This cannot happen during const-eval (because interning already detects
// dangling pointers), but it can happen in Miri.
PointerUseAfterFree(..) => DanglingPtrUseAfterFree {
Ub(PointerUseAfterFree(..)) => DanglingPtrUseAfterFree {
ptr_kind,
},
);
@ -477,7 +487,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
try_validation!(
value.to_bool(),
self.path,
InvalidBool(..) => ValidationErrorKind::InvalidBool {
Ub(InvalidBool(..)) => ValidationErrorKind::InvalidBool {
value: format!("{value:x}"),
}
);
@ -488,7 +498,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
try_validation!(
value.to_char(),
self.path,
InvalidChar(..) => ValidationErrorKind::InvalidChar {
Ub(InvalidChar(..)) => ValidationErrorKind::InvalidChar {
value: format!("{value:x}"),
}
);
@ -497,7 +507,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
// NOTE: Keep this in sync with the array optimization for int/float
// types below!
let value = self.read_scalar(
self.read_scalar(
value,
if matches!(ty.kind(), ty::Float(..)) {
ExpectedKind::Float
@ -505,14 +515,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
ExpectedKind::Int
},
)?;
// As a special exception we *do* match on a `Scalar` here, since we truly want
// to know its underlying representation (and *not* cast it to an integer).
if matches!(value, Scalar::Ptr(..)) {
throw_validation_failure!(
self.path,
ExpectedNonPtr { value: format!("{value:x}") }
)
}
Ok(true)
}
ty::RawPtr(..) => {
@ -546,10 +548,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
let _fn = try_validation!(
self.ecx.get_ptr_fn(ptr),
self.path,
DanglingIntPointer(..) |
InvalidFunctionPointer(..) => InvalidFnPtr {
value: format!("{ptr}"),
},
Ub(DanglingIntPointer(..) | InvalidFunctionPointer(..)) =>
InvalidFnPtr { value: format!("{ptr}") },
);
// FIXME: Check if the signature matches
} else {
@ -657,11 +657,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
Ok(try_validation!(
this.ecx.read_discriminant(op),
this.path,
InvalidTag(val) => InvalidEnumTag {
Ub(InvalidTag(val)) => InvalidEnumTag {
value: format!("{val:x}"),
},
UninhabitedEnumVariantRead(_) => UninhabitedEnumTag,
InvalidUninitBytes(None) => UninitEnumTag,
Ub(UninhabitedEnumVariantRead(_)) => UninhabitedEnumVariant,
// Uninit / bad provenance are not possible since the field was already previously
// checked at its integer type.
))
})
}
@ -740,7 +741,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
try_validation!(
self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr, Size::from_bytes(len)),
self.path,
InvalidUninitBytes(..) => { UninitStr },
Ub(InvalidUninitBytes(..)) => Uninit { expected: ExpectedKind::Str },
Unsup(ReadPointerAsInt(_)) => PointerAsInt { expected: ExpectedKind::Str }
);
}
ty::Array(tys, ..) | ty::Slice(tys)
@ -752,6 +754,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
if matches!(tys.kind(), ty::Int(..) | ty::Uint(..) | ty::Float(..))
=>
{
let expected = if tys.is_integral() { ExpectedKind::Int } else { ExpectedKind::Float };
// Optimized handling for arrays of integer/float type.
// This is the length of the array/slice.
@ -770,7 +773,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
Left(mplace) => mplace,
Right(imm) => match *imm {
Immediate::Uninit =>
throw_validation_failure!(self.path, UninitVal),
throw_validation_failure!(self.path, Uninit { expected }),
Immediate::Scalar(..) | Immediate::ScalarPair(..) =>
bug!("arrays/slices can never have Scalar/ScalarPair layout"),
}
@ -796,17 +799,21 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
// For some errors we might be able to provide extra information.
// (This custom logic does not fit the `try_validation!` macro.)
match err.kind() {
err_ub!(InvalidUninitBytes(Some((_alloc_id, access)))) => {
Ub(InvalidUninitBytes(Some((_alloc_id, access)))) | Unsup(ReadPointerAsInt(Some((_alloc_id, access)))) => {
// Some byte was uninitialized, determine which
// element that byte belongs to so we can
// provide an index.
let i = usize::try_from(
access.uninit.start.bytes() / layout.size.bytes(),
access.bad.start.bytes() / layout.size.bytes(),
)
.unwrap();
self.path.push(PathElem::ArrayElem(i));
throw_validation_failure!(self.path, UninitVal)
if matches!(err.kind(), Ub(InvalidUninitBytes(_))) {
throw_validation_failure!(self.path, Uninit { expected })
} else {
throw_validation_failure!(self.path, PointerAsInt { expected })
}
}
// Propagate upwards (that will also check for unexpected errors).
@ -892,17 +899,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Run it.
match visitor.visit_value(&op) {
Ok(()) => Ok(()),
// Pass through validation failures.
Err(err) if matches!(err.kind(), err_ub!(Validation { .. })) => Err(err),
// Complain about any other kind of UB error -- those are bad because we'd like to
// Pass through validation failures and "invalid program" issues.
Err(err)
if matches!(
err.kind(),
err_ub!(ValidationError { .. }) | InterpError::InvalidProgram(_)
) =>
{
Err(err)
}
// Complain about any other kind of error -- those are bad because we'd like to
// report them in a way that shows *where* in the value the issue lies.
Err(err) if matches!(err.kind(), InterpError::UndefinedBehavior(_)) => {
Err(err) => {
let (err, backtrace) = err.into_parts();
backtrace.print_backtrace();
bug!("Unexpected Undefined Behavior error during validation: {err:?}");
}
// Pass through everything else.
Err(err) => Err(err),
}
}