From 90d95dd89a9c2f7b8c8b71c1042ad61d0a6e6729 Mon Sep 17 00:00:00 2001 From: Vince Bridgers Date: Tue, 12 Nov 2024 00:56:14 +0100 Subject: [PATCH] [codegen] Fix crash in codegan caused by pointer calculation overflow Fixes https://github.com/llvm/llvm-project/issues/48168 Under certain conditions, the front end does not detect a possible overflow address calculations until codegen. This change emits a warning instead of allowing the compiler to crash. clang: /clang/lib/CodeGen/CGExprScalar.cpp:5834: llvm::Value* clang::CodeGen::CodeGenFunction::EmitCheckedInBoundsGEP( llvm::Type*, llvm::Value*, llvm::ArrayRef, bool, bool, clang::SourceLocation, const llvm::Twine&): Assertion `(!isa(EvaluatedGEP.TotalOffset) || EvaluatedGEP.OffsetOverflows == Builder.getFalse()) && "If the offset got constant-folded, we don't expect that there was an " "overflow."' failed. 0. Program arguments: clang -c --target=x86_64-- -fsanitize=undefined ubsan-emit-bounds-check-crash-x86.c 1. parser at end of file 2. ubsan-emit-bounds-check-crash-x86.c:4:5: LLVM IR generation of declaration 'main' 3. ubsan-emit-bounds-check-crash-x86.c:4:5: Generating code for declaration 'main' ... #9 clang::CodeGen::CodeGenFunction::EmitCheckedInBoundsGEP(clang::CodeGen::Address, llvm::ArrayRef, llvm::Type*, bool, bool, clang::SourceLocation, clang::CharUnits, llvm::Twine const&) llvm::ArrayRef, clang::QualType, bool, bool, clang::SourceLocation, clang::QualType*, clang::Expr const*, llvm::Twine const&) CGExpr.cpp:0:0 bool) --- clang/lib/CodeGen/CGExprScalar.cpp | 13 +++++++++---- .../CodeGen/ubsan-emit-bounds-check-crash-msp.c | 7 +++++++ .../CodeGen/ubsan-emit-bounds-check-crash-x86.c | 7 +++++++ 3 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 clang/test/CodeGen/ubsan-emit-bounds-check-crash-msp.c create mode 100644 clang/test/CodeGen/ubsan-emit-bounds-check-crash-x86.c diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 287d911e10ba5..5ed865820a915 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -5831,10 +5831,15 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr, GEPOffsetAndOverflow EvaluatedGEP = EmitGEPOffsetInBytes(Ptr, GEPVal, getLLVMContext(), CGM, Builder); - assert((!isa(EvaluatedGEP.TotalOffset) || - EvaluatedGEP.OffsetOverflows == Builder.getFalse()) && - "If the offset got constant-folded, we don't expect that there was an " - "overflow."); + if (!(!isa(EvaluatedGEP.TotalOffset) || + EvaluatedGEP.OffsetOverflows == Builder.getFalse())) { + DiagnosticsEngine &Diags = CGM.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, "Expression caused pointer calculation " + "overflow during code generation"); + Diags.Report(Loc, DiagID); + return GEPVal; + } auto *Zero = llvm::ConstantInt::getNullValue(IntPtrTy); diff --git a/clang/test/CodeGen/ubsan-emit-bounds-check-crash-msp.c b/clang/test/CodeGen/ubsan-emit-bounds-check-crash-msp.c new file mode 100644 index 0000000000000..b4da2f2b7ee72 --- /dev/null +++ b/clang/test/CodeGen/ubsan-emit-bounds-check-crash-msp.c @@ -0,0 +1,7 @@ +// REQUIRES: msp430-registered-target +// RUN: %clang -c -fsanitize=undefined -Wno-tentative-definition-array -Wno-return-type -Wno-unused-value -Wno-array-bounds -Xclang -verify --target=msp430-- %s +int a; +_Complex double b[1][1]; +void c(void) { + b[a][8920]; // expected-error {{Expression caused pointer calculation overflow during code generation}} +} diff --git a/clang/test/CodeGen/ubsan-emit-bounds-check-crash-x86.c b/clang/test/CodeGen/ubsan-emit-bounds-check-crash-x86.c new file mode 100644 index 0000000000000..63bda82c14ae2 --- /dev/null +++ b/clang/test/CodeGen/ubsan-emit-bounds-check-crash-x86.c @@ -0,0 +1,7 @@ +// REQUIRES: x86-registered-target +// RUN: %clang -c -Wno-tentative-definition-array -Wno-return-type -Wno-unused-value -Wno-array-bounds -Xclang -verify --target=x86_64-- -fsanitize=undefined %s +int **a[]; +int main() { + (*a)[3300220222222200000]; // expected-error {{Expression caused pointer calculation overflow during code generation}} + return 0; +}