diff options
author | Yingwei Zheng <dtcxzyw2333@gmail.com> | 2025-05-09 14:53:00 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-09 14:53:00 +0800 |
commit | d2b012e3913a56d3cb2d9798bf77dc2599148dfb (patch) | |
tree | 2b598be59efe4ba03536c7fbc0594d6b01822d45 /clang | |
parent | 03d3e6dbe9e7a0c64e6c62b583bb187723421717 (diff) | |
download | llvm-d2b012e3913a56d3cb2d9798bf77dc2599148dfb.zip llvm-d2b012e3913a56d3cb2d9798bf77dc2599148dfb.tar.gz llvm-d2b012e3913a56d3cb2d9798bf77dc2599148dfb.tar.bz2 |
[Clang][CodeGen] Enable pointer overflow check for GCC workaround (#137849)
Do not suppress the pointer overflow check for the `(i8*) nullptr + N`
idiom.
Related issue: https://github.com/llvm/llvm-project/issues/137833
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 27 | ||||
-rw-r--r-- | clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c | 21 |
2 files changed, 43 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index f639a87..df793a5 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4180,11 +4180,28 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, // The index is not pointer-sized. // The pointer type is not byte-sized. // - if (BinaryOperator::isNullPointerArithmeticExtension(CGF.getContext(), - op.Opcode, - expr->getLHS(), - expr->getRHS())) - return CGF.Builder.CreateIntToPtr(index, pointer->getType()); + // Note that we do not suppress the pointer overflow check in this case. + if (BinaryOperator::isNullPointerArithmeticExtension( + CGF.getContext(), op.Opcode, expr->getLHS(), expr->getRHS())) { + Value *Ptr = CGF.Builder.CreateIntToPtr(index, pointer->getType()); + if (CGF.getLangOpts().PointerOverflowDefined || + !CGF.SanOpts.has(SanitizerKind::PointerOverflow) || + NullPointerIsDefined(CGF.Builder.GetInsertBlock()->getParent(), + PtrTy->getPointerAddressSpace())) + return Ptr; + // The inbounds GEP of null is valid iff the index is zero. + CodeGenFunction::SanitizerScope SanScope(&CGF); + Value *IsZeroIndex = CGF.Builder.CreateIsNull(index); + llvm::Constant *StaticArgs[] = { + CGF.EmitCheckSourceLocation(op.E->getExprLoc())}; + llvm::Type *IntPtrTy = DL.getIntPtrType(PtrTy); + Value *IntPtr = llvm::Constant::getNullValue(IntPtrTy); + Value *ComputedGEP = CGF.Builder.CreateZExtOrTrunc(index, IntPtrTy); + Value *DynamicArgs[] = {IntPtr, ComputedGEP}; + CGF.EmitCheck({{IsZeroIndex, SanitizerKind::SO_PointerOverflow}}, + SanitizerHandler::PointerOverflow, StaticArgs, DynamicArgs); + return Ptr; + } if (width != DL.getIndexTypeSizeInBits(PtrTy)) { // Zero-extend or sign-extend the pointer value according to diff --git a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c index 63b6db2..26d17e7 100644 --- a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c +++ b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c @@ -32,6 +32,7 @@ // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1500:.*]] = {{.*}}, i32 1500, i32 15 } } // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1600:.*]] = {{.*}}, i32 1600, i32 15 } } // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1700:.*]] = {{.*}}, i32 1700, i32 15 } } +// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1800:.*]] = {{.*}}, i32 1800, i32 20 } } #ifdef __cplusplus extern "C" { @@ -431,6 +432,26 @@ char *void_ptr(void *base, unsigned long offset) { return base + offset; } +char *constant_null_add(unsigned long offset) { + // CHECK: define{{.*}} ptr @constant_null_add(i64 noundef %[[OFFSET:.*]]) + // CHECK-NEXT: [[ENTRY:.*]]: + // CHECK-NEXT: %[[OFFSET_ADDR:.*]] = alloca i64, align 8 + // CHECK-NEXT: store i64 %[[OFFSET]], ptr %[[OFFSET_ADDR]], align 8 + // CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, ptr %[[OFFSET_ADDR]], align 8 + // CHECK-NEXT: %[[ADD_PTR:.*]] = inttoptr i64 %[[OFFSET_RELOADED]] to ptr + // CHECK-SANITIZE-NEXT: %[[IS_NULL:.*]] = icmp eq i64 %[[OFFSET_RELOADED]], 0, !nosanitize + // CHECK-SANITIZE-NEXT: br i1 %[[IS_NULL]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: + // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1800]], i64 0, i64 %[[OFFSET_RELOADED]]) + // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1800]], i64 0, i64 %[[OFFSET_RELOADED]]) + // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize + // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize + // CHECK-SANITIZE: [[CONT]]: + // CHECK-NEXT: ret ptr %[[ADD_PTR]] +#line 1800 + return (char *)0 + offset; +} + #ifdef __cplusplus } #endif |