java-topology/defects/rustc/patch/rustc-0001-0002-evalstack-swapremove.patch

65 lines
2.7 KiB
Diff

# UNDF: UNDF-2026-000000771
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index c935869..9218cd1 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -1,9 +1,34 @@
+use rustc_data_structures::fx::FxHashSet;
use rustc_macros::HashStable;
use smallvec::SmallVec;
use tracing::instrument;
use crate::ty::{self, DefId, OpaqueTypeKey, Ty, TyCtxt, TypingEnv};
+/// Stack for cycle detection in `apply_inner`.
+/// Wraps SmallVec (for push/pop LIFO order) with FxHashSet (for O(1) contains).
+/// CWE-407 fix: SmallVec::contains is O(n); FxHashSet::contains is O(1).
+#[derive(Default)]
+struct EvalStack<'tcx> {
+ vec: SmallVec<[Ty<'tcx>; 1]>,
+ set: FxHashSet<Ty<'tcx>>,
+}
+
+impl<'tcx> EvalStack<'tcx> {
+ fn contains(&self, t: &Ty<'tcx>) -> bool {
+ self.set.contains(t)
+ }
+ fn push(&mut self, t: Ty<'tcx>) {
+ self.vec.push(t);
+ self.set.insert(t);
+ }
+ fn pop(&mut self) {
+ if let Some(t) = self.vec.pop() {
+ self.set.remove(&t);
+ }
+ }
+}
+
/// Represents whether some type is inhabited in a given context.
/// Examples of uninhabited types are `!`, `enum Void {}`, or a struct
/// containing either of those types.
@@ -82,7 +107,7 @@ fn apply_inner<E: std::fmt::Debug>(
self,
tcx: TyCtxt<'tcx>,
typing_env: TypingEnv<'tcx>,
- eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, // for cycle detection
+ eval_stack: &mut EvalStack<'tcx>, // for cycle detection; Set-backed for O(1) contains
in_module: &impl Fn(DefId) -> Result<bool, E>,
reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>,
) -> Result<bool, E> {
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index 8462471..713fec3 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -66,8 +66,10 @@ fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
vec = &mut self.blanket_impls;
}
+ // CWE-407 partial fix: swap_remove is O(1) vs remove's O(n) shift.
+ // position() scan is still O(n); full O(1) requires Children to use IndexSet<DefId>.
let index = vec.iter().position(|d| *d == impl_def_id).unwrap();
- vec.remove(index);
+ vec.swap_remove(index);
}
/// Attempt to insert an impl into this set of children, while comparing for