From 44e66b658f20c7e3282261d566086e9f2d5e16d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrique=20Carr=C3=A3o?= Date: Thu, 4 Apr 2024 20:36:50 +0100 Subject: [PATCH] Fix #121126: index out of bounds exceeds max value When indexing an array with an index (u32) that exceeds the maximum value allowed by FieldIdx (default: 0xFFFF_FF00), although the compiler would detect the error, it would also cause a panic, which is a bug. I fixed it by adding a verification before calling the FieldIdx::from_u32(idx) method. This check ensures that if the idx value is greater than the maximum allowed value, it returns Option::None, similar to how other functions handle errors during the call to the project method of type Value. --- .../rustc_mir_transform/src/known_panics_lint.rs | 10 ++++++++-- ...-out-of-bounds-exceeds-max-value-issue-121126.rs | 13 +++++++++++++ ...-of-bounds-exceeds-max-value-issue-121126.stderr | 10 ++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 tests/ui/indexing/index-out-of-bounds-exceeds-max-value-issue-121126.rs create mode 100644 tests/ui/indexing/index-out-of-bounds-exceeds-max-value-issue-121126.stderr diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 2218154ea5e78..9f328634bc399 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -101,8 +101,14 @@ impl<'tcx> Value<'tcx> { } (PlaceElem::Index(idx), Value::Aggregate { fields, .. }) => { let idx = prop.get_const(idx.into())?.immediate()?; - let idx = prop.ecx.read_target_usize(idx).ok()?; - fields.get(FieldIdx::from_u32(idx.try_into().ok()?)).unwrap_or(&Value::Uninit) + let idx: u32 = prop.ecx.read_target_usize(idx).ok()?.try_into().ok()?; + + let max: u32 = FieldIdx::MAX.index().try_into().ok()?; + if idx > max { + return None; + } + + fields.get(FieldIdx::from_u32(idx)).unwrap_or(&Value::Uninit) } ( PlaceElem::ConstantIndex { offset, min_length: _, from_end: false }, diff --git a/tests/ui/indexing/index-out-of-bounds-exceeds-max-value-issue-121126.rs b/tests/ui/indexing/index-out-of-bounds-exceeds-max-value-issue-121126.rs new file mode 100644 index 0000000000000..7750993f1e20a --- /dev/null +++ b/tests/ui/indexing/index-out-of-bounds-exceeds-max-value-issue-121126.rs @@ -0,0 +1,13 @@ +// Regression test for #121126. Compiler was panicking when indexing an array +// with an index that is out of bounds and its value is greater than the max +// value allowed for an index. + +//@ build-fail + +fn main() { + [0][0xFFFF_FF01]; +//~^ ERROR this operation will panic at runtime [unconditional_panic] +} + +// NOTE: In order for the test to be valid, the index can take on any value +// between FieldIdx::MAX + 1 (= 0xFFF_FF01) and u32::MAX (= 0xFFF_FFFF) diff --git a/tests/ui/indexing/index-out-of-bounds-exceeds-max-value-issue-121126.stderr b/tests/ui/indexing/index-out-of-bounds-exceeds-max-value-issue-121126.stderr new file mode 100644 index 0000000000000..e530a994b14c3 --- /dev/null +++ b/tests/ui/indexing/index-out-of-bounds-exceeds-max-value-issue-121126.stderr @@ -0,0 +1,10 @@ +error: this operation will panic at runtime + --> $DIR/issue-121126-index-out-of-bounds-exceeds-max-value.rs:8:5 + | +LL | [0][0xFFFF_FF01]; + | ^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 4294967041 + | + = note: `#[deny(unconditional_panic)]` on by default + +error: aborting due to 1 previous error +