Skip to content

Commit 551e20d

Browse files
authored
[ELF] Reject error-prone meta characters in input section description
The lexer is overly permissive. When parsing file patterns in an input section description and there is a missing `)`, we would accept many non-sensible tokens (e.g. `}`) as patterns, leading to confusion, e.g. `*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.text*)) } PROVIDE_HIDDEN(__code_end = .)` (#81804). Ideally, the lexer should be stateful to report more errors like GNU ld and get rid of hacks like `ScriptLexer::maybeSplitExpr`, but that would require a large rewrite of the lexer. For now, just reject certain non-wildcard meta characters to detect common mistakes. Pull Request: #84130
1 parent 318bff6 commit 551e20d

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

lld/ELF/ScriptParser.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -717,9 +717,19 @@ SmallVector<SectionPattern, 0> ScriptParser::readInputSectionsList() {
717717

718718
StringMatcher SectionMatcher;
719719
// Break if the next token is ), EXCLUDE_FILE, or SORT*.
720-
while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE" &&
721-
peekSortKind() == SortSectionPolicy::Default)
720+
while (!errorCount() && peekSortKind() == SortSectionPolicy::Default) {
721+
StringRef s = peek();
722+
if (s == ")" || s == "EXCLUDE_FILE")
723+
break;
724+
// Detect common mistakes when certain non-wildcard meta characters are
725+
// used without a closing ')'.
726+
if (!s.empty() && strchr("(){}", s[0])) {
727+
skip();
728+
setError("section pattern is expected");
729+
break;
730+
}
722731
SectionMatcher.addPattern(unquote(next()));
732+
}
723733

724734
if (!SectionMatcher.empty())
725735
ret.push_back({std::move(excludeFilePat), std::move(SectionMatcher)});

lld/test/ELF/linkerscript/wildcards.s

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,26 +91,42 @@ SECTIONS {
9191
.text : { *([.]abc .ab[v-y] ) }
9292
}
9393

94-
## Test a few non-wildcard meta characters rejected by GNU ld.
94+
## Test a few non-wildcard characters rejected by GNU ld.
9595

9696
#--- lbrace.lds
97-
# RUN: ld.lld -T lbrace.lds a.o -o out
97+
# RUN: not ld.lld -T lbrace.lds a.o 2>&1 | FileCheck %s --check-prefix=ERR-LBRACE --match-full-lines --strict-whitespace
98+
# ERR-LBRACE:{{.*}}: section pattern is expected
99+
# ERR-LBRACE-NEXT:>>> .text : { *(.a* { ) }
100+
# ERR-LBRACE-NEXT:>>> ^
98101
SECTIONS {
99102
.text : { *(.a* { ) }
100103
}
101104

105+
#--- lbrace2.lds
106+
# RUN: not ld.lld -T lbrace2.lds a.o 2>&1 | FileCheck %s --check-prefix=ERR-LBRACE2 --match-full-lines --strict-whitespace
107+
# ERR-LBRACE2:{{.*}}: section pattern is expected
108+
# ERR-LBRACE2-NEXT:>>> .text : { *(.a*{) }
109+
# ERR-LBRACE2-NEXT:>>> ^
110+
SECTIONS {
111+
.text : { *(.a*{) }
112+
}
113+
102114
#--- lparen.lds
103-
## ( is recognized as a section name pattern. Note, ( is rejected by GNU ld.
104-
# RUN: ld.lld -T lparen.lds a.o -o out
105-
# RUN: llvm-objdump --section-headers out | FileCheck --check-prefix=SEC-NO %s
115+
# RUN: not ld.lld -T lparen.lds a.o 2>&1 | FileCheck %s --check-prefix=ERR-LPAREN --match-full-lines --strict-whitespace
116+
# ERR-LPAREN:{{.*}}: section pattern is expected
117+
# ERR-LPAREN-NEXT:>>> .text : { *(.a* ( ) }
118+
# ERR-LPAREN-NEXT:>>> ^
106119
SECTIONS {
107-
.text : { *(.a* ( ) }
120+
.text : { *(.a* ( ) }
108121
}
109122

110123
#--- rbrace.lds
111-
# RUN: ld.lld -T rbrace.lds a.o -o out
124+
# RUN: not ld.lld -T rbrace.lds a.o 2>&1 | FileCheck %s --check-prefix=ERR-RBRACE --match-full-lines --strict-whitespace
125+
# ERR-RBRACE:{{.*}}: section pattern is expected
126+
# ERR-RBRACE-NEXT:>>> .text : { *(.a* x = 3; } ) }
127+
# ERR-RBRACE-NEXT:>>> ^
112128
SECTIONS {
113-
.text : { *(.a* } ) }
129+
.text : { *(.a* x = 3; } ) }
114130
}
115131

116132
#--- rparen.lds

0 commit comments

Comments
 (0)