Skip to content

Commit 5c0b803

Browse files
committed
Use _boundsCheckPrecondition for unsafe buffer pointer index manipulation
1 parent 6bd528d commit 5c0b803

File tree

2 files changed

+22
-33
lines changed

2 files changed

+22
-33
lines changed

stdlib/public/core/UnsafeBufferPointer.swift.gyb

+8-33
Original file line numberDiff line numberDiff line change
@@ -201,28 +201,17 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
201201
// NOTE: this is a manual specialization of index movement for a Strideable
202202
// index that is required for UnsafeBufferPointer performance. The
203203
// optimizer is not capable of creating partial specializations yet.
204-
// NOTE: Range checks are not performed here, because it is done later by
205-
// the subscript function.
206-
// NOTE: Wrapping math because we allow unsafe buffer pointers not to verify
207-
// index preconditions in release builds. Our (optimistic) assumption is
208-
// that the caller is already ensuring that indices are valid, so we can
209-
// elide the usual checks to help the optimizer generate better code.
210-
// However, we still check for overflow in debug mode.
211204
let result = i.addingReportingOverflow(1)
212-
_debugPrecondition(!result.overflow)
205+
_boundsCheckPrecondition(!result.overflow)
213206
return result.partialValue
214207
}
215208

216209
@inlinable // unsafe-performance
217210
public func formIndex(after i: inout Int) {
218211
// NOTE: this is a manual specialization of index movement for a Strideable
219212
// index that is required for UnsafeBufferPointer performance. The
220-
// optimizer is not capable of creating partial specializations yet.
221-
// NOTE: Range checks are not performed here, because it is done later by
222-
// the subscript function.
223-
// See note on wrapping arithmetic in `index(after:)` above.
224213
let result = i.addingReportingOverflow(1)
225-
_debugPrecondition(!result.overflow)
214+
_boundsCheckPrecondition(!result.overflow)
226215
i = result.partialValue
227216
}
228217

@@ -231,11 +220,8 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
231220
// NOTE: this is a manual specialization of index movement for a Strideable
232221
// index that is required for UnsafeBufferPointer performance. The
233222
// optimizer is not capable of creating partial specializations yet.
234-
// NOTE: Range checks are not performed here, because it is done later by
235-
// the subscript function.
236-
// See note on wrapping arithmetic in `index(after:)` above.
237223
let result = i.subtractingReportingOverflow(1)
238-
_debugPrecondition(!result.overflow)
224+
_boundsCheckPrecondition(!result.overflow)
239225
return result.partialValue
240226
}
241227

@@ -244,11 +230,8 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
244230
// NOTE: this is a manual specialization of index movement for a Strideable
245231
// index that is required for UnsafeBufferPointer performance. The
246232
// optimizer is not capable of creating partial specializations yet.
247-
// NOTE: Range checks are not performed here, because it is done later by
248-
// the subscript function.
249-
// See note on wrapping arithmetic in `index(after:)` above.
250233
let result = i.subtractingReportingOverflow(1)
251-
_debugPrecondition(!result.overflow)
234+
_boundsCheckPrecondition(!result.overflow)
252235
i = result.partialValue
253236
}
254237

@@ -257,11 +240,8 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
257240
// NOTE: this is a manual specialization of index movement for a Strideable
258241
// index that is required for UnsafeBufferPointer performance. The
259242
// optimizer is not capable of creating partial specializations yet.
260-
// NOTE: Range checks are not performed here, because it is done later by
261-
// the subscript function.
262-
// See note on wrapping arithmetic in `index(after:)` above.
263243
let result = i.addingReportingOverflow(n)
264-
_debugPrecondition(!result.overflow)
244+
_boundsCheckPrecondition(!result.overflow)
265245
return result.partialValue
266246
}
267247

@@ -270,19 +250,16 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
270250
// NOTE: this is a manual specialization of index movement for a Strideable
271251
// index that is required for UnsafeBufferPointer performance. The
272252
// optimizer is not capable of creating partial specializations yet.
273-
// NOTE: Range checks are not performed here, because it is done later by
274-
// the subscript function.
275-
// See note on wrapping arithmetic in `index(after:)` above.
276253
let maxOffset = limit.subtractingReportingOverflow(i)
277-
_debugPrecondition(!maxOffset.overflow)
254+
_boundsCheckPrecondition(!maxOffset.overflow)
278255
let l = maxOffset.partialValue
279256

280257
if n > 0 ? l >= 0 && l < n : l <= 0 && n < l {
281258
return nil
282259
}
283260

284261
let result = i.addingReportingOverflow(n)
285-
_debugPrecondition(!result.overflow)
262+
_boundsCheckPrecondition(!result.overflow)
286263
return result.partialValue
287264
}
288265

@@ -291,15 +268,13 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
291268
// NOTE: this is a manual specialization of index movement for a Strideable
292269
// index that is required for UnsafeBufferPointer performance. The
293270
// optimizer is not capable of creating partial specializations yet.
294-
// NOTE: Range checks are not performed here, because it is done later by
295-
// the subscript function.
296271
// NOTE: We allow the subtraction to silently overflow in release builds
297272
// to eliminate a superfluous check when `start` and `end` are both valid
298273
// indices. (The operation can only overflow if `start` is negative, which
299274
// implies it's an invalid index.) `Collection` does not specify what
300275
// `distance` should return when given an invalid index pair.
301276
let result = end.subtractingReportingOverflow(start)
302-
_debugPrecondition(!result.overflow)
277+
_boundsCheckPrecondition(!result.overflow)
303278
return result.partialValue
304279
}
305280

test/stdlib/BoundsCheckTraps.swift

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

39+
BoundsCheckTraps.test("UnsafeMutableBufferPointerIndexes")
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+
let i = buffer.index(after: Int.max)
48+
_blackHole(i)
49+
}
50+
_blackHole(array)
51+
}
52+
3953
BoundsCheckTraps.test("UnsafeRawBufferPointer")
4054
.skip(.custom(
4155
{ _isFastAssertConfiguration() || _isReleaseAssertConfiguration() },

0 commit comments

Comments
 (0)