From fe3b238dead49275838babd6f7757253e8cc7c6c Mon Sep 17 00:00:00 2001 From: Rangi <35663410+Rangi42@users.noreply.github.com> Date: Mon, 6 Jul 2026 16:18:42 -0400 Subject: [PATCH] Do not allow defining labels outside sections (#2013) Creating a `Symbol` with `type = SYM_LABEL` but `section = nullptr` is inconsistent and dangerous. I was not able to cause any buggy behavior so far, but it's safer and reasonable to not create such a symbol in the first place. The main consequence is that `DEF(LabelOutsideSection)` will now evaluate as 0. --- src/asm/rpn.cpp | 4 ++-- src/asm/symbol.cpp | 13 ++++++++----- test/asm/anon-label-bad.err | 2 +- test/asm/label-outside-section.err | 2 +- test/asm/line-continuation-whitespace.err | 2 +- test/asm/line-continuation.err | 2 +- test/asm/macro-@.err | 2 +- test/asm/macro-syntax.err | 4 ++-- test/asm/pops-restore-no-section.err | 2 +- test/asm/use-label-outside-section.asm | 3 ++- test/asm/use-label-outside-section.err | 6 +++--- test/asm/use-label-outside-section.out | 1 + 12 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/asm/rpn.cpp b/src/asm/rpn.cpp index d8c75dc5..a479ac27 100644 --- a/src/asm/rpn.cpp +++ b/src/asm/rpn.cpp @@ -227,9 +227,9 @@ static int32_t tryConstMask(Expression const &lhs, Expression const &rhs) { return -1; } - assume(sym.isNumeric()); + assume(sym.type == SYM_LABEL); + // We can now safely use `expr.value()` and `sym.getSection()` - // We can now safely use `expr.value()` int32_t mask = expr.value(); // The mask must not cover any unknown bits diff --git a/src/asm/symbol.cpp b/src/asm/symbol.cpp index 1dd9b645..cc3a2383 100644 --- a/src/asm/symbol.cpp +++ b/src/asm/symbol.cpp @@ -537,6 +537,12 @@ Symbol *sym_AddVar(InternedStr symName, int32_t value) { static Symbol *addLabel(InternedStr symName) { assumeAlreadyExpanded(symName); + Section *section = sect_GetSymbolSection(); + if (!section) { + error("Cannot define label `%s` outside of a `SECTION`", symName.c_str()); + return nullptr; + } + Symbol *sym = sym_FindExactSymbol(symName); if (!sym) { @@ -547,6 +553,7 @@ static Symbol *addLabel(InternedStr symName) { } else { updateSymbolFilename(*sym); } + // If the symbol already exists as a ref, just "take over" it sym->type = SYM_LABEL; sym->data = static_cast(sect_GetSymbolOffset()); @@ -554,11 +561,7 @@ static Symbol *addLabel(InternedStr symName) { if (options.exportAll && !symName.str().starts_with('!')) { sym->isExported = true; } - sym->section = sect_GetSymbolSection(); - - if (sym && !sym->section) { - error("Label `%s` created outside of a `SECTION`", symName.c_str()); - } + sym->section = section; return sym; } diff --git a/test/asm/anon-label-bad.err b/test/asm/anon-label-bad.err index e4777723..4c404f8f 100644 --- a/test/asm/anon-label-bad.err +++ b/test/asm/anon-label-bad.err @@ -1,4 +1,4 @@ -error: Label `!0` created outside of a `SECTION` +error: Cannot define label `!0` outside of a `SECTION` at anon-label-bad.asm(2) error: Reference to anonymous label 2 before, when only 1 has been created so far at anon-label-bad.asm(6) diff --git a/test/asm/label-outside-section.err b/test/asm/label-outside-section.err index 9d511be9..e3dcdc4e 100644 --- a/test/asm/label-outside-section.err +++ b/test/asm/label-outside-section.err @@ -1,3 +1,3 @@ -error: Label `bad` created outside of a `SECTION` +error: Cannot define label `bad` outside of a `SECTION` at label-outside-section.asm(1) Assembly aborted with 1 error diff --git a/test/asm/line-continuation-whitespace.err b/test/asm/line-continuation-whitespace.err index 45dd5edc..12a06b7d 100644 --- a/test/asm/line-continuation-whitespace.err +++ b/test/asm/line-continuation-whitespace.err @@ -1,3 +1,3 @@ -error: Label `foo` created outside of a `SECTION` +error: Cannot define label `foo` outside of a `SECTION` at line-continuation-whitespace.asm(7) Assembly aborted with 1 error diff --git a/test/asm/line-continuation.err b/test/asm/line-continuation.err index 2a056973..2ae31dcc 100644 --- a/test/asm/line-continuation.err +++ b/test/asm/line-continuation.err @@ -2,6 +2,6 @@ error: Invalid character 's' after line continuation at line-continuation.asm(3) warning: spam [-Wuser] at line-continuation.asm::spam(4) <- line-continuation.asm(6) -error: Label `foo` created outside of a `SECTION` +error: Cannot define label `foo` outside of a `SECTION` at line-continuation.asm(14) Assembly aborted with 2 errors diff --git a/test/asm/macro-@.err b/test/asm/macro-@.err index bdc08941..54b58c5f 100644 --- a/test/asm/macro-@.err +++ b/test/asm/macro-@.err @@ -1,4 +1,4 @@ -error: Label `foo` created outside of a `SECTION` +error: Cannot define label `foo` outside of a `SECTION` at macro-@.asm(1) error: `@` is not a macro at macro-@.asm(1) diff --git a/test/asm/macro-syntax.err b/test/asm/macro-syntax.err index 04c2fcdc..7745bdb4 100644 --- a/test/asm/macro-syntax.err +++ b/test/asm/macro-syntax.err @@ -1,4 +1,4 @@ -error: Label `old` created outside of a `SECTION` +error: Cannot define label `old` outside of a `SECTION` at macro-syntax.asm(7) error: syntax error, unexpected MACRO at macro-syntax.asm(7) @@ -6,6 +6,6 @@ error: `\1` cannot be used outside of a macro at macro-syntax.asm(8) error: syntax error, unexpected ENDM at macro-syntax.asm(9) -error: `old` is not a macro +error: Undefined macro `old` at macro-syntax.asm(11) Assembly aborted with 5 errors diff --git a/test/asm/pops-restore-no-section.err b/test/asm/pops-restore-no-section.err index 89cffd98..652be0a8 100644 --- a/test/asm/pops-restore-no-section.err +++ b/test/asm/pops-restore-no-section.err @@ -1,4 +1,4 @@ -error: Label `DisallowedContent` created outside of a `SECTION` +error: Cannot define label `DisallowedContent` outside of a `SECTION` at pops-restore-no-section.asm(9) error: Cannot output data outside of a `SECTION` at pops-restore-no-section.asm(10) diff --git a/test/asm/use-label-outside-section.asm b/test/asm/use-label-outside-section.asm index a1d24da0..58094f75 100644 --- a/test/asm/use-label-outside-section.asm +++ b/test/asm/use-label-outside-section.asm @@ -1,2 +1,3 @@ lab: - PRINTLN lab-lab + PRINTLN DEF(lab) + PRINTLN lab - lab diff --git a/test/asm/use-label-outside-section.err b/test/asm/use-label-outside-section.err index 8b73984e..ac1144e9 100644 --- a/test/asm/use-label-outside-section.err +++ b/test/asm/use-label-outside-section.err @@ -1,5 +1,5 @@ -error: Label `lab` created outside of a `SECTION` +error: Cannot define label `lab` outside of a `SECTION` at use-label-outside-section.asm(1) -error: Expected constant expression: `lab` is not constant at assembly time - at use-label-outside-section.asm(2) +error: Expected constant expression: undefined symbol `lab` + at use-label-outside-section.asm(3) Assembly aborted with 2 errors diff --git a/test/asm/use-label-outside-section.out b/test/asm/use-label-outside-section.out index ebfabbe4..22bfd727 100644 --- a/test/asm/use-label-outside-section.out +++ b/test/asm/use-label-outside-section.out @@ -1 +1,2 @@ $0 +$0