Skip to content

Commit 9bda1e5

Browse files
authored
Merge pull request swiftlang#13340 from glessard/umbp-failearlyrangecheck
2 parents 74ba135 + 68e50d3 commit 9bda1e5

File tree

2 files changed

+91
-2
lines changed

2 files changed

+91
-2
lines changed

stdlib/public/core/UnsafeBufferPointer.swift.gyb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,16 @@ extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessColle
197197

198198
@_inlineable
199199
public func _failEarlyRangeCheck(_ index: Int, bounds: Range<Int>) {
200-
// NOTE: This method is a no-op for performance reasons.
200+
// NOTE: In release mode, this method is a no-op for performance reasons.
201+
_debugPrecondition(index >= bounds.lowerBound)
202+
_debugPrecondition(index < bounds.upperBound)
201203
}
202204

203205
@_inlineable
204206
public func _failEarlyRangeCheck(_ range: Range<Int>, bounds: Range<Int>) {
205-
// NOTE: This method is a no-op for performance reasons.
207+
// NOTE: In release mode, this method is a no-op for performance reasons.
208+
_debugPrecondition(range.lowerBound >= bounds.lowerBound)
209+
_debugPrecondition(range.upperBound <= bounds.upperBound)
206210
}
207211

208212
@_inlineable

validation-test/stdlib/UnsafeBufferPointer.swift.gyb

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,91 @@ UnsafeMutableBufferPointerTestSuite.test("changeElementViaBuffer") {
325325
expectEqual(-1.0, allocated[count-1])
326326
}
327327

328+
let bufCount = 4
329+
let sliceRange: Range = 1..<bufCount-1
330+
% for mutable in [True, False]:
331+
% for raw in [True, False]:
332+
% for action in ['read', 'change']:
333+
% if action != 'change' or mutable:
334+
for testIndex in (0..<bufCount) {
335+
% Type = 'Unsafe' + ('Mutable' if mutable else '') + ('Raw' if raw else '') + 'BufferPointer'
336+
${Type}TestSuite.test("${action}Element\(testIndex)ViaSlice") {
337+
% if raw:
338+
let allocated = UnsafeMutableRawPointer.allocate(bytes: bufCount, alignedTo: 8)
339+
for i in 0..<bufCount {
340+
allocated.storeBytes(of: UInt8(i), toByteOffset: i, as: UInt8.self)
341+
}
342+
% else:
343+
let allocated = UnsafeMutablePointer<Int>.allocate(capacity: bufCount)
344+
for i in 0..<bufCount { allocated[i] = i }
345+
% end # if mutable
346+
defer { allocated.deallocate() }
347+
348+
let buffer = ${Type}(start: allocated, count: bufCount)
349+
${'var' if mutable else 'let'} slice = buffer[sliceRange]
350+
351+
if _isDebugAssertConfiguration(),
352+
testIndex < sliceRange.lowerBound ||
353+
testIndex >= sliceRange.upperBound {
354+
expectCrashLater()
355+
}
356+
% if action == 'read':
357+
let value = slice[testIndex]
358+
expectEqual(buffer[testIndex], value)
359+
% else:
360+
slice[testIndex] = 103
361+
expectEqual(buffer[testIndex], 103)
362+
% end # if action
363+
}
364+
}
365+
% end # if action or mutable
366+
% end # for action
367+
% end # for raw
368+
% end # for mutable
369+
370+
let testRanges = (0..<bufCount-1).map({ i -> Range<Int> in i..<i+2 })
371+
% for mutable in [True, False]:
372+
% for raw in [True, False]:
373+
% for action in ['read', 'change']:
374+
% if action != 'change' or mutable:
375+
for testRange in testRanges {
376+
% Type = 'Unsafe' + ('Mutable' if mutable else '') + ('Raw' if raw else '') + 'BufferPointer'
377+
${Type}TestSuite.test("${action}Slice\(testRange)ViaSlice") {
378+
% if raw:
379+
let allocated = UnsafeMutableRawPointer.allocate(bytes: bufCount+2, alignedTo: 8)
380+
for i in 0..<bufCount+2 {
381+
allocated.storeBytes(of: UInt8(i), toByteOffset: i, as: UInt8.self)
382+
}
383+
% else:
384+
let allocated = UnsafeMutablePointer<Int>.allocate(capacity: bufCount+2)
385+
for i in 0..<bufCount+2 { allocated[i] = i }
386+
% end # if mutable
387+
defer { allocated.deallocate() }
388+
389+
let buffer = ${Type}(start: allocated, count: bufCount+2)
390+
${'var' if mutable else 'let'} slice = buffer[sliceRange]
391+
392+
if _isDebugAssertConfiguration(),
393+
testRange.lowerBound < sliceRange.lowerBound ||
394+
testRange.upperBound > sliceRange.upperBound {
395+
expectCrashLater()
396+
}
397+
398+
% if action == 'read':
399+
let value = slice[testRange]
400+
expectEqualSequence(buffer[testRange], value)
401+
% else:
402+
let sourceSlice = buffer[bufCount..<bufCount+2]
403+
slice[testRange] = sourceSlice
404+
expectEqualSequence(buffer[testRange], sourceSlice)
405+
% end # if action
406+
}
407+
}
408+
% end # if action or mutable
409+
% end # for action
410+
% end # for raw
411+
% end # for mutable
412+
328413
protocol SubscriptTest {
329414
static var start: Int { get }
330415
static var end: Int { get }

0 commit comments

Comments
 (0)