shithub: rgbds

Download patch

ref: 6068b565f5f487ad725cacc1ff79ed4451cd89b7
parent: a21cef71908be8d93009542a324dceef9c14d855
author: ISSOtm <[email protected]>
date: Fri Aug 30 00:42:56 EDT 2019

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?

--- a/include/asm/fstack.h
+++ b/include/asm/fstack.h
@@ -35,6 +35,8 @@
 	uint32_t nREPTBlockSize;
 };
 
+extern unsigned int nMaxFileStackDepth;
+
 void fstk_RunInclude(char *tzFileName);
 void fstk_RunMacroArg(int32_t s);
 void fstk_Init(char *s);
--- a/src/asm/fstack.c
+++ b/src/asm/fstack.c
@@ -28,6 +28,8 @@
 #include "types.h"
 
 static struct sContext *pFileStack;
+static unsigned int nFileStackDepth;
+unsigned int nMaxFileStackDepth;
 static struct sSymbol *pCurrentMacro;
 static YY_BUFFER_STATE CurrentFlexHandle;
 static FILE *pCurrentFile;
@@ -51,6 +53,8 @@
 #define STAT_isMacroArg		2
 #define STAT_isREPTBlock	3
 
+/* Max context stack size */
+
 /*
  * Context push and pop
  */
@@ -58,6 +62,9 @@
 {
 	struct sContext **ppFileStack;
 
+	if (++nFileStackDepth > nMaxFileStackDepth)
+		fatalerror("Recursion limit (%d) exceeded", nMaxFileStackDepth);
+
 	ppFileStack = &pFileStack;
 	while (*ppFileStack)
 		ppFileStack = &((*ppFileStack)->pNext);
@@ -158,6 +165,8 @@
 		fatalerror("%s: Internal error.", __func__);
 	}
 
+	nFileStackDepth--;
+
 	free(*ppLastFile);
 	*ppLastFile = NULL;
 	yy_switch_to_buffer(CurrentFlexHandle);
@@ -417,6 +426,7 @@
 		if (pCurrentFile == NULL)
 			err(1, "Unable to open file '%s'", pFileName);
 	}
+	nFileStackDepth = 0;
 
 	nMacroCount = 0;
 	nCurrentStatus = STAT_isInclude;
--- a/src/asm/main.c
+++ b/src/asm/main.c
@@ -315,6 +315,8 @@
 
 	/* yydebug=1; */
 
+	nMaxFileStackDepth = 64;
+
 	DefaultOptions.gbgfx[0] = '0';
 	DefaultOptions.gbgfx[1] = '1';
 	DefaultOptions.gbgfx[2] = '2';
@@ -332,7 +334,7 @@
 
 	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) {
 		case 'b':
 			if (strlen(optarg) == 2) {
@@ -385,6 +387,12 @@
 			if (newopt.fillchar < 0 || newopt.fillchar > 0xFF)
 				errx(1, "Argument for option 'p' must be between 0 and 0xFF");
 
+			break;
+		case 'r':
+			nMaxFileStackDepth = strtoul(optarg, &ep, 0);
+
+			if (optarg[0] == '\0' || *ep != '\0')
+				errx(1, "Invalid argument for option 'r'");
 			break;
 		case 'V':
 			printf("rgbasm %s\n", get_package_version_string());