]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Fix segv when handling invalid array capacities
authorPhilip Herron <herron.philip@googlemail.com>
Sun, 31 Aug 2025 21:57:05 +0000 (22:57 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Thu, 30 Oct 2025 19:59:07 +0000 (20:59 +0100)
We need to catch the error node for the array capacity and return early.
Otherwise we try to const evaluate something thats just silly. Also
when compiling array expressions we can simply reuse the array capacity
expression we already have cons folded.

Fixes Rust-GCC#3965

gcc/rust/ChangeLog:

* backend/rust-compile-context.h: add assertions for context peeks
* backend/rust-compile-expr.cc (CompileExpr::visit): check for valid loop context
(CompileExpr::array_copied_expr): just reuse array tyty capacity value
* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): catch error

gcc/testsuite/ChangeLog:

* rust/compile/issue-3965-1.rs: New test.
* rust/compile/issue-3965-2.rs: New test.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
gcc/rust/backend/rust-compile-context.h
gcc/rust/backend/rust-compile-expr.cc
gcc/rust/typecheck/rust-hir-type-check-expr.cc
gcc/testsuite/rust/compile/issue-3965-1.rs [new file with mode: 0644]
gcc/testsuite/rust/compile/issue-3965-2.rs [new file with mode: 0644]

index 69bba515882f5c69e6e0bbe9f521d0c05e6cf36d..e98bbc2d49f356bc176f5f420a8836202b29cfeb 100644 (file)
@@ -322,7 +322,13 @@ public:
 
   void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); }
 
-  Bvariable *peek_loop_context () { return loop_value_stack.back (); }
+  bool have_loop_context () const { return !loop_value_stack.empty (); }
+
+  Bvariable *peek_loop_context ()
+  {
+    rust_assert (!loop_value_stack.empty ());
+    return loop_value_stack.back ();
+  }
 
   Bvariable *pop_loop_context ()
   {
@@ -336,7 +342,11 @@ public:
     loop_begin_labels.push_back (label);
   }
 
-  tree peek_loop_begin_label () { return loop_begin_labels.back (); }
+  tree peek_loop_begin_label ()
+  {
+    rust_assert (!loop_begin_labels.empty ());
+    return loop_begin_labels.back ();
+  }
 
   tree pop_loop_begin_label ()
   {
index 2bec52bfc4a87ae2b3f99a595176f3a6f2a447cd..946bbb1234f7c4b0743bf673a4e4604281c71dea 100644 (file)
@@ -891,6 +891,10 @@ CompileExpr::visit (HIR::BreakExpr &expr)
 void
 CompileExpr::visit (HIR::ContinueExpr &expr)
 {
+  translated = error_mark_node;
+  if (!ctx->have_loop_context ())
+    return;
+
   tree label = ctx->peek_loop_begin_label ();
   if (expr.has_label ())
     {
@@ -2000,13 +2004,11 @@ CompileExpr::array_copied_expr (location_t expr_locus,
       return error_mark_node;
     }
 
-  ctx->push_const_context ();
-  tree capacity_expr = CompileExpr::Compile (elems.get_num_copies_expr (), ctx);
-  ctx->pop_const_context ();
-
+  auto capacity_tyty = array_tyty.get_capacity ();
+  tree capacity_expr = capacity_tyty->get_value ();
   if (!TREE_CONSTANT (capacity_expr))
     {
-      rust_error_at (expr_locus, "non const num copies %qT", array_type);
+      rust_error_at (expr_locus, "non const num copies %qT", capacity_expr);
       return error_mark_node;
     }
 
index 9a772cba4c605d58f5f7a4316b9e8c483ce3be12..dc063587e0d80ba99401bd026a9fce5210bd1b8e 100644 (file)
@@ -1090,6 +1090,8 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
 
        auto capacity_expr_ty
          = TypeCheckExpr::Resolve (elems.get_num_copies_expr ());
+       if (capacity_expr_ty->is<TyTy::ErrorType> ())
+         return;
 
        context->insert_type (elems.get_num_copies_expr ().get_mappings (),
                              expected_ty);
diff --git a/gcc/testsuite/rust/compile/issue-3965-1.rs b/gcc/testsuite/rust/compile/issue-3965-1.rs
new file mode 100644 (file)
index 0000000..291a220
--- /dev/null
@@ -0,0 +1,4 @@
+fn main() {
+    [(); { continue }];
+    // { dg-error ".continue. outside of a loop .E0268." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3965-2.rs b/gcc/testsuite/rust/compile/issue-3965-2.rs
new file mode 100644 (file)
index 0000000..d48503f
--- /dev/null
@@ -0,0 +1,7 @@
+fn main() {
+    loop { continue }
+
+    [(); {while true {break}; 0}];
+
+    [(); {while true {break}; 0}];
+}