Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
2026-06-28 Todd White <todd.white@thalion.global>
* Source/CFBinaryHeap.c (CFBinaryHeapCreateCopy): Enlarge the copy's
capacity to at least the source count before copying the values.
(CFBinaryHeapRemoveMinimumValue): Do nothing on an empty heap
instead of reading _values[-1] and setting _count to -1.
* Tests/CFBinaryHeap/general.m: Regression tests.

2021-09-30 Frederik Seiffert <frederik@algoriddim.com>
* Source/CFDate.c: Fix logic in CFGregorianDateIsValid()

Expand Down
9 changes: 8 additions & 1 deletion Source/CFBinaryHeap.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,11 @@ CFBinaryHeapCreateCopy (CFAllocatorRef alloc, CFIndex capacity,
CFBinaryHeapRef heap)
{
CFBinaryHeapRef ret;


/* The copy must be able to hold every value regardless of the requested
capacity. */
if (capacity < heap->_count)
capacity = heap->_count;
ret = CFBinaryHeapCreate (alloc, capacity, heap->_callBacks,
&heap->_context);
memcpy (ret->_values, heap->_values, sizeof(void*) * heap->_count);
Expand Down Expand Up @@ -369,6 +373,9 @@ CFBinaryHeapRemoveMinimumValue (CFBinaryHeapRef heap)
const void *last;
void *info;

if (heap->_count == 0)
return;

release = heap->_callBacks->release;
if (release)
release (CFGetAllocator(heap), heap->_values[0]);
Expand Down
29 changes: 28 additions & 1 deletion Tests/CFBinaryHeap/general.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,33 @@ int main (void)
PASS_CF(n == 5, "Minimum value in binary heap is %d.", (int)n);

CFRelease (heap);


/* A copy with a requested capacity smaller than the count must still
hold every value (no write past the buffer). */
{
CFBinaryHeapRef big = CFBinaryHeapCreate (NULL, 0, NULL, NULL);
CFBinaryHeapRef copy;
CFIndex i;

for (i = 0; i < 20; i++)
CFBinaryHeapAddValue (big, (const void *)(i + 1));
copy = CFBinaryHeapCreateCopy (NULL, 0, big);
PASS_CF(CFBinaryHeapGetCount (copy) == 20
&& (CFIndex)CFBinaryHeapGetMinimum (copy) == 1,
"A copy with capacity 0 holds all 20 values.");
CFRelease (copy);
CFRelease (big);
}

/* Removing from an empty heap must be a no-op, not read out of bounds. */
{
CFBinaryHeapRef empty = CFBinaryHeapCreate (NULL, 0, NULL, NULL);

CFBinaryHeapRemoveMinimumValue (empty);
PASS_CF(CFBinaryHeapGetCount (empty) == 0,
"Removing from an empty heap leaves it empty.");
CFRelease (empty);
}

return 0;
}
Loading