Skip to content

Commit 0adc84b

Browse files
committed
Don't allow constant eval to access generator layouts
1 parent bb90f81 commit 0adc84b

File tree

15 files changed

+189
-7
lines changed

15 files changed

+189
-7
lines changed

compiler/rustc_const_eval/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ const_eval_frame_note_inner = inside {$where_ ->
112112
*[other] {""}
113113
}
114114
115+
const_eval_generator_layout_indirect = because of contained type `{$ty}`
116+
115117
const_eval_in_bounds_test = out-of-bounds pointer use
116118
const_eval_incompatible_calling_conventions =
117119
calling a function with calling convention {$callee_conv} using calling convention {$caller_conv}
@@ -431,6 +433,8 @@ const_eval_validation_expected_str = expected a string
431433
const_eval_validation_front_matter_invalid_value = constructing invalid value
432434
const_eval_validation_front_matter_invalid_value_with_path = constructing invalid value at {$path}
433435
436+
const_eval_validation_generator_layout_access = cannot compute layout of `{$ty}`
437+
434438
const_eval_validation_invalid_bool = {$front_matter}: encountered {$value}, but expected a boolean
435439
const_eval_validation_invalid_box_meta = {$front_matter}: encountered invalid box metadata: total size is bigger than largest supported object
436440
const_eval_validation_invalid_box_slice_meta = {$front_matter}: encountered invalid box metadata: slice is bigger than largest supported object

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
357357

358358
const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error
359359

360+
// We don't allow access to generator layout at compile time.
361+
const ACCESS_GENERATOR_LAYOUT: bool = false;
362+
360363
#[inline(always)]
361364
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
362365
ecx.machine.check_alignment

compiler/rustc_const_eval/src/errors.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
674674
InvalidBool { .. } => const_eval_validation_invalid_bool,
675675
InvalidChar { .. } => const_eval_validation_invalid_char,
676676
InvalidFnPtr { .. } => const_eval_validation_invalid_fn_ptr,
677+
GeneratorLayoutAccess { .. } => const_eval_validation_generator_layout_access,
677678
}
678679
}
679680

@@ -773,6 +774,20 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
773774
DanglingPtrNoProvenance { pointer, .. } => {
774775
err.set_arg("pointer", pointer);
775776
}
777+
GeneratorLayoutAccess { ty, generators } => {
778+
err.set_arg("ty", ty);
779+
for generator in generators {
780+
if generator != ty {
781+
let message = handler.eagerly_translate_to_string(
782+
fluent::const_eval_generator_layout_indirect,
783+
[("ty".into(), DiagnosticArgValue::Str(generator.to_string().into()))]
784+
.iter()
785+
.map(|(a, b)| (a, b)),
786+
);
787+
err.help(message);
788+
}
789+
}
790+
}
776791
NullPtr { .. }
777792
| PtrToStatic { .. }
778793
| PtrToMut { .. }

compiler/rustc_const_eval/src/interpret/machine.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
130130
/// Should the machine panic on allocation failures?
131131
const PANIC_ON_ALLOC_FAIL: bool;
132132

133+
/// Should the machine allow access to generator layout.
134+
const ACCESS_GENERATOR_LAYOUT: bool;
135+
133136
/// Whether memory accesses should be alignment-checked.
134137
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment;
135138

compiler/rustc_const_eval/src/interpret/step.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
267267

268268
NullaryOp(ref null_op, ty) => {
269269
let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?;
270+
271+
// Ensure we don't need the layout of any generators if applicable.
272+
// This prevents typeck from depending on MIR optimizations.
273+
self.validate_generator_layout_access(ty)?;
274+
270275
let layout = self.layout_of(ty)?;
271276
if let mir::NullOp::SizeOf | mir::NullOp::AlignOf = null_op && layout.is_unsized() {
272277
span_bug!(

compiler/rustc_const_eval/src/interpret/validity.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use rustc_middle::mir::interpret::{
1616
ExpectedKind, InterpError, InvalidMetaKind, PointerKind, ValidationErrorInfo,
1717
ValidationErrorKind, ValidationErrorKind::*,
1818
};
19-
use rustc_middle::ty;
2019
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
20+
use rustc_middle::ty::{self, Ty};
2121
use rustc_span::symbol::{sym, Symbol};
2222
use rustc_target::abi::{
2323
Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
@@ -950,4 +950,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
950950
// recurse through references which, for now, we don't want here, either.
951951
self.validate_operand_internal(op, vec![], None, None)
952952
}
953+
954+
/// This function checks if the given `ty`'s layout depends on generators.
955+
#[inline(always)]
956+
pub fn validate_generator_layout_access(&self, ty: Ty<'tcx>) -> InterpResult<'tcx> {
957+
if !M::ACCESS_GENERATOR_LAYOUT {
958+
let generators = self.tcx.layout_generators(ty);
959+
if !generators.is_empty() {
960+
throw_validation_failure!(Vec::new(), GeneratorLayoutAccess { ty, generators });
961+
}
962+
}
963+
Ok(())
964+
}
953965
}

compiler/rustc_middle/src/mir/interpret/error.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::{AllocId, AllocRange, ConstAlloc, Pointer, Scalar};
22

33
use crate::mir::interpret::ConstValue;
44
use crate::query::TyCtxtAt;
5-
use crate::ty::{layout, tls, Ty, ValTree};
5+
use crate::ty::{layout, tls, List, Ty, ValTree};
66

77
use rustc_data_structures::sync::Lock;
88
use rustc_errors::{
@@ -404,6 +404,7 @@ pub enum ValidationErrorKind<'tcx> {
404404
InvalidBool { value: String },
405405
InvalidChar { value: String },
406406
InvalidFnPtr { value: String },
407+
GeneratorLayoutAccess { ty: Ty<'tcx>, generators: &'tcx List<Ty<'tcx>> },
407408
}
408409

409410
/// Error information for when the program did something that might (or might not) be correct

compiler/rustc_middle/src/query/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,6 +1405,15 @@ rustc_queries! {
14051405
desc { "computing layout of `{}`", key.value }
14061406
}
14071407

1408+
/// Computes the generators present in the layout of a type.
1409+
/// This expects a normalized input type with regions erased.
1410+
query layout_generators(
1411+
key: Ty<'tcx>
1412+
) -> &'tcx ty::List<Ty<'tcx>> {
1413+
depth_limit
1414+
desc { "calculating generators in layout of `{}`", key }
1415+
}
1416+
14081417
/// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
14091418
///
14101419
/// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance`

compiler/rustc_mir_transform/src/const_prop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ impl ConstPropMachine<'_, '_> {
147147
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> {
148148
compile_time_machine!(<'mir, 'tcx>);
149149
const PANIC_ON_ALLOC_FAIL: bool = true; // all allocations are small (see `MAX_ALLOC_LIMIT`)
150+
const ACCESS_GENERATOR_LAYOUT: bool = true;
150151

151152
type MemoryKind = !;
152153

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm
512512
rustc_const_eval::interpret::compile_time_machine!(<'mir, 'tcx>);
513513
type MemoryKind = !;
514514
const PANIC_ON_ALLOC_FAIL: bool = true;
515+
const ACCESS_GENERATOR_LAYOUT: bool = true;
515516

516517
fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment {
517518
unimplemented!()

0 commit comments

Comments
 (0)