]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: macro-expand: Keep optional references to last_{def, invoc}
authorArthur Cohen <arthur.cohen@embecosm.com>
Thu, 3 Aug 2023 15:24:14 +0000 (17:24 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 18:00:29 +0000 (19:00 +0100)
This avoids a use-after-free when reaching the recursion limit.

gcc/rust/ChangeLog:

* expand/rust-macro-expand.h: Keep optional references for last_def
and last_invoc.
* expand/rust-macro-expand.cc (MacroExpander::expand_invoc): Store
optional references.
* rust-session-manager.cc (Session::expansion): Use tl::optional's APIs
for better checking.

gcc/rust/expand/rust-macro-expand.cc
gcc/rust/expand/rust-macro-expand.h
gcc/rust/rust-session-manager.cc

index 2010357277d22d179e23d8f31d85122a683ea475..fe2056036b37718f3710330330c343439e983820 100644 (file)
@@ -17,6 +17,7 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-macro-expand.h"
+#include "optional.h"
 #include "rust-macro-substitute-ctx.h"
 #include "rust-ast-full.h"
 #include "rust-ast-visitor.h"
@@ -281,8 +282,8 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
 
   // We store the last expanded invocation and macro definition for error
   // reporting in case the recursion limit is reached
-  last_invoc = &invoc;
-  last_def = rules_def;
+  last_invoc = *invoc.clone_macro_invocation_impl ();
+  last_def = *rules_def;
 
   if (rules_def->is_builtin ())
     fragment
index d52d0707f9733baa564e4fb377e0cb4a220131b4..34fc01f0d0b049c038ab688bc0e80a7ed0ae5ea4 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef RUST_MACRO_EXPAND_H
 #define RUST_MACRO_EXPAND_H
 
+#include "optional.h"
 #include "rust-buffered-queue.h"
 #include "rust-parse.h"
 #include "rust-token.h"
@@ -480,8 +481,15 @@ struct MacroExpander
    */
   void reset_changed_state () { has_changed_flag = false; }
 
-  AST::MacroRulesDefinition *get_last_definition () { return last_def; }
-  AST::MacroInvocation *get_last_invocation () { return last_invoc; }
+  tl::optional<AST::MacroRulesDefinition &> &get_last_definition ()
+  {
+    return last_def;
+  }
+
+  tl::optional<AST::MacroInvocation &> &get_last_invocation ()
+  {
+    return last_invoc;
+  }
 
 private:
   AST::Fragment parse_proc_macro_output (ProcMacro::TokenStream ts);
@@ -493,8 +501,8 @@ private:
   AST::Fragment expanded_fragment;
   bool has_changed_flag;
 
-  AST::MacroRulesDefinition *last_def;
-  AST::MacroInvocation *last_invoc;
+  tl::optional<AST::MacroRulesDefinition &> last_def;
+  tl::optional<AST::MacroInvocation &> last_invoc;
 
 public:
   Resolver::Resolver *resolver;
index 55f6ec5585bb821d9af7579e889a7ea024549f69..bb6cf4c9cca2aa07f90dd33adf7da2dbe1a0b59e 100644 (file)
@@ -898,10 +898,10 @@ Session::expansion (AST::Crate &crate)
 
   if (iterations == cfg.recursion_limit)
     {
-      auto last_invoc = expander.get_last_invocation ();
-      auto last_def = expander.get_last_definition ();
+      auto &last_invoc = expander.get_last_invocation ();
+      auto &last_def = expander.get_last_definition ();
 
-      rust_assert (last_def && last_invoc);
+      rust_assert (last_def.has_value () && last_invoc.has_value ());
 
       rich_location range (line_table, last_invoc->get_locus ());
       range.add_range (last_def->get_locus ());