authorgravatar for Frechdachs@users.noreply.github.comFrechdachs <Frechdachs@users.noreply.github.com> 2022-12-13 20:55:41+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-09 15:04:28-07:00
logf8ea292d0989ac8245399a8dad6f27c8b28cd696
tree2f5bb0e1304a645e820e7552af445c83b17ebab0
parentb5222f86eec68088b9bd83ad2f648654242082ec

std: Fix update() method in PriorityQueue and PriorityDequeue (#13908)

Previously the update() method would iterate over its capacity, which may contain uninitialized memory or already removed elements.

2 files changed, 26 insertions(+), 4 deletions(-)

lib/std/priority_dequeue.zig+13-2
...@@ -390,8 +390,10 @@ pub fn PriorityDequeue(comptime T: type, comptime Context: type, comptime compar...@@ -390,8 +390,10 @@ pub fn PriorityDequeue(comptime T: type, comptime Context: type, comptime compar
390390
391 pub fn update(self: *Self, elem: T, new_elem: T) !void {391 pub fn update(self: *Self, elem: T, new_elem: T) !void {
392 const old_index = blk: {392 const old_index = blk: {
393 for (self.items) |item, idx| {393 var idx: usize = 0;
394 if (compareFn(self.context, item, elem).compare(.eq)) break :blk idx;394 while (idx < self.len) : (idx += 1) {
395 const item = self.items[idx];
396 if (compareFn(self.context, item, elem) == .eq) break :blk idx;
395 }397 }
396 return error.ElementNotFound;398 return error.ElementNotFound;
397 };399 };
...@@ -778,6 +780,15 @@ test "std.PriorityDequeue: update same max queue" {...@@ -778,6 +780,15 @@ test "std.PriorityDequeue: update same max queue" {
778 try expectEqual(@as(u32, 1), queue.removeMax());780 try expectEqual(@as(u32, 1), queue.removeMax());
779}781}
780782
783test "std.PriorityDequeue: update after remove" {
784 var queue = PDQ.init(testing.allocator, {});
785 defer queue.deinit();
786
787 try queue.add(1);
788 try expectEqual(@as(u32, 1), queue.removeMin());
789 try expectError(error.ElementNotFound, queue.update(1, 1));
790}
791
781test "std.PriorityDequeue: iterator" {792test "std.PriorityDequeue: iterator" {
782 var queue = PDQ.init(testing.allocator, {});793 var queue = PDQ.init(testing.allocator, {});
783 var map = std.AutoHashMap(u32, void).init(testing.allocator);794 var map = std.AutoHashMap(u32, void).init(testing.allocator);
lib/std/priority_queue.zig+13-2
...@@ -218,8 +218,10 @@ pub fn PriorityQueue(comptime T: type, comptime Context: type, comptime compareF...@@ -218,8 +218,10 @@ pub fn PriorityQueue(comptime T: type, comptime Context: type, comptime compareF
218218
219 pub fn update(self: *Self, elem: T, new_elem: T) !void {219 pub fn update(self: *Self, elem: T, new_elem: T) !void {
220 const update_index = blk: {220 const update_index = blk: {
221 for (self.items) |item, idx| {221 var idx: usize = 0;
222 if (compareFn(self.context, item, elem).compare(.eq)) break :blk idx;222 while (idx < self.len) : (idx += 1) {
223 const item = self.items[idx];
224 if (compareFn(self.context, item, elem) == .eq) break :blk idx;
223 }225 }
224 return error.ElementNotFound;226 return error.ElementNotFound;
225 };227 };
...@@ -591,6 +593,15 @@ test "std.PriorityQueue: update same max heap" {...@@ -591,6 +593,15 @@ test "std.PriorityQueue: update same max heap" {
591 try expectEqual(@as(u32, 1), queue.remove());593 try expectEqual(@as(u32, 1), queue.remove());
592}594}
593595
596test "std.PriorityQueue: update after remove" {
597 var queue = PQlt.init(testing.allocator, {});
598 defer queue.deinit();
599
600 try queue.add(1);
601 try expectEqual(@as(u32, 1), queue.remove());
602 try expectError(error.ElementNotFound, queue.update(1, 1));
603}
604
594test "std.PriorityQueue: siftUp in remove" {605test "std.PriorityQueue: siftUp in remove" {
595 var queue = PQlt.init(testing.allocator, {});606 var queue = PQlt.init(testing.allocator, {});
596 defer queue.deinit();607 defer queue.deinit();