Skip to content

Commit d2b012e

Browse files
authored
[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: #137833
1 parent 03d3e6d commit d2b012e

File tree

2 files changed

+43
-5
lines changed

2 files changed

+43
-5
lines changed

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4180,11 +4180,28 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
41804180
// The index is not pointer-sized.
41814181
// The pointer type is not byte-sized.
41824182
//
4183-
if (BinaryOperator::isNullPointerArithmeticExtension(CGF.getContext(),
4184-
op.Opcode,
4185-
expr->getLHS(),
4186-
expr->getRHS()))
4187-
return CGF.Builder.CreateIntToPtr(index, pointer->getType());
4183+
// Note that we do not suppress the pointer overflow check in this case.
4184+
if (BinaryOperator::isNullPointerArithmeticExtension(
4185+
CGF.getContext(), op.Opcode, expr->getLHS(), expr->getRHS())) {
4186+
Value *Ptr = CGF.Builder.CreateIntToPtr(index, pointer->getType());
4187+
if (CGF.getLangOpts().PointerOverflowDefined ||
4188+
!CGF.SanOpts.has(SanitizerKind::PointerOverflow) ||
4189+
NullPointerIsDefined(CGF.Builder.GetInsertBlock()->getParent(),
4190+
PtrTy->getPointerAddressSpace()))
4191+
return Ptr;
4192+
// The inbounds GEP of null is valid iff the index is zero.
4193+
CodeGenFunction::SanitizerScope SanScope(&CGF);
4194+
Value *IsZeroIndex = CGF.Builder.CreateIsNull(index);
4195+
llvm::Constant *StaticArgs[] = {
4196+
CGF.EmitCheckSourceLocation(op.E->getExprLoc())};
4197+
llvm::Type *IntPtrTy = DL.getIntPtrType(PtrTy);
4198+
Value *IntPtr = llvm::Constant::getNullValue(IntPtrTy);
4199+
Value *ComputedGEP = CGF.Builder.CreateZExtOrTrunc(index, IntPtrTy);
4200+
Value *DynamicArgs[] = {IntPtr, ComputedGEP};
4201+
CGF.EmitCheck({{IsZeroIndex, SanitizerKind::SO_PointerOverflow}},
4202+
SanitizerHandler::PointerOverflow, StaticArgs, DynamicArgs);
4203+
return Ptr;
4204+
}
41884205

41894206
if (width != DL.getIndexTypeSizeInBits(PtrTy)) {
41904207
// Zero-extend or sign-extend the pointer value according to

clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1500:.*]] = {{.*}}, i32 1500, i32 15 } }
3333
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1600:.*]] = {{.*}}, i32 1600, i32 15 } }
3434
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1700:.*]] = {{.*}}, i32 1700, i32 15 } }
35+
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1800:.*]] = {{.*}}, i32 1800, i32 20 } }
3536

3637
#ifdef __cplusplus
3738
extern "C" {
@@ -431,6 +432,26 @@ char *void_ptr(void *base, unsigned long offset) {
431432
return base + offset;
432433
}
433434

435+
char *constant_null_add(unsigned long offset) {
436+
// CHECK: define{{.*}} ptr @constant_null_add(i64 noundef %[[OFFSET:.*]])
437+
// CHECK-NEXT: [[ENTRY:.*]]:
438+
// CHECK-NEXT: %[[OFFSET_ADDR:.*]] = alloca i64, align 8
439+
// CHECK-NEXT: store i64 %[[OFFSET]], ptr %[[OFFSET_ADDR]], align 8
440+
// CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, ptr %[[OFFSET_ADDR]], align 8
441+
// CHECK-NEXT: %[[ADD_PTR:.*]] = inttoptr i64 %[[OFFSET_RELOADED]] to ptr
442+
// CHECK-SANITIZE-NEXT: %[[IS_NULL:.*]] = icmp eq i64 %[[OFFSET_RELOADED]], 0, !nosanitize
443+
// CHECK-SANITIZE-NEXT: br i1 %[[IS_NULL]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
444+
// CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]:
445+
// CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1800]], i64 0, i64 %[[OFFSET_RELOADED]])
446+
// CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1800]], i64 0, i64 %[[OFFSET_RELOADED]])
447+
// CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize
448+
// CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
449+
// CHECK-SANITIZE: [[CONT]]:
450+
// CHECK-NEXT: ret ptr %[[ADD_PTR]]
451+
#line 1800
452+
return (char *)0 + offset;
453+
}
454+
434455
#ifdef __cplusplus
435456
}
436457
#endif

0 commit comments

Comments
 (0)