Skip to content

Commit 1a65a4e

Browse files
committed
Switch UnsafeRawBufferPointer over to _boundsCheckPrecondition
1 parent 174a5a7 commit 1a65a4e

File tree

2 files changed

+51
-35
lines changed

2 files changed

+51
-35
lines changed

stdlib/public/core/UnsafeRawBufferPointer.swift.gyb

+35-35
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ public struct Unsafe${Mutable}RawBufferPointer {
112112
public init(
113113
@_nonEphemeral start: Unsafe${Mutable}RawPointer?, count: Int
114114
) {
115-
_debugPrecondition(count >= 0, "${Self} with negative count")
116-
_debugPrecondition(count == 0 || start != nil,
115+
_boundsCheckPrecondition(count >= 0, "${Self} with negative count")
116+
_boundsCheckPrecondition(count == 0 || start != nil,
117117
"${Self} has a nil start and nonzero count")
118118
_position = start
119119
_end = start.map { $0 + _assumeNonNegative(count) }
@@ -159,7 +159,7 @@ extension UnsafeRawBufferPointer.Iterator: IteratorProtocol, Sequence {
159159
//
160160
// We check these invariants in debug builds to defend against invalidly constructed
161161
// pointers.
162-
_debugPrecondition(_position! < _end!)
162+
_boundsCheckPrecondition(_position! < _end!)
163163
let position = _position._unsafelyUnwrappedUnchecked
164164
let result = position.load(as: UInt8.self)
165165
_position = position + 1
@@ -239,14 +239,14 @@ extension Unsafe${Mutable}RawBufferPointer: ${Mutable}Collection {
239239
@inlinable
240240
public subscript(i: Int) -> Element {
241241
get {
242-
_debugPrecondition(i >= 0)
243-
_debugPrecondition(i < endIndex)
242+
_boundsCheckPrecondition(i >= 0)
243+
_boundsCheckPrecondition(i < endIndex)
244244
return _position._unsafelyUnwrappedUnchecked.load(fromByteOffset: i, as: UInt8.self)
245245
}
246246
% if mutable:
247247
nonmutating set {
248-
_debugPrecondition(i >= 0)
249-
_debugPrecondition(i < endIndex)
248+
_boundsCheckPrecondition(i >= 0)
249+
_boundsCheckPrecondition(i < endIndex)
250250
_position._unsafelyUnwrappedUnchecked.storeBytes(of: newValue, toByteOffset: i, as: UInt8.self)
251251
}
252252
% end # mutable
@@ -259,15 +259,15 @@ extension Unsafe${Mutable}RawBufferPointer: ${Mutable}Collection {
259259
@inlinable
260260
public subscript(bounds: Range<Int>) -> SubSequence {
261261
get {
262-
_debugPrecondition(bounds.lowerBound >= startIndex)
263-
_debugPrecondition(bounds.upperBound <= endIndex)
262+
_boundsCheckPrecondition(bounds.lowerBound >= startIndex)
263+
_boundsCheckPrecondition(bounds.upperBound <= endIndex)
264264
return Slice(base: self, bounds: bounds)
265265
}
266266
% if mutable:
267267
nonmutating set {
268-
_debugPrecondition(bounds.lowerBound >= startIndex)
269-
_debugPrecondition(bounds.upperBound <= endIndex)
270-
_debugPrecondition(bounds.count == newValue.count)
268+
_boundsCheckPrecondition(bounds.lowerBound >= startIndex)
269+
_boundsCheckPrecondition(bounds.upperBound <= endIndex)
270+
_boundsCheckPrecondition(bounds.count == newValue.count)
271271

272272
if !newValue.isEmpty {
273273
(baseAddress! + bounds.lowerBound).copyMemory(
@@ -292,8 +292,8 @@ extension Unsafe${Mutable}RawBufferPointer: ${Mutable}Collection {
292292
@inlinable
293293
public func swapAt(_ i: Int, _ j: Int) {
294294
guard i != j else { return }
295-
_debugPrecondition(i >= 0 && j >= 0)
296-
_debugPrecondition(i < endIndex && j < endIndex)
295+
_boundsCheckPrecondition(i >= 0 && j >= 0)
296+
_boundsCheckPrecondition(i < endIndex && j < endIndex)
297297
let pi = (_position! + i)
298298
let pj = (_position! + j)
299299
let tmp = pi.load(fromByteOffset: 0, as: UInt8.self)
@@ -394,8 +394,8 @@ extension Unsafe${Mutable}RawBufferPointer {
394394
/// memory.
395395
@inlinable
396396
public func load<T>(fromByteOffset offset: Int = 0, as type: T.Type) -> T {
397-
_debugPrecondition(offset >= 0, "${Self}.load with negative offset")
398-
_debugPrecondition(offset + MemoryLayout<T>.size <= self.count,
397+
_boundsCheckPrecondition(offset >= 0, "${Self}.load with negative offset")
398+
_boundsCheckPrecondition(offset + MemoryLayout<T>.size <= self.count,
399399
"${Self}.load out of bounds")
400400
return baseAddress!.load(fromByteOffset: offset, as: T.self)
401401
}
@@ -436,8 +436,8 @@ extension Unsafe${Mutable}RawBufferPointer {
436436
fromByteOffset offset: Int = 0,
437437
as type: T.Type
438438
) -> T {
439-
_debugPrecondition(offset >= 0, "${Self}.load with negative offset")
440-
_debugPrecondition(offset + MemoryLayout<T>.size <= self.count,
439+
_boundsCheckPrecondition(offset >= 0, "${Self}.load with negative offset")
440+
_boundsCheckPrecondition(offset + MemoryLayout<T>.size <= self.count,
441441
"${Self}.load out of bounds")
442442
return baseAddress!.loadUnaligned(fromByteOffset: offset, as: T.self)
443443
}
@@ -447,8 +447,8 @@ extension Unsafe${Mutable}RawBufferPointer {
447447
fromByteOffset offset: Int = 0,
448448
as type: T.Type
449449
) -> T {
450-
_debugPrecondition(offset >= 0, "${Self}.load with negative offset")
451-
_debugPrecondition(offset + MemoryLayout<T>.size <= self.count,
450+
_boundsCheckPrecondition(offset >= 0, "${Self}.load with negative offset")
451+
_boundsCheckPrecondition(offset + MemoryLayout<T>.size <= self.count,
452452
"${Self}.load out of bounds")
453453
return baseAddress!.loadUnaligned(fromByteOffset: offset, as: T.self)
454454
}
@@ -495,8 +495,8 @@ extension Unsafe${Mutable}RawBufferPointer {
495495
public func storeBytes<T>(
496496
of value: T, toByteOffset offset: Int = 0, as type: T.Type
497497
) {
498-
_debugPrecondition(offset >= 0, "${Self}.storeBytes with negative offset")
499-
_debugPrecondition(offset + MemoryLayout<T>.size <= self.count,
498+
_boundsCheckPrecondition(offset >= 0, "${Self}.storeBytes with negative offset")
499+
_boundsCheckPrecondition(offset + MemoryLayout<T>.size <= self.count,
500500
"${Self}.storeBytes out of bounds")
501501

502502
let pointer = baseAddress._unsafelyUnwrappedUnchecked
@@ -511,8 +511,8 @@ extension Unsafe${Mutable}RawBufferPointer {
511511
@usableFromInline func _legacy_se0349_storeBytes<T>(
512512
of value: T, toByteOffset offset: Int = 0, as type: T.Type
513513
) {
514-
_debugPrecondition(offset >= 0, "${Self}.storeBytes with negative offset")
515-
_debugPrecondition(offset + MemoryLayout<T>.size <= self.count,
514+
_boundsCheckPrecondition(offset >= 0, "${Self}.storeBytes with negative offset")
515+
_boundsCheckPrecondition(offset + MemoryLayout<T>.size <= self.count,
516516
"${Self}.storeBytes out of bounds")
517517

518518
baseAddress!._legacy_se0349_storeBytes_internal(
@@ -538,7 +538,7 @@ extension Unsafe${Mutable}RawBufferPointer {
538538
/// be less than or equal to this buffer's `count`.
539539
@inlinable
540540
public func copyMemory(from source: UnsafeRawBufferPointer) {
541-
_debugPrecondition(source.count <= self.count,
541+
_boundsCheckPrecondition(source.count <= self.count,
542542
"${Self}.copyMemory source has too many elements")
543543
if let baseAddress = baseAddress, let sourceAddress = source.baseAddress {
544544
baseAddress.copyMemory(from: sourceAddress, byteCount: source.count)
@@ -568,7 +568,7 @@ extension Unsafe${Mutable}RawBufferPointer {
568568

569569
if source.withContiguousStorageIfAvailable({
570570
(buffer: UnsafeBufferPointer<UInt8>) -> Void in
571-
_debugPrecondition(source.count <= self.count,
571+
_boundsCheckPrecondition(source.count <= self.count,
572572
"${Self}.copyBytes source has too many elements")
573573
if let base = buffer.baseAddress {
574574
position.copyMemory(from: base, byteCount: buffer.count)
@@ -578,7 +578,7 @@ extension Unsafe${Mutable}RawBufferPointer {
578578
}
579579

580580
for (index, byteValue) in source.enumerated() {
581-
_debugPrecondition(index < self.count,
581+
_boundsCheckPrecondition(index < self.count,
582582
"${Self}.copyBytes source has too many elements")
583583
position.storeBytes(
584584
of: byteValue, toByteOffset: index, as: UInt8.self)
@@ -666,7 +666,7 @@ extension Unsafe${Mutable}RawBufferPointer {
666666
// We only do this in debug builds to prevent a measurable performance
667667
// degradation wrt passing around pointers not wrapped in a BufferPointer
668668
// construct.
669-
_debugPrecondition(
669+
_boundsCheckPrecondition(
670670
slice.startIndex >= 0 && slice.endIndex <= slice.base.count,
671671
"Invalid slice")
672672
let base = slice.base.baseAddress?.advanced(by: slice.startIndex)
@@ -783,7 +783,7 @@ extension Unsafe${Mutable}RawBufferPointer {
783783
let elementStride = MemoryLayout<S.Element>.stride
784784

785785
// This has to be a debug precondition due to the cost of walking over some collections.
786-
_debugPrecondition(source.underestimatedCount <= (count / elementStride),
786+
_boundsCheckPrecondition(source.underestimatedCount <= (count / elementStride),
787787
"insufficient space to accommodate source.underestimatedCount elements")
788788
guard let base = baseAddress else {
789789
// this can be a precondition since only an invalid argument should be costly
@@ -792,7 +792,7 @@ extension Unsafe${Mutable}RawBufferPointer {
792792
return (it, UnsafeMutableBufferPointer(start: nil, count: 0))
793793
}
794794

795-
_debugPrecondition(
795+
_boundsCheckPrecondition(
796796
Int(bitPattern: base) & (MemoryLayout<S.Element>.alignment-1) == 0,
797797
"buffer base address must be properly aligned to access S.Element"
798798
)
@@ -852,7 +852,7 @@ extension Unsafe${Mutable}RawBufferPointer {
852852
guard let sourceAddress = $0.baseAddress, !$0.isEmpty else {
853853
return .init(start: nil, count: 0)
854854
}
855-
_debugPrecondition(
855+
_boundsCheckPrecondition(
856856
Int(bitPattern: baseAddress) & (MemoryLayout<C.Element>.alignment-1) == 0,
857857
"buffer base address must be properly aligned to access C.Element"
858858
)
@@ -877,7 +877,7 @@ extension Unsafe${Mutable}RawBufferPointer {
877877
return .init(start: nil, count: 0)
878878
}
879879
_internalInvariant(_end != nil)
880-
_debugPrecondition(
880+
_boundsCheckPrecondition(
881881
Int(bitPattern: baseAddress) & (MemoryLayout<C.Element>.alignment-1) == 0,
882882
"buffer base address must be properly aligned to access C.Element"
883883
)
@@ -939,7 +939,7 @@ extension Unsafe${Mutable}RawBufferPointer {
939939
guard let sourceAddress = source.baseAddress, !source.isEmpty else {
940940
return .init(start: nil, count: 0)
941941
}
942-
_debugPrecondition(
942+
_boundsCheckPrecondition(
943943
Int(bitPattern: baseAddress) & (MemoryLayout<T>.alignment-1) == 0,
944944
"buffer base address must be properly aligned to access T"
945945
)
@@ -1081,7 +1081,7 @@ extension Unsafe${Mutable}RawBufferPointer {
10811081
guard let s = _position else {
10821082
return try body(.init(start: nil, count: 0))
10831083
}
1084-
_debugPrecondition(
1084+
_boundsCheckPrecondition(
10851085
Int(bitPattern: s) & (MemoryLayout<T>.alignment-1) == 0,
10861086
"baseAddress must be a properly aligned pointer for type T"
10871087
)
@@ -1134,7 +1134,7 @@ extension Unsafe${Mutable}RawBufferPointer {
11341134
try withMemoryRebound(to: Element.self) { b in
11351135
var buffer = b
11361136
defer {
1137-
_debugPrecondition(
1137+
_boundsCheckPrecondition(
11381138
(b.baseAddress, b.count) == (buffer.baseAddress, buffer.count),
11391139
"UnsafeMutableRawBufferPointer.withContiguousMutableStorageIfAvailable: replacing the buffer is not allowed"
11401140
)

test/stdlib/BoundsCheckTraps.swift

+16
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,20 @@ BoundsCheckTraps.test("UnsafeMutableBufferPointer")
3636
_blackHole(array)
3737
}
3838

39+
BoundsCheckTraps.test("UnsafeRawBufferPointer")
40+
.skip(.custom(
41+
{ _isFastAssertConfiguration() || _isReleaseAssertConfiguration() },
42+
reason: "this trap is not guaranteed to happen"))
43+
.code {
44+
expectCrashLater()
45+
var array = [1, 2, 3]
46+
array.withUnsafeBufferPointer { buffer in
47+
print(UnsafeRawBufferPointer(buffer).load(fromByteOffset: MemoryLayout<Int>.stride * 3, as: Int.self))
48+
}
49+
array.withUnsafeMutableBufferPointer { buffer in
50+
UnsafeMutableRawBufferPointer(buffer).storeBytes(of: 17, toByteOffset: MemoryLayout<Int>.stride * 3, as: Int.self)
51+
}
52+
_blackHole(array)
53+
}
54+
3955
runAllTests()

0 commit comments

Comments
 (0)