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

via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 5 02:34:03 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-pgo

Author: Nikita Popov (nikic)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/118782.diff


1 Files Affected:

- (modified) compiler-rt/lib/profile/InstrProfilingMerge.c (+12-5) 


``````````diff
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);

``````````

</details>


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


More information about the llvm-commits mailing list