[llvm] 2d48b40 - Fix UB in DIExpression::appendOffset()

Adrian Prantl via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 19 09:17:28 PDT 2022


Author: Adrian Prantl
Date: 2022-08-19T09:16:59-07:00
New Revision: 2d48b403f6e21dc09fadf3b490a860873b85a3ac

URL: https://github.com/llvm/llvm-project/commit/2d48b403f6e21dc09fadf3b490a860873b85a3ac
DIFF: https://github.com/llvm/llvm-project/commit/2d48b403f6e21dc09fadf3b490a860873b85a3ac.diff

LOG: Fix UB in DIExpression::appendOffset()

The absolute value of 0x8000000000000000 does not fit into an int64_t
and UBSan tells us that by crashing.

rdar://98799670

Differential Revision: https://reviews.llvm.org/D132194

Added: 
    llvm/test/DebugInfo/salvage-overflow.ll

Modified: 
    llvm/lib/IR/DebugInfoMetadata.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 50799327c78a0..1b2c3ee936027 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -1387,7 +1387,10 @@ void DIExpression::appendOffset(SmallVectorImpl<uint64_t> &Ops,
     Ops.push_back(Offset);
   } else if (Offset < 0) {
     Ops.push_back(dwarf::DW_OP_constu);
-    Ops.push_back(-Offset);
+    // Avoid UB when encountering LLONG_MIN, because in 2's complement
+    // abs(LLONG_MIN) is LLONG_MAX+1.
+    uint64_t AbsMinusOne = -(Offset+1);
+    Ops.push_back(AbsMinusOne + 1);
     Ops.push_back(dwarf::DW_OP_minus);
   }
 }

diff  --git a/llvm/test/DebugInfo/salvage-overflow.ll b/llvm/test/DebugInfo/salvage-overflow.ll
new file mode 100644
index 0000000000000..873583fc9f772
--- /dev/null
+++ b/llvm/test/DebugInfo/salvage-overflow.ll
@@ -0,0 +1,45 @@
+; RUN: opt %s -sroa -early-cse -S | FileCheck %s
+; CHECK: DIExpression(DW_OP_constu, 9223372036854775808, DW_OP_minus, DW_OP_stack_value)
+; Created from the following C input (and then delta-reduced the IR):
+;
+; extern unsigned long long use(unsigned long long);
+; void f(unsigned long long x) {
+;   for (; x > 0; x --) {
+;     unsigned long long y = x + 0x8000000000000000;
+;     use(x);
+;   }
+; }
+
+define void @f(i64 noundef %x) #0 !dbg !9 {
+entry:
+  %x.addr = alloca i64, align 8
+  %y = alloca i64, align 8
+  br label %for.cond
+for.cond:                                         ; preds = %for.inc, %entry
+  %0 = load i64, i64* %x.addr, align 8
+  %1 = bitcast i64* %y to i8*
+  call void @llvm.dbg.declare(metadata i64* %y, metadata !15, metadata !DIExpression())
+, !dbg !29
+  %2 = load i64, i64* %x.addr, align 8
+  %add = add i64 %2, -9223372036854775808
+  store i64 %add, i64* %y, align 8
+  br label %for.cond
+}
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+!llvm.module.flags = !{!3,!7}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None, sysroot: "/")
+!1 = !DIFile(filename: "t.c", directory: "/")
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!7 = !{i32 7, !"frame-pointer", i32 2}
+!9 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 2, type: !10, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13)
+!10 = !DISubroutineType(types: !11)
+!11 = !{null, !12}
+!12 = !DIBasicType(name: "unsigned long long", size: 64, encoding: DW_ATE_unsigned)
+!13 = !{}
+!15 = !DILocalVariable(name: "y", scope: !16, file: !1, line: 4, type: !12)
+!16 = distinct !DILexicalBlock(scope: !17, file: !1, line: 3, column: 23)
+!17 = distinct !DILexicalBlock(scope: !18, file: !1, line: 3, column: 3)
+!18 = distinct !DILexicalBlock(scope: !9, file: !1, line: 3, column: 3)
+!29 = !DILocation(line: 4, column: 24, scope: !16)


        


More information about the llvm-commits mailing list