Skip to content

Commit 969439f

Browse files
CohenArthurP-E-P
authored andcommitted
macro-expand: Keep optional references to last_{def, invoc}
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.
1 parent 5712d7d commit 969439f

File tree

3 files changed

+18
-9
lines changed

3 files changed

+18
-9
lines changed

gcc/rust/expand/rust-macro-expand.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// <http://www.gnu.org/licenses/>.
1818

1919
#include "rust-macro-expand.h"
20+
#include "optional.h"
2021
#include "rust-macro-substitute-ctx.h"
2122
#include "rust-ast-full.h"
2223
#include "rust-ast-visitor.h"
@@ -281,8 +282,8 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
281282

282283
// We store the last expanded invocation and macro definition for error
283284
// reporting in case the recursion limit is reached
284-
last_invoc = &invoc;
285-
last_def = rules_def;
285+
last_invoc = *invoc.clone_macro_invocation_impl ();
286+
last_def = *rules_def;
286287

287288
if (rules_def->is_builtin ())
288289
fragment

gcc/rust/expand/rust-macro-expand.h

+12-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifndef RUST_MACRO_EXPAND_H
2020
#define RUST_MACRO_EXPAND_H
2121

22+
#include "optional.h"
2223
#include "rust-buffered-queue.h"
2324
#include "rust-parse.h"
2425
#include "rust-token.h"
@@ -480,8 +481,15 @@ struct MacroExpander
480481
*/
481482
void reset_changed_state () { has_changed_flag = false; }
482483

483-
AST::MacroRulesDefinition *get_last_definition () { return last_def; }
484-
AST::MacroInvocation *get_last_invocation () { return last_invoc; }
484+
tl::optional<AST::MacroRulesDefinition &> &get_last_definition ()
485+
{
486+
return last_def;
487+
}
488+
489+
tl::optional<AST::MacroInvocation &> &get_last_invocation ()
490+
{
491+
return last_invoc;
492+
}
485493

486494
private:
487495
AST::Fragment parse_proc_macro_output (ProcMacro::TokenStream ts);
@@ -493,8 +501,8 @@ struct MacroExpander
493501
AST::Fragment expanded_fragment;
494502
bool has_changed_flag;
495503

496-
AST::MacroRulesDefinition *last_def;
497-
AST::MacroInvocation *last_invoc;
504+
tl::optional<AST::MacroRulesDefinition &> last_def;
505+
tl::optional<AST::MacroInvocation &> last_invoc;
498506

499507
public:
500508
Resolver::Resolver *resolver;

gcc/rust/rust-session-manager.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -898,10 +898,10 @@ Session::expansion (AST::Crate &crate)
898898

899899
if (iterations == cfg.recursion_limit)
900900
{
901-
auto last_invoc = expander.get_last_invocation ();
902-
auto last_def = expander.get_last_definition ();
901+
auto &last_invoc = expander.get_last_invocation ();
902+
auto &last_def = expander.get_last_definition ();
903903

904-
rust_assert (last_def && last_invoc);
904+
rust_assert (last_def.has_value () && last_invoc.has_value ());
905905

906906
rich_location range (line_table, last_invoc->get_locus ());
907907
range.add_range (last_def->get_locus ());

0 commit comments

Comments
 (0)