better document const-pattern dynamic soundness checks, and fix a soundness hole
This commit is contained in:
parent
db98d32ea0
commit
e8ffa2182b
@ -193,7 +193,7 @@ fn validate_and_turn_into_const<'tcx>(
|
|||||||
mplace.into(),
|
mplace.into(),
|
||||||
path,
|
path,
|
||||||
&mut ref_tracking,
|
&mut ref_tracking,
|
||||||
/*may_ref_to_static*/ is_static,
|
/*may_ref_to_static*/ ecx.memory.extra.can_access_statics,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,12 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct MemoryExtra {
|
pub struct MemoryExtra {
|
||||||
/// Whether this machine may read from statics
|
/// We need to make sure consts never point to anything mutable, even recursively. That is
|
||||||
|
/// relied on for pattern matching on consts with references.
|
||||||
|
/// To achieve this, two pieces have to work together:
|
||||||
|
/// * Interning makes everything outside of statics immutable.
|
||||||
|
/// * Pointers to allocations inside of statics can never leak outside, to a non-static global.
|
||||||
|
/// This boolean here controls the second part.
|
||||||
pub(super) can_access_statics: bool,
|
pub(super) can_access_statics: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,6 +342,8 @@ fn before_access_global(
|
|||||||
} else if static_def_id.is_some() {
|
} else if static_def_id.is_some() {
|
||||||
// Machine configuration does not allow us to read statics
|
// Machine configuration does not allow us to read statics
|
||||||
// (e.g., `const` initializer).
|
// (e.g., `const` initializer).
|
||||||
|
// See const_eval::machine::MemoryExtra::can_access_statics for why
|
||||||
|
// this check is so important.
|
||||||
Err(ConstEvalErrKind::ConstAccessesStatic.into())
|
Err(ConstEvalErrKind::ConstAccessesStatic.into())
|
||||||
} else {
|
} else {
|
||||||
// Immutable global, this read is fine.
|
// Immutable global, this read is fine.
|
||||||
|
@ -404,19 +404,27 @@ fn check_safe_pointer(
|
|||||||
// Skip validation entirely for some external statics
|
// Skip validation entirely for some external statics
|
||||||
let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id);
|
let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id);
|
||||||
if let Some(GlobalAlloc::Static(did)) = alloc_kind {
|
if let Some(GlobalAlloc::Static(did)) = alloc_kind {
|
||||||
// `extern static` cannot be validated as they have no body.
|
// See const_eval::machine::MemoryExtra::can_access_statics for why
|
||||||
// FIXME: Statics from other crates are also skipped.
|
// this check is so important.
|
||||||
// They might be checked at a different type, but for now we
|
// This check is reachable when the const just referenced the static,
|
||||||
// want to avoid recursing too deeply. This is not sound!
|
// but never read it (so we never entered `before_access_global`).
|
||||||
if !did.is_local() || self.ecx.tcx.is_foreign_item(did) {
|
// We also need to do it here instead of going on to avoid running
|
||||||
return Ok(());
|
// into the `before_access_global` check during validation.
|
||||||
}
|
|
||||||
if !self.may_ref_to_static && self.ecx.tcx.is_static(did) {
|
if !self.may_ref_to_static && self.ecx.tcx.is_static(did) {
|
||||||
throw_validation_failure!(
|
throw_validation_failure!(
|
||||||
format_args!("a {} pointing to a static variable", kind),
|
format_args!("a {} pointing to a static variable", kind),
|
||||||
self.path
|
self.path
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// `extern static` cannot be validated as they have no body.
|
||||||
|
// FIXME: Statics from other crates are also skipped.
|
||||||
|
// They might be checked at a different type, but for now we
|
||||||
|
// want to avoid recursing too deeply. We might miss const-invalid data,
|
||||||
|
// but things are still sound otherwise (in particular re: consts
|
||||||
|
// referring to statics).
|
||||||
|
if !did.is_local() || self.ecx.tcx.is_foreign_item(did) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Proceed recursively even for ZST, no reason to skip them!
|
// Proceed recursively even for ZST, no reason to skip them!
|
||||||
|
Loading…
Reference in New Issue
Block a user