Skip to content

Commit d52cd82

Browse files
committed
[stdlib] Add a missing debug mode check to U*BP.init(rebasing:)
`Slice` does not technically guarantee that its indices are valid in its base, so these initializers accidentally allowed the creation of obviously out-of-bounds buffers.
1 parent c5c27c7 commit d52cd82

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

stdlib/public/core/UnsafeBufferPointer.swift.gyb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,17 @@ extension Unsafe${Mutable}BufferPointer {
498498
/// - Parameter slice: The buffer slice to rebase.
499499
@inlinable // unsafe-performance
500500
public init(rebasing slice: Slice<UnsafeBufferPointer<Element>>) {
501+
// NOTE: `Slice` does not guarantee that its start/end indices are valid
502+
// in `base` -- it merely ensures that `startIndex <= endIndex`.
503+
// We need manually check that we aren't given an invalid slice,
504+
// or the resulting collection would allow access that was
505+
// out-of-bounds with respect to the original base buffer.
506+
// We only do this in debug builds to prevent a measurable performance
507+
// degradation wrt passing around pointers not wrapped in a BufferPointer
508+
// construct.
509+
_debugPrecondition(
510+
slice.startIndex >= 0 && slice.endIndex <= slice.base.count,
511+
"Invalid slice")
501512
let base = slice.base.baseAddress?.advanced(by: slice.startIndex)
502513
let count = slice.endIndex &- slice.startIndex
503514
self.init(start: base, count: count)

stdlib/public/core/UnsafeRawBufferPointer.swift.gyb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,17 @@ extension Unsafe${Mutable}RawBufferPointer {
511511
/// - Parameter slice: The raw buffer slice to rebase.
512512
@inlinable
513513
public init(rebasing slice: Slice<UnsafeRawBufferPointer>) {
514+
// NOTE: `Slice` does not guarantee that its start/end indices are valid
515+
// in `base` -- it merely ensures that `startIndex <= endIndex`.
516+
// We need manually check that we aren't given an invalid slice,
517+
// or the resulting collection would allow access that was
518+
// out-of-bounds with respect to the original base buffer.
519+
// We only do this in debug builds to prevent a measurable performance
520+
// degradation wrt passing around pointers not wrapped in a BufferPointer
521+
// construct.
522+
_debugPrecondition(
523+
slice.startIndex >= 0 && slice.endIndex <= slice.base.count,
524+
"Invalid slice")
514525
let base = slice.base.baseAddress?.advanced(by: slice.startIndex)
515526
let count = slice.endIndex &- slice.startIndex
516527
self.init(start: base, count: count)

0 commit comments

Comments
 (0)