[compiler-rt] [profile] Fix bounds checks in profile merging (PR #118782)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 5 02:33:23 PST 2024


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/118782

These bounds checks work on the result of the pointer addition -- but the pointer addition already asserts that no overflow may occur, so the checks are optimized away after #118472. Avoid this by performing the addition in a way that permits overflow.

>From 44d55b712497a7de358369b716186c5f3de3efdc Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Thu, 5 Dec 2024 11:30:28 +0100
Subject: [PATCH] [profile] Fix bounds checks in profile merging

These bounds checks work on the result of the pointer addition --
but the pointer addition already asserts that no overflow may
occur, so the checks are optimized away after #118472. Avoid this
by performing the addition in a way that permits overflow.
---
 compiler-rt/lib/profile/InstrProfilingMerge.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/compiler-rt/lib/profile/InstrProfilingMerge.c b/compiler-rt/lib/profile/InstrProfilingMerge.c
index 7cf1679811eb07..77fc69110c73ea 100644
--- a/compiler-rt/lib/profile/InstrProfilingMerge.c
+++ b/compiler-rt/lib/profile/InstrProfilingMerge.c
@@ -127,6 +127,12 @@ getDistanceFromCounterToValueProf(const __llvm_profile_header *const Header) {
          PaddingBytesAfterVNamesSize;
 }
 
+// Add offset to pointer without assuming that the addition does not overflow.
+// This allows performing bounds checks by checking the result of the addition.
+static const char *ptr_add_with_overflow(const char *p, size_t offset) {
+  return (const char *)((uintptr_t)p + offset);
+}
+
 COMPILER_RT_VISIBILITY
 int __llvm_profile_merge_from_buffer(const char *ProfileData,
                                      uint64_t ProfileSize) {
@@ -154,9 +160,10 @@ int __llvm_profile_merge_from_buffer(const char *ProfileData,
   SrcCountersStart = (char *)SrcDataEnd;
   SrcCountersEnd = SrcCountersStart +
                    Header->NumCounters * __llvm_profile_counter_entry_size();
-  SrcBitmapStart = SrcCountersEnd + __llvm_profile_get_num_padding_bytes(
-                                        SrcCountersEnd - SrcCountersStart);
-  SrcNameStart = SrcBitmapStart + Header->NumBitmapBytes;
+  SrcBitmapStart = ptr_add_with_overflow(
+      SrcCountersEnd,
+      __llvm_profile_get_num_padding_bytes(SrcCountersEnd - SrcCountersStart));
+  SrcNameStart = ptr_add_with_overflow(SrcBitmapStart, Header->NumBitmapBytes);
   SrcValueProfDataStart =
       SrcNameStart + getDistanceFromCounterToValueProf(Header);
   if (SrcNameStart < SrcCountersStart || SrcNameStart < SrcBitmapStart)
@@ -200,8 +207,8 @@ int __llvm_profile_merge_from_buffer(const char *ProfileData,
     // CountersDelta computes the offset into the in-buffer counter section.
     //
     // On WIN64, CountersDelta is truncated as well, so no need for signext.
-    char *SrcCounters =
-        SrcCountersStart + ((uintptr_t)SrcData->CounterPtr - CountersDelta);
+    char *SrcCounters = ptr_add_with_overflow(
+        SrcCountersStart, (uintptr_t)SrcData->CounterPtr - CountersDelta);
     // CountersDelta needs to be decreased as we advance to the next data
     // record.
     CountersDelta -= sizeof(*SrcData);



More information about the llvm-commits mailing list