ref: c755fa3469af9c4179b36f7b06ef54a95b8eafeb
parent: e78a1d5bfd2840fa94c6a4c75a4e3aabeb904b70
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Fri Apr 16 17:15:01 EDT 2021
`readIdentifier` does not process characters that get truncated Previously a '.' could be past the truncation limit but still cause the identifier to be marked as local, violating an assertion in `sym_AddLocalLabel`. Fixes #832
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -1210,6 +1210,11 @@
return (c <= 'Z' && c >= 'A') || (c <= 'z' && c >= 'a') || c == '.' || c == '_';
}
+static bool continuesIdentifier(int c)
+{
+ return startsIdentifier(c) || (c <= '9' && c >= '0') || c == '#' || c == '@';
+}
+
static int readIdentifier(char firstChar)
{
dbgPrint("Reading identifier or keyword\n");
@@ -1217,30 +1222,24 @@
yylval.tzSym[0] = firstChar;
uint16_t nodeID = keywordDict[0].children[dictIndex(firstChar)];
int tokenType = firstChar == '.' ? T_LOCAL_ID : T_ID;
- size_t i;
+ size_t i = 1;
- for (i = 1; ; i++) {
- int c = peek();
-
- /* If that char isn't in the symbol charset, end */
- if ((c > '9' || c < '0')
- && (c > 'Z' || c < 'A')
- && (c > 'z' || c < 'a')
- && c != '#' && c != '.' && c != '@' && c != '_')
- break;
+ /* Continue reading while the char is in the symbol charset */
+ for (int c = peek(); continuesIdentifier(c); i++, c = peek()) {
shiftChar();
- /* Write the char to the identifier's name */
- if (i < sizeof(yylval.tzSym) - 1)
+ if (i < sizeof(yylval.tzSym) - 1) {
+ /* Write the char to the identifier's name */
yylval.tzSym[i] = c;
- /* If the char was a dot, mark the identifier as local */
- if (c == '.')
- tokenType = T_LOCAL_ID;
+ /* If the char was a dot, mark the identifier as local */
+ if (c == '.')
+ tokenType = T_LOCAL_ID;
- /* Attempt to traverse the tree to check for a keyword */
- if (nodeID) /* Do nothing if matching already failed */
- nodeID = keywordDict[nodeID].children[dictIndex(c)];
+ /* Attempt to traverse the tree to check for a keyword */
+ if (nodeID) /* Do nothing if matching already failed */
+ nodeID = keywordDict[nodeID].children[dictIndex(c)];
+ }
}
if (i > sizeof(yylval.tzSym) - 1) {
--- /dev/null
+++ b/test/asm/local-truncated.asm
@@ -1,0 +1,11 @@
+SECTION "Test", ROM0
+
+MACRO a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
+ println "truncated :("
+ENDM
+
+a012:
+ a012.local
+
+a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012:
+ a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012.local
--- /dev/null
+++ b/test/asm/local-truncated.err
@@ -1,0 +1,7 @@
+warning: local-truncated.asm(10): [-Wlong-string]
+ Symbol name too long, got truncated
+ERROR: local-truncated.asm(10):
+ 'a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001' already defined at local-truncated.asm(3)
+warning: local-truncated.asm(11): [-Wlong-string]
+ Symbol name too long, got truncated
+error: Assembly aborted (1 error)!
--- /dev/null
+++ b/test/asm/local-truncated.out
@@ -1,0 +1,1 @@
+truncated :(