]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Fix out of bounds indexing while expanding macros with repetition
authorOwen Avery <powerboat9.gamer@gmail.com>
Thu, 20 Apr 2023 17:31:30 +0000 (13:31 -0400)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:34:16 +0000 (18:34 +0100)
gcc/rust/ChangeLog:

* expand/rust-macro-substitute-ctx.cc
(SubstituteCtx::substitute_repetition): Fix out-of-bounds.

gcc/testsuite/ChangeLog:

* rust/compile/macro52.rs: New test.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
gcc/rust/expand/rust-macro-substitute-ctx.cc
gcc/testsuite/rust/compile/macro52.rs [new file with mode: 0644]

index 9592d2d2a9e178469949dacede177c539e854567..eb0f149b10ad498439598b8293b4a6e76ee30cf7 100644 (file)
@@ -147,15 +147,27 @@ SubstituteCtx::substitute_repetition (
        {
          MatchedFragment sub_fragment;
 
+         // Hack: A repeating meta variable might not be present in the new
+         // macro. Don't include this match if the fragment doesn't have enough
+         // items, as check_repetition_amount should prevent repetition amount
+         // mismatches anyway.
+         bool is_used = true;
+
          // FIXME: Hack: If a fragment is not repeated, how does it fit in the
          // submap? Do we really want to expand it? Is this normal behavior?
          if (kv_match.second.is_single_fragment ())
            sub_fragment = kv_match.second.get_single_fragment ();
          else
-           sub_fragment = kv_match.second.get_fragments ()[i];
+           {
+             if (kv_match.second.get_fragments ().size () > i)
+               sub_fragment = kv_match.second.get_fragments ().at (i);
+             else
+               is_used = false;
+           }
 
-         sub_map.insert (
-           {kv_match.first, MatchedFragmentContainer::metavar (sub_fragment)});
+         if (is_used)
+           sub_map.insert ({kv_match.first,
+                            MatchedFragmentContainer::metavar (sub_fragment)});
        }
 
       auto substitute_context = SubstituteCtx (input, new_macro, sub_map);
diff --git a/gcc/testsuite/rust/compile/macro52.rs b/gcc/testsuite/rust/compile/macro52.rs
new file mode 100644 (file)
index 0000000..31002eb
--- /dev/null
@@ -0,0 +1,11 @@
+macro_rules! multi {
+    ($( $a:ident )? $( + $b:ident )?) => {
+        {
+            $( let $a: u32 )?;
+        }
+    }
+}
+
+pub fn foo() {
+    multi!(_a);
+}