authorgravatar for erik.arvstedt@gmail.comErik Arvstedt <erik.arvstedt@gmail.com> 2024-01-19 00:25:43+01:00
committergravatar for erik.arvstedt@gmail.comErik Arvstedt <erik.arvstedt@gmail.com> 2024-01-19 00:55:17+01:00
log0bb6967d1464d95e50ef620ea5b3ebd9f9c0bc97
tree9e12c6195d5224a53537962408bffecc310d9b81
parent14efbbfd89c7e034436faa87a201a35324b9dff3

std.ArrayList: remove `+ 1` overflow checks


1 files changed, 32 insertions(+), 34 deletions(-)

lib/std/array_list.zig+32-34
......@@ -126,7 +126,8 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
126126
127127 /// The caller owns the returned memory. Empties this ArrayList.
128128 pub fn toOwnedSliceSentinel(self: *Self, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) {
129 try self.ensureTotalCapacityPrecise(try addOrOom(self.items.len, 1));
129 // This addition can never overflow because `self.items` can never occupy the whole address space
130 try self.ensureTotalCapacityPrecise(self.items.len + 1);
130131 self.appendAssumeCapacity(sentinel);
131132 const result = try self.toOwnedSlice();
132133 return result[0 .. result.len - 1 :sentinel];
......@@ -493,7 +494,9 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
493494 /// Increase length by 1, returning pointer to the new item.
494495 /// The returned pointer becomes invalid when the list resized.
495496 pub fn addOne(self: *Self) Allocator.Error!*T {
496 try self.ensureUnusedCapacity(1);
497 // This can never overflow because `self.items` can never occupy the whole address space
498 const newlen = self.items.len + 1;
499 try self.ensureTotalCapacity(newlen);
497500 return self.addOneAssumeCapacity();
498501 }
499502
......@@ -710,7 +713,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
710713
711714 /// The caller owns the returned memory. ArrayList becomes empty.
712715 pub fn toOwnedSliceSentinel(self: *Self, allocator: Allocator, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) {
713 try self.ensureTotalCapacityPrecise(allocator, try addOrOom(self.items.len, 1));
716 // This addition can never overflow because `self.items` can never occupy the whole address space
717 try self.ensureTotalCapacityPrecise(allocator, self.items.len + 1);
714718 self.appendAssumeCapacity(sentinel);
715719 const result = try self.toOwnedSlice(allocator);
716720 return result[0 .. result.len - 1 :sentinel];
......@@ -1071,7 +1075,8 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
10711075 /// Increase length by 1, returning pointer to the new item.
10721076 /// The returned element pointer becomes invalid when the list is resized.
10731077 pub fn addOne(self: *Self, allocator: Allocator) Allocator.Error!*T {
1074 const newlen = try addOrOom(self.items.len, 1);
1078 // This can never overflow because `self.items` can never occupy the whole address space
1079 const newlen = self.items.len + 1;
10751080 try self.ensureTotalCapacity(allocator, newlen);
10761081 return self.addOneAssumeCapacity();
10771082 }
......@@ -1991,47 +1996,40 @@ test "std.ArrayList(u32).getLastOrNull()" {
19911996test "return OutOfMemory when capacity would exceed maximum usize integer value" {
19921997 const a = testing.allocator;
19931998 const new_item: u32 = 42;
1999 const items = &.{ 42, 43 };
19942000
19952001 {
19962002 var list: ArrayListUnmanaged(u32) = .{
19972003 .items = undefined,
1998 .capacity = math.maxInt(usize),
2004 .capacity = math.maxInt(usize) - 1,
19992005 };
2000 list.items.len = math.maxInt(usize);
2001
2002 try testing.expectError(error.OutOfMemory, list.append(a, new_item));
2003 try testing.expectError(error.OutOfMemory, list.appendSlice(a, &.{new_item}));
2004 try testing.expectError(error.OutOfMemory, list.appendNTimes(a, new_item, 1));
2005 try testing.expectError(error.OutOfMemory, list.appendUnalignedSlice(a, &.{new_item}));
2006 try testing.expectError(error.OutOfMemory, list.addOne(a));
2007 try testing.expectError(error.OutOfMemory, list.addManyAt(a, 0, 1));
2008 try testing.expectError(error.OutOfMemory, list.addManyAsArray(a, 1));
2009 try testing.expectError(error.OutOfMemory, list.addManyAsSlice(a, 1));
2010 try testing.expectError(error.OutOfMemory, list.insert(a, 0, new_item));
2011 try testing.expectError(error.OutOfMemory, list.insertSlice(a, 0, &.{new_item}));
2012 try testing.expectError(error.OutOfMemory, list.toOwnedSliceSentinel(a, 0));
2013 try testing.expectError(error.OutOfMemory, list.ensureUnusedCapacity(a, 1));
2006 list.items.len = math.maxInt(usize) - 1;
2007
2008 try testing.expectError(error.OutOfMemory, list.appendSlice(a, items));
2009 try testing.expectError(error.OutOfMemory, list.appendNTimes(a, new_item, 2));
2010 try testing.expectError(error.OutOfMemory, list.appendUnalignedSlice(a, &.{ new_item, new_item }));
2011 try testing.expectError(error.OutOfMemory, list.addManyAt(a, 0, 2));
2012 try testing.expectError(error.OutOfMemory, list.addManyAsArray(a, 2));
2013 try testing.expectError(error.OutOfMemory, list.addManyAsSlice(a, 2));
2014 try testing.expectError(error.OutOfMemory, list.insertSlice(a, 0, items));
2015 try testing.expectError(error.OutOfMemory, list.ensureUnusedCapacity(a, 2));
20142016 }
20152017
20162018 {
20172019 var list: ArrayList(u32) = .{
20182020 .items = undefined,
2019 .capacity = math.maxInt(usize),
2021 .capacity = math.maxInt(usize) - 1,
20202022 .allocator = a,
20212023 };
2022 list.items.len = math.maxInt(usize);
2023
2024 try testing.expectError(error.OutOfMemory, list.append(new_item));
2025 try testing.expectError(error.OutOfMemory, list.appendSlice(&.{new_item}));
2026 try testing.expectError(error.OutOfMemory, list.appendNTimes(new_item, 1));
2027 try testing.expectError(error.OutOfMemory, list.appendUnalignedSlice(&.{new_item}));
2028 try testing.expectError(error.OutOfMemory, list.addOne());
2029 try testing.expectError(error.OutOfMemory, list.addManyAt(0, 1));
2030 try testing.expectError(error.OutOfMemory, list.addManyAsArray(1));
2031 try testing.expectError(error.OutOfMemory, list.addManyAsSlice(1));
2032 try testing.expectError(error.OutOfMemory, list.insert(0, new_item));
2033 try testing.expectError(error.OutOfMemory, list.insertSlice(0, &.{new_item}));
2034 try testing.expectError(error.OutOfMemory, list.toOwnedSliceSentinel(0));
2035 try testing.expectError(error.OutOfMemory, list.ensureUnusedCapacity(1));
2024 list.items.len = math.maxInt(usize) - 1;
2025
2026 try testing.expectError(error.OutOfMemory, list.appendSlice(items));
2027 try testing.expectError(error.OutOfMemory, list.appendNTimes(new_item, 2));
2028 try testing.expectError(error.OutOfMemory, list.appendUnalignedSlice(&.{ new_item, new_item }));
2029 try testing.expectError(error.OutOfMemory, list.addManyAt(0, 2));
2030 try testing.expectError(error.OutOfMemory, list.addManyAsArray(2));
2031 try testing.expectError(error.OutOfMemory, list.addManyAsSlice(2));
2032 try testing.expectError(error.OutOfMemory, list.insertSlice(0, items));
2033 try testing.expectError(error.OutOfMemory, list.ensureUnusedCapacity(2));
20362034 }
20372035}