diff --git a/Programs/testPrograms/stringKeyword.asm b/Programs/testPrograms/stringKeyword.asm new file mode 100644 index 0000000..60e3ccc --- /dev/null +++ b/Programs/testPrograms/stringKeyword.asm @@ -0,0 +1,48 @@ +; A program whose data contains the names of directives. +; +; The quotes are gone by the time the assembler looks at a token, so "#Program" written as +; a string looked exactly like the directive. It was read as one: the segment silently +; changed in the middle of the Data Segment, the string's nine bytes were charged to the +; Program cursor instead, and every label defined after it came out nine bytes wrong. The +; file still had a valid header and a plausible length, so nothing said a word - the only +; symptom was a program that jumped into the middle of an instruction. +; +; This is the fourth of that family. A string spelling a mnemonic assembled as that +; instruction, a string beginning with a zero was rejected as a malformed literal, a string +; in the Program Segment was discarded in silence, and now this. +; +; It came up because an assembler written FOR this machine has to compare tokens against +; the directive names, so it necessarily has them in its data. Nothing else ever did. +; +; What it checks: that the strings survive as strings, and that a label defined after them +; still points where it should. Everything after Directives would shift if the bug came +; back, so printing Message is the test. +; +; Written by Anachronaut + +#Program + +start: + SETD.0 Directives + CALL show + SETD.0 Message + CALL show + HALT + +show: + LDA.0 + BRA showDone + OUTA 0x00 + INCD.0 + BRI show +showDone: + RET + +#Data + +Directives: +"#Program #Data #Include #Vectors #Base #Align #Reserve +" +Message: +"and a label after them still points at itself +" diff --git a/Source/Assembler/Assm-util.c b/Source/Assembler/Assm-util.c index bad9434..921dde8 100644 --- a/Source/Assembler/Assm-util.c +++ b/Source/Assembler/Assm-util.c @@ -44,6 +44,19 @@ void toUppercase(char *str) { } int checkIfKeyword(intermediateElement *currentElement) { + // A string is never a keyword, however it is spelled. The quotes are gone by the time + // a token is looked at, so a program with "#Program" in its data - which is exactly + // what an assembler written for this machine needs, to compare tokens against - had + // the string read as the directive. The segment silently changed in the middle of the + // Data Segment, the string's nine bytes were charged to the Program cursor, and every + // label after it was nine bytes out while the file itself still looked well formed. + // + // This is the fourth of this family: the instruction check and the literal check both + // carry the same guard, for the same reason. It lives inside this one rather than at + // the call site so that it cannot be left off again. + if (currentElement->type == STRING) { + return 0; + } if (currentElement->token[0] == '#') { if (debug) printf("Token: %s is a keyword.\n", currentElement->token); currentElement->type = KEYWORD; diff --git a/Tests/expected/stringKeyword.out b/Tests/expected/stringKeyword.out new file mode 100644 index 0000000..c4cc509 --- /dev/null +++ b/Tests/expected/stringKeyword.out @@ -0,0 +1,4 @@ +#Program #Data #Include #Vectors #Base #Align #Reserve +and a label after them still points at itself +Execution halted. +[exit 0] diff --git a/Tests/manifest b/Tests/manifest index 0d0e968..ea90ea0 100644 --- a/Tests/manifest +++ b/Tests/manifest @@ -387,6 +387,11 @@ diagUnbasedSegment | testPrograms/diagnostics/unbasedSegment.asm | xfail | - lib-print | Libraries/print.asm | xfail | - | - # These three call print.asm routines but have no #Include line at all. They are # only ever pulled in by printTest.asm, so they are not standalone programs. +# A string that spells a directive is a string. The quotes are gone by the time a token is +# looked at, so "#Program" in a program's data was read as the directive: the segment +# changed in the middle of the Data Segment and every label after it came out nine bytes +# wrong, in a file that still had a valid header and a plausible length. +stringKeyword | testPrograms/stringKeyword.asm | run | - | - printDecimalTest | testPrograms/printDecimalTest.asm | xfail | - | - printDigitTest | testPrograms/printDigitTest.asm | xfail | - | - printHexTest | testPrograms/printHexTest.asm | xfail | - | -