Fix for bug #51. Now at v2.0.22.
authorShamus Hammons <jlhamm@acm.org>
Tue, 29 Sep 2020 02:41:40 +0000 (21:41 -0500)
committerShamus Hammons <jlhamm@acm.org>
Tue, 29 Sep 2020 02:41:40 +0000 (21:41 -0500)
We bumped the # of tokens in the TOKENSTREAM structure from 32 to 64,
but also added some logic to the macro invocation code to check if we
break the limits and thus don't crash.  Will 64 be enough?  My crystal
ball is cloudy ATM...  :-P

macro.c
op.c
token.c
token.h
version.h

diff --git a/macro.c b/macro.c
index 22bd0d9f7c444d4824228cab8307e82c648c9f85..17378dcde2f676a9546142eba0fc5f6a3c6d4365 100644 (file)
--- a/macro.c
+++ b/macro.c
@@ -406,41 +406,75 @@ int InvokeMacro(SYM * mac, WORD siz)
                // Parse out the arguments and set them up correctly
                TOKEN * p = imacro->argument[nargs].token;
                int stringNum = 0;
+               int numTokens = 0;
 
                while (*tok != EOL)
                {
                        if (*tok == ACONST)
                        {
+                               // Sanity checking (it's numTokens + 1 because we need an EOL
+                               // if we successfully parse this argument)
+                               if ((numTokens + 3) >= TS_MAXTOKENS)
+                                       return error("Too many tokens in argument #%d in MACRO invocation", nargs + 1);
+
                                for(int i=0; i<3; i++)
                                        *p++ = *tok++;
+
+                               numTokens += 3;
                        }
                        else if (*tok == CONST)         // Constants are 64-bits
                        {
+                               // Sanity checking (it's numTokens + 1 because we need an EOL
+                               // if we successfully parse this argument)
+                               if ((numTokens + 3) >= TS_MAXTOKENS)
+                                       return error("Too many tokens in argument #%d in MACRO invocation", nargs + 1);
+
                                *p++ = *tok++;                  // Token
                                uint64_t *p64 = (uint64_t *)p;
                                uint64_t *tok64 = (uint64_t *)tok;
                                *p64++ = *tok64++;
                                tok = (TOKEN *)tok64;
                                p = (uint32_t *)p64;
+                               numTokens += 3;
                        }
                        else if ((*tok == STRING) || (*tok == SYMBOL))
                        {
+                               // Sanity checking (it's numTokens + 1 because we need an EOL
+                               // if we successfully parse this argument)
+                               if (stringNum >= TS_MAXSTRINGS)
+                                       return error("Too many strings in argument #%d in MACRO invocation", nargs + 1);
+
+                               if ((numTokens + 2) >= TS_MAXTOKENS)
+                                       return error("Too many tokens in argument #%d in MACRO invocation", nargs + 1);
+
                                *p++ = *tok++;
                                imacro->argument[nargs].string[stringNum] = strdup(string[*tok++]);
                                *p++ = stringNum++;
+                               numTokens += 2;
                        }
                        else if (*tok == ',')
                        {
+                               // Sanity checking
+                               if ((nargs + 1) >= TS_MAXARGS)
+                                       return error("Too many arguments in MACRO invocation");
+
                                // Comma delimiter was found, so set up for next argument
                                *p++ = EOL;
                                tok++;
                                stringNum = 0;
+                               numTokens = 0;
                                nargs++;
                                p = imacro->argument[nargs].token;
                        }
                        else
                        {
+                               // Sanity checking (it's numTokens + 1 because we need an EOL
+                               // if we successfully parse this argument)
+                               if ((numTokens + 1) >= TS_MAXTOKENS)
+                                       return error("Too many tokens in argument #%d in MACRO invocation", nargs + 1);
+
                                *p++ = *tok++;
+                               numTokens++;
                        }
                }
 
diff --git a/op.c b/op.c
index 836f4de173b01add2b452414574c98b9c5c13953..3833bfbee292e17117b3058cc7a9333e29103fc3 100644 (file)
--- a/op.c
+++ b/op.c
@@ -89,6 +89,7 @@ static inline uint64_t CheckFlags(char * s)
                return 0x04;
        else if (strcmp(scratchbuf, "RELEASE") == 0)
                return 0x08;
+
        return 0;
 }
 
diff --git a/token.c b/token.c
index 9299e3f7c3d7ffb9605421514ac471fded34a7d3..fa5af09b1dd6d60d18bae85d8f59417f643c0d7d 100644 (file)
--- a/token.c
+++ b/token.c
@@ -673,7 +673,6 @@ overflow:
 char * GetNextMacroLine(void)
 {
        IMACRO * imacro = cur_inobj->inobj.imacro;
-//     LONG * strp = imacro->im_nextln;
        LLIST * strp = imacro->im_nextln;
 
        if (strp == NULL)                                               // End-of-macro
diff --git a/token.h b/token.h
index 95adf0157c0982d2519e78cc20e0d7a67b2f5c63..251a503f424036a705edf559b3ecd9302b85d56b 100644 (file)
--- a/token.h
+++ b/token.h
 #define SRC_IREPT       2                      // Input source is IREPT
 
 // Macros
-#define INOBJ           struct _inobj
-#define IUNION          union _iunion
-#define IFILE           struct _incldfile
-#define IMACRO          struct _imacro
-#define IREPT           struct _irept
-#define IFENT           struct _ifent
+#define INOBJ          struct _inobj
+#define IUNION         union  _iunion
+#define IFILE          struct _incldfile
+#define TOKENSTREAM    struct _tokenstream
+#define IMACRO         struct _imacro
+#define IREPT          struct _irept
+#define IFENT          struct _ifent
 
 // Tunable definitions
 #define LNSIZ           1024           // Maximum size of a line of text
@@ -126,10 +127,14 @@ IFILE {
        char ifbuf[LNBUFSIZ];   // Line buffer
 };
 
-#define TOKENSTREAM struct _tokenstream
+// Consts for maximums in TOKENSTREAM
+#define TS_MAXTOKENS   64      // 32 ought to be enough for anybody (including XiA!)
+#define TS_MAXSTRINGS  32      // same for attached strings
+#define TS_MAXARGS             20      // Assume no more than 20 arguments in an invocation
+
 TOKENSTREAM {
-       TOKEN token[32];                // 32 ought to be enough for anybody (including XiA!)
-       char * string[32];              // same for attached strings
+       TOKEN token[TS_MAXTOKENS];
+       char * string[TS_MAXSTRINGS];
 };
 
 // Information about a macro invocation
@@ -141,7 +146,7 @@ IMACRO {
        LONG im_olduniq;                // Old value of 'macuniq'
        SYM * im_macro;                 // Pointer to macro we're in
        char im_lnbuf[LNSIZ];   // Line buffer
-       TOKENSTREAM argument[20];       // Assume no more than 20 arguments in an invocation
+       TOKENSTREAM argument[TS_MAXARGS];
 };
 
 // Information about a .rept invocation
index 5764ad5e8d3531bb2a2644cfad8127b00fdd7420..6b5d5ef81fa0bbc7e437e965a48debe2b1d446d9 100644 (file)
--- a/version.h
+++ b/version.h
@@ -15,7 +15,7 @@
 
 #define MAJOR   2              // Major version number
 #define MINOR   0              // Minor version number
-#define PATCH   21             // Patch release number
+#define PATCH   22             // Patch release number
 
 #endif // __VERSION_H__