Add recursion limit for INCLUDE and macros

(And REPT.)
Not exactly a *recursion* limit, more like a *stack depth* limit,
but calling it "recursion" conveys its purpose better.
The default of 64 is super overkill: even in a a project with
what I believe to be above-average levels of nesting, the
level only peaked at 6.
Keeping in mind the purpose of this is to catch infinite
recursion, which is still caught quickly (in usual cases, anyways),
this default seems sensible.
And it passes tests. What more do you need?
This commit is contained in:
ISSOtm
2019-08-30 04:42:56 +02:00
parent a21cef7190
commit 6068b565f5
3 changed files with 21 additions and 1 deletions

View File

@@ -35,6 +35,8 @@ struct sContext {
uint32_t nREPTBlockSize; uint32_t nREPTBlockSize;
}; };
extern unsigned int nMaxFileStackDepth;
void fstk_RunInclude(char *tzFileName); void fstk_RunInclude(char *tzFileName);
void fstk_RunMacroArg(int32_t s); void fstk_RunMacroArg(int32_t s);
void fstk_Init(char *s); void fstk_Init(char *s);

View File

@@ -28,6 +28,8 @@
#include "types.h" #include "types.h"
static struct sContext *pFileStack; static struct sContext *pFileStack;
static unsigned int nFileStackDepth;
unsigned int nMaxFileStackDepth;
static struct sSymbol *pCurrentMacro; static struct sSymbol *pCurrentMacro;
static YY_BUFFER_STATE CurrentFlexHandle; static YY_BUFFER_STATE CurrentFlexHandle;
static FILE *pCurrentFile; static FILE *pCurrentFile;
@@ -51,6 +53,8 @@ uint32_t ulMacroReturnValue;
#define STAT_isMacroArg 2 #define STAT_isMacroArg 2
#define STAT_isREPTBlock 3 #define STAT_isREPTBlock 3
/* Max context stack size */
/* /*
* Context push and pop * Context push and pop
*/ */
@@ -58,6 +62,9 @@ static void pushcontext(void)
{ {
struct sContext **ppFileStack; struct sContext **ppFileStack;
if (++nFileStackDepth > nMaxFileStackDepth)
fatalerror("Recursion limit (%d) exceeded", nMaxFileStackDepth);
ppFileStack = &pFileStack; ppFileStack = &pFileStack;
while (*ppFileStack) while (*ppFileStack)
ppFileStack = &((*ppFileStack)->pNext); ppFileStack = &((*ppFileStack)->pNext);
@@ -158,6 +165,8 @@ static int32_t popcontext(void)
fatalerror("%s: Internal error.", __func__); fatalerror("%s: Internal error.", __func__);
} }
nFileStackDepth--;
free(*ppLastFile); free(*ppLastFile);
*ppLastFile = NULL; *ppLastFile = NULL;
yy_switch_to_buffer(CurrentFlexHandle); yy_switch_to_buffer(CurrentFlexHandle);
@@ -417,6 +426,7 @@ void fstk_Init(char *pFileName)
if (pCurrentFile == NULL) if (pCurrentFile == NULL)
err(1, "Unable to open file '%s'", pFileName); err(1, "Unable to open file '%s'", pFileName);
} }
nFileStackDepth = 0;
nMacroCount = 0; nMacroCount = 0;
nCurrentStatus = STAT_isInclude; nCurrentStatus = STAT_isInclude;

View File

@@ -315,6 +315,8 @@ int main(int argc, char *argv[])
/* yydebug=1; */ /* yydebug=1; */
nMaxFileStackDepth = 64;
DefaultOptions.gbgfx[0] = '0'; DefaultOptions.gbgfx[0] = '0';
DefaultOptions.gbgfx[1] = '1'; DefaultOptions.gbgfx[1] = '1';
DefaultOptions.gbgfx[2] = '2'; DefaultOptions.gbgfx[2] = '2';
@@ -332,7 +334,7 @@ int main(int argc, char *argv[])
newopt = CurrentOptions; newopt = CurrentOptions;
while ((ch = getopt(argc, argv, "b:D:Eg:hi:LM:o:p:Vvw")) != -1) { while ((ch = getopt(argc, argv, "b:D:Eg:hi:LM:o:p:r:Vvw")) != -1) {
switch (ch) { switch (ch) {
case 'b': case 'b':
if (strlen(optarg) == 2) { if (strlen(optarg) == 2) {
@@ -386,6 +388,12 @@ int main(int argc, char *argv[])
errx(1, "Argument for option 'p' must be between 0 and 0xFF"); errx(1, "Argument for option 'p' must be between 0 and 0xFF");
break; break;
case 'r':
nMaxFileStackDepth = strtoul(optarg, &ep, 0);
if (optarg[0] == '\0' || *ep != '\0')
errx(1, "Invalid argument for option 'r'");
break;
case 'V': case 'V':
printf("rgbasm %s\n", get_package_version_string()); printf("rgbasm %s\n", get_package_version_string());
exit(0); exit(0);