From 5db7604efff0b0a3e573c888a7d56f524376db23 Mon Sep 17 00:00:00 2001 From: uz Date: Tue, 7 Jun 2011 21:17:35 +0000 Subject: [PATCH] Don't allow too many nested macro expansions. Until now, it was possible to send the assembler in an endless loop by a recursive macro without end condition or a set of macros that called each other. git-svn-id: svn://svn.cc65.org/cc65/trunk@5038 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ca65/macro.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/ca65/macro.c b/src/ca65/macro.c index ddf88b994..868b03f19 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -107,6 +107,7 @@ struct Macro { TokNode* TokRoot; /* Root of token list */ TokNode* TokLast; /* Pointer to last token in list */ unsigned char Style; /* Macro style */ + unsigned char Incomplete; /* Macro is currently built */ StrBuf Name; /* Macro name, dynamically allocated */ }; @@ -139,6 +140,9 @@ struct MacExp { unsigned LISlot; /* Slot for additional line infos */ }; +/* Maximum number of nested macro expansions */ +#define MAX_MACEXPANSIONS 256U + /* Number of active macro expansions */ static unsigned MacExpansions = 0; @@ -230,6 +234,7 @@ static Macro* NewMacro (const StrBuf* Name, unsigned char Style) M->TokRoot = 0; M->TokLast = 0; M->Style = Style; + M->Incomplete = 1; SB_Init (&M->Name); SB_Copy (&M->Name, Name); @@ -533,6 +538,9 @@ void MacDef (unsigned Style) NextTok (); } + /* Reset the Incomplete flag now that parsing is done */ + M->Incomplete = 0; + Done: /* Switch out of raw token mode */ LeaveRawTokenMode (); @@ -677,7 +685,7 @@ static void StartExpClassic (Macro* M) token_t Term; - /* Create a structure holding expansion data. This must be done before + /* Create a structure holding expansion data. This must be done before * skipping the macro name, because the call to NextTok may cause a new * expansion if the next token is actually a .define style macro. */ @@ -854,6 +862,20 @@ void MacExpandStart (void) Macro* M = HT_FindEntry (&MacroTab, &CurTok.SVal); CHECK (M != 0); + /* We cannot expand an incomplete macro */ + if (M->Incomplete) { + Error ("Cannot expand an incomplete macro"); + return; + } + + /* Don't allow too many nested macro expansions - otherwise it is possible + * to force an endless loop and assembler crash. + */ + if (MacExpansions >= MAX_MACEXPANSIONS) { + Error ("Too many nested macro expansions"); + return; + } + /* Call the apropriate subroutine */ switch (M->Style) { case MAC_STYLE_CLASSIC: StartExpClassic (M); break;