[ELF] << >>: make RHS less than 64
authorFangrui Song <i@maskray.me>
Thu, 15 Jun 2023 17:34:33 +0000 (10:34 -0700)
committerFangrui Song <i@maskray.me>
Thu, 15 Jun 2023 17:34:33 +0000 (10:34 -0700)
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
lld/test/ELF/linkerscript/operators.test

index a4fb0f7..85cee08 100644 (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 == ">")
index 3958b95..0b6fdc2 100644 (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