Skip to content

Commit 7b09e1b

Browse files
authored
Merge pull request #2218 from swiftlang/automerge/merge-main-2026-08-30_09-07
2 parents 56a1256 + ca9abd9 commit 7b09e1b

7 files changed

Lines changed: 44 additions & 10 deletions

File tree

Sources/FoundationEssentials/Data/Data.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -768,9 +768,6 @@ public struct Data : RandomAccessCollection, MutableCollection, RangeReplaceable
768768
/// - parameter range: The range in the data to set to `0`.
769769
@inlinable // This is @inlinable as trivially forwarding.
770770
public mutating func resetBytes(in range: Range<Index>) {
771-
// it is worth noting that the range here may be out of bounds of the Data itself (which triggers a growth)
772-
precondition(range.lowerBound >= 0, "Ranges must not be negative bounds")
773-
precondition(range.upperBound >= 0, "Ranges must not be negative bounds")
774771
_representation.resetBytes(in: range)
775772
}
776773

Sources/FoundationEssentials/Data/Representations/Data+Inline.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ extension Data {
257257
mutating func resetBytes(in range: Range<Index>) {
258258
assert(range.lowerBound <= MemoryLayout<Buffer>.size)
259259
assert(range.upperBound <= MemoryLayout<Buffer>.size)
260-
precondition(range.lowerBound <= length, "index \(range.lowerBound) is out of bounds of 0..<\(length)")
260+
precondition(range.lowerBound >= 0 && range.lowerBound <= length, "index \(range.lowerBound) is out of bounds of 0..<\(length)")
261261
if length < range.upperBound {
262262
length = UInt8(range.upperBound)
263263
}

Sources/FoundationEssentials/Data/Representations/Data+InlineSlice.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ extension Data {
261261
mutating func resetBytes(in range: Range<Index>) {
262262
assert(range.lowerBound < HalfInt.max)
263263
assert(range.upperBound < HalfInt.max)
264-
precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
264+
precondition(range.lowerBound >= startIndex && range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
265265
ensureUniqueReference()
266266
storage.resetBytes(in: range)
267267
if slice.upperBound < range.upperBound {

Sources/FoundationEssentials/Data/Representations/Data+LargeSlice.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ extension Data {
244244

245245
@inlinable // This is @inlinable as reasonably small.
246246
mutating func resetBytes(in range: Range<Int>) {
247-
precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
247+
precondition(range.lowerBound >= startIndex && range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
248248
ensureUniqueReference()
249249
storage.resetBytes(in: range)
250250
if slice.range.upperBound < range.upperBound {

Sources/FoundationEssentials/Data/Representations/Data+LegacyRepresentation.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -517,16 +517,14 @@ extension Data {
517517
mutating func resetBytes(in range: Range<Index>) {
518518
switch self {
519519
case .empty:
520+
precondition(range.lowerBound == 0, "index \(range.lowerBound) is out of bounds of 0..<0)")
520521
if range.upperBound == 0 {
521522
self = .empty
522523
} else if InlineData.canStore(count: range.upperBound) {
523-
precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
524524
self = .inline(InlineData(count: range.upperBound))
525525
} else if InlineSlice.canStore(count: range.upperBound) {
526-
precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
527526
self = .slice(InlineSlice(count: range.upperBound))
528527
} else {
529-
precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
530528
self = .large(LargeSlice(count: range.upperBound))
531529
}
532530
case .inline(var inline):

Sources/FoundationEssentials/Data/Representations/Data+Representation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ extension Data {
187187

188188
@export(implementation)
189189
mutating func resetBytes(in range: Range<Index>) {
190-
precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
190+
precondition(range.lowerBound >= startIndex && range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
191191
ensureUniqueReference()
192192
_storage.resetBytes(in: range)
193193
if _slice.upperBound < range.upperBound {

Tests/FoundationEssentialsTests/DataTests.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2329,10 +2329,35 @@ private final class DataTests {
23292329
}
23302330

23312331
@Test func bounding_failure_reset_range() async {
2332+
await #expect(processExitsWith: .failure) {
2333+
var data = Data()
2334+
data.resetBytes(in: -1..<0)
2335+
}
2336+
2337+
await #expect(processExitsWith: .failure) {
2338+
var data = Data()
2339+
data.resetBytes(in: 2..<3)
2340+
}
2341+
2342+
await #expect(processExitsWith: .failure) {
2343+
var data = try #require("Hello World".data(using: .utf8))
2344+
data.resetBytes(in: -1..<2)
2345+
}
2346+
23322347
await #expect(processExitsWith: .failure) {
23332348
var data = try #require("Hello World".data(using: .utf8))
23342349
data.resetBytes(in: 100..<200)
23352350
}
2351+
2352+
await #expect(processExitsWith: .failure) {
2353+
var data = Data(count: 128)
2354+
data.resetBytes(in: -1..<2)
2355+
}
2356+
2357+
await #expect(processExitsWith: .failure) {
2358+
var data = Data(count: 128)
2359+
data.resetBytes(in: 200..<201)
2360+
}
23362361
}
23372362

23382363
@Test func bounding_failure_append_bad_length() async {
@@ -3846,6 +3871,20 @@ struct LargeDataTests {
38463871
#expect(large[1] == 0xBB)
38473872
#expect(large[2] == 0xCC)
38483873
}
3874+
3875+
#if FOUNDATION_EXIT_TESTS
3876+
@Test func resetBytesBounds() async {
3877+
await #expect(processExitsWith: .failure) {
3878+
var data = Data(count: largeCount)
3879+
data.resetBytes(in: -1..<2)
3880+
}
3881+
3882+
await #expect(processExitsWith: .failure) {
3883+
var data = Data(count: largeCount)
3884+
data.resetBytes(in: (data.endIndex + 1) ..< (data.endIndex + 2))
3885+
}
3886+
}
3887+
#endif
38493888
}
38503889

38513890
private func expectLargeIfLegacyABI(_ data: Data, sourceLocation: SourceLocation = #_sourceLocation) {

0 commit comments

Comments
 (0)