From 802fcfe5f4f2458dd62340411d03c973a50e84cc Mon Sep 17 00:00:00 2001 From: Evgeny Leviant Date: Tue, 14 Apr 2026 16:17:11 +0200 Subject: [PATCH] Mitigate UB when subtracting pointers clang emits sdiv exact instruction, when subtracting pointers, assuming both of them belong to the same array and therefore are properly aligned. This is not the case, when we subtracting unrelated pointers, which may not be aligned to a type size. --- clang/lib/CodeGen/CGExprScalar.cpp | 3 +++ clang/test/CodeGen/MSKernel/subptr.c | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 clang/test/CodeGen/MSKernel/subptr.c diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 7529d4465f2c..af89b427531d 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4447,6 +4447,9 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) { divisor = CGF.CGM.getSize(elementSize); } + // With -fms-kernel we emit normal sdiv to mitigate UB. + if (CGF.getLangOpts().Kernel) + return Builder.CreateSDiv(diffInChars, divisor, "sub.ptr.div"); // Otherwise, do a full sdiv. This uses the "exact" form of sdiv, since // pointer difference in C is only defined in the case where both operands // are pointing to elements of an array. diff --git a/clang/test/CodeGen/MSKernel/subptr.c b/clang/test/CodeGen/MSKernel/subptr.c new file mode 100644 index 000000000000..13079bb840a5 --- /dev/null +++ b/clang/test/CodeGen/MSKernel/subptr.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fms-kernel -triple x86_64-windows-msvc -O2 -emit-llvm %s -o - | FileCheck %s +// CHECK: define {{.*}} i64 @sub_ptrs(ptr noundef %p1, ptr noundef %p2) +// CHECK-NEXT: entry: +// CHECK-NEXT: %sub.ptr.lhs.cast = ptrtoint ptr %p1 to i64 +// CHECK-NEXT: %sub.ptr.rhs.cast = ptrtoint ptr %p2 to i64 +// CHECK-NEXT: %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast +// CHECK-NEXT: %sub.ptr.div = sdiv i64 %sub.ptr.sub, 4 +// CHECK-NEXT: ret i64 %sub.ptr.div + +long long sub_ptrs(int* p1, int* p2) { + return p1 - p2; +} +