[ELF] << >>: make RHS less than 64

The left/right shift linker script operators may trigger UB.
E.g. in linkerscript/end-overflow-check.test, the initial REGION1__PADDED_SR_SHIFT is
uint64_t(-3), cause the following expression to trigger an out-of-range shift in
a ubsan build of lld.

    REGION1__PADDED_SR_SIZE = MAX(1 << REGION1__PADDED_SR_SHIFT, 32);

Protect such UBs by making RHS less than 64.
This commit is contained in:
Fangrui Song 2023-06-15 10:34:33 -07:00
parent faf7cd97d0
commit daba24ee7b
2 changed files with 11 additions and 7 deletions

View File

@ -1094,9 +1094,9 @@ SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
case '-':
return sub(lhs, e());
case '<':
return lhs.getValue() << e().getValue();
return lhs.getValue() << e().getValue() % 64;
case '>':
return lhs.getValue() >> e().getValue();
return lhs.getValue() >> e().getValue() % 64;
case '&':
return lhs.getValue() & e().getValue();
case '|':
@ -1147,9 +1147,9 @@ Expr ScriptParser::combine(StringRef op, Expr l, Expr r) {
};
}
if (op == "<<")
return [=] { return l().getValue() << r().getValue(); };
return [=] { return l().getValue() << r().getValue() % 64; };
if (op == ">>")
return [=] { return l().getValue() >> r().getValue(); };
return [=] { return l().getValue() >> r().getValue() % 64; };
if (op == "<")
return [=] { return l().getValue() < r().getValue(); };
if (op == ">")

View File

@ -12,6 +12,7 @@ SECTIONS {
multiplicative = 20 / 2 % 7;
additive = 1 - 2 + -3 * -2;
shift = 2 << 5 >> 1 << 2;
shift2 = 2 << 69 >> 65;
less = 1 < 0 ? 1 : 2;
lesseq = 1<<0 <= 1>>0 ? 1 : 2;
greater = 0 > 1 ? 1 : 2;
@ -36,9 +37,11 @@ SECTIONS {
minusassign = 3;
minusassign -= 1;
lshiftassign = 1;
lshiftassign <<= 2;
rshiftassign = 5;
lshiftassign <<= 1;
lshiftassign <<= 65; # arbitrarily reduced to 1
rshiftassign = 24;
rshiftassign >>= 1;
rshiftassign >>= 130; # arbitrarily reduced to 2
andassign = 6;
andassign &= 4;
orassign = 4;
@ -73,6 +76,7 @@ SECTIONS {
# CHECK-NEXT: 0000000000000003 A multiplicative
# CHECK-NEXT: 0000000000000005 A additive
# CHECK-NEXT: 0000000000000080 A shift
# CHECK-NEXT: 0000000000000020 A shift
# CHECK-NEXT: 0000000000000002 A less
# CHECK-NEXT: 0000000000000001 A lesseq
# CHECK-NEXT: 0000000000000002 A greater
@ -92,7 +96,7 @@ SECTIONS {
# CHECK-NEXT: 0000000000000003 A plusassign
# CHECK-NEXT: 0000000000000002 A minusassign
# CHECK-NEXT: 0000000000000004 A lshiftassign
# CHECK-NEXT: 0000000000000002 A rshiftassign
# CHECK-NEXT: 0000000000000003 A rshiftassign
# CHECK-NEXT: 0000000000000004 A andassign
# CHECK-NEXT: 0000000000000005 A orassign
# CHECK-NEXT: 0000000000000015 A braces