Skip to content

Conversation

@igorkudrin
Copy link
Collaborator

GetHeapRanges() could return two overlapping ranges because it did not check whether heap_pointer1 lies within the range returned for heap_pointer2. This could result in a test failure in test_find_ranges_in_memory_two_matches when
process.FindRangesInMemory() returned 3 instead of 2.

The patch ensures that GetHeapRanges() returns either two non-overlapping ranges or one range covering both heap pointers.

The issue was probably introduced in #111951

`GetHeapRanges()` could return two overlapping ranges because it did not
check whether `heap_pointer1` lies within the range returned for
`heap_pointer2`. This could result in a test failure in
`test_find_ranges_in_memory_two_matches` when
`process.FindRangesInMemory()` returned 3 instead of 2.

The patch ensures that `GetHeapRanges()` returns either two
non-overlapping ranges or one range covering both heap pointers.
@llvmbot
Copy link
Member

llvmbot commented Aug 9, 2025

@llvm/pr-subscribers-lldb

Author: Igor Kudrin (igorkudrin)

Changes

GetHeapRanges() could return two overlapping ranges because it did not check whether heap_pointer1 lies within the range returned for heap_pointer2. This could result in a test failure in test_find_ranges_in_memory_two_matches when
process.FindRangesInMemory() returned 3 instead of 2.

The patch ensures that GetHeapRanges() returns either two non-overlapping ranges or one range covering both heap pointers.

The issue was probably introduced in #111951


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

1 Files Affected:

  • (modified) lldb/test/API/python_api/find_in_memory/address_ranges_helper.py (+20-13)
diff --git a/lldb/test/API/python_api/find_in_memory/address_ranges_helper.py b/lldb/test/API/python_api/find_in_memory/address_ranges_helper.py
index dcceca6d8a5c5..102f2b0edd4c6 100644
--- a/lldb/test/API/python_api/find_in_memory/address_ranges_helper.py
+++ b/lldb/test/API/python_api/find_in_memory/address_ranges_helper.py
@@ -55,27 +55,34 @@ def GetRangeFromAddrValue(test_base, addr, shrink=False):
     return lldb.SBAddressRange(start, size)
 
 
-def IsWithinRange(addr, size, range, target):
-    start_addr = range.GetBaseAddress().GetLoadAddress(target)
-    end_addr = start_addr + range.GetByteSize()
-    addr = addr.GetValueAsUnsigned()
-    return addr >= start_addr and addr + size <= end_addr
-
-
 def GetHeapRanges(test_base, shrink=False):
     frame = test_base.thread.GetSelectedFrame()
 
     ex = frame.EvaluateExpression("heap_pointer1")
     test_base.assertTrue(ex.IsValid())
-    range = GetRangeFromAddrValue(test_base, ex, shrink)
-    addr_ranges = lldb.SBAddressRangeList()
-    addr_ranges.Append(range)
+    range1 = GetRangeFromAddrValue(test_base, ex, shrink)
+    range1_start = range1.GetBaseAddress().GetLoadAddress(test_base.target)
+    range1_end = range1_start + range1.GetByteSize()
 
     ex = frame.EvaluateExpression("heap_pointer2")
     test_base.assertTrue(ex.IsValid())
-    size = len(DOUBLE_INSTANCE_PATTERN_HEAP)
-    if not IsWithinRange(ex, size, addr_ranges[0], test_base.target):
-        addr_ranges.Append(GetRangeFromAddrValue(test_base, ex, shrink))
+    range2 = GetRangeFromAddrValue(test_base, ex, shrink)
+    range2_start = range2.GetBaseAddress().GetLoadAddress(test_base.target)
+    range2_end = range2_start + range2.GetByteSize()
+
+    addr_ranges = lldb.SBAddressRangeList()
+
+    if range1_end < range2_start or range2_end < range1_start:
+        # The ranges do not overlap; add them both.
+        addr_ranges.Append(range1)
+        addr_ranges.Append(range2)
+    else:
+        # Merge overlapping ranges.
+        base = min(range1_start, range2_start)
+        end = max(range1_end, range2_end)
+        start = lldb.SBAddress(base, test_base.target)
+        size = end - base
+        addr_ranges.Append(lldb.SBAddressRange(start, size))
 
     return addr_ranges
 

@bulbazord
Copy link
Member

Help me understand, how does Process::FindRangesInMemory return 3 matches when GetHeapRanges gives you 2 overlapping ranges? And how does it still return 2 matches when GetHeapRanges returns 1 large range?

@igorkudrin
Copy link
Collaborator Author

igorkudrin commented Aug 12, 2025

Help me understand, how does Process::FindRangesInMemory return 3 matches when GetHeapRanges gives you 2 overlapping ranges? And how does it still return 2 matches when GetHeapRanges returns 1 large range?

Assume the addresses of heap_pointer1 and heap_pointer2 are 0x1500 and 0x1900 respectively. GetRangeFromAddrValue() returns the ranges [0x1000, 0x1800) and [0x1400, 0x1c00) for them. The second pointer is not within the range returned for the first pointer, so, before this patch, GetHeapRanges() added the second range to the list. And then, FindRangesInMemory() found the search string once in the first range, at 0x1500, and twice in the second range, at 0x1500 and 0x1900. The new version detects the overlap and returns one merged range, which is [0x1000, 0x1c00). As a result, FindRangesInMemory() finds the needle string in this range twice, as expected.

Copy link
Member

@bulbazord bulbazord left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, that makes sense to me. Thanks for the explanation!

@igorkudrin igorkudrin merged commit 36c2a66 into llvm:main Aug 13, 2025
11 checks passed
@igorkudrin igorkudrin deleted the lldb-fix-find-in-memory branch August 13, 2025 21:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants