From daba24ee7bd3d80f085e2e5f057af6b873a78a24 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 15 Jun 2023 10:34:33 -0700 Subject: [PATCH] [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. --- lld/ELF/ScriptParser.cpp | 8 ++++---- lld/test/ELF/linkerscript/operators.test | 10 +++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index a4fb0f7c6e17..85cee08999cd 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -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 == ">") diff --git a/lld/test/ELF/linkerscript/operators.test b/lld/test/ELF/linkerscript/operators.test index 3958b956a8eb..0b6fdc2fe63f 100644 --- a/lld/test/ELF/linkerscript/operators.test +++ b/lld/test/ELF/linkerscript/operators.test @@ -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