Skip to content

Commit e1cc31c

Browse files
committed
stdlib: opt out of stack protection in places where there can't be buffer overflows.
We trust the internal implementation of the stdlib to not cause any unintentional buffer overflows. In such cases we can use the "unprotected" address-to-pointer conversions. This avoids inserting stack protections where it's not needed.
1 parent b8abc5a commit e1cc31c

File tree

9 files changed

+29
-28
lines changed

9 files changed

+29
-28
lines changed

stdlib/public/core/AnyHashable.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,10 @@ public struct AnyHashable {
159159
}
160160

161161
self.init(_box: _ConcreteHashableBox(false)) // Dummy value
162+
let ptr = UnsafeMutablePointer<AnyHashable>(Builtin.unprotectedAddressOf(&self))
162163
_makeAnyHashableUpcastingToHashableBaseType(
163164
base,
164-
storingResultInto: &self)
165+
storingResultInto: ptr)
165166
}
166167

167168
internal init<H: Hashable>(_usingDefaultRepresentationOf base: H) {

stdlib/public/core/FloatingPointParsing.swift.gyb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ extension ${Self}: LosslessStringConvertible {
169169
self.init(Substring(text))
170170
} else {
171171
self = 0.0
172-
let success = withUnsafeMutablePointer(to: &self) { p -> Bool in
172+
let success = _withUnprotectedUnsafeMutablePointer(to: &self) { p -> Bool in
173173
text.withCString { chars -> Bool in
174174
switch chars[0] {
175175
case 9, 10, 11, 12, 13, 32:
@@ -198,7 +198,7 @@ extension ${Self}: LosslessStringConvertible {
198198
@available(SwiftStdlib 5.3, *)
199199
public init?(_ text: Substring) {
200200
self = 0.0
201-
let success = withUnsafeMutablePointer(to: &self) { p -> Bool in
201+
let success = _withUnprotectedUnsafeMutablePointer(to: &self) { p -> Bool in
202202
text.withCString { chars -> Bool in
203203
switch chars[0] {
204204
case 9, 10, 11, 12, 13, 32:

stdlib/public/core/KeyPath.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,7 +1951,8 @@ func _modifyAtWritableKeyPath_impl<Root, Value>(
19511951
keyPath: _unsafeUncheckedDowncast(keyPath,
19521952
to: ReferenceWritableKeyPath<Root, Value>.self))
19531953
}
1954-
return keyPath._projectMutableAddress(from: &root)
1954+
let ptr = UnsafePointer<Root>(Builtin.unprotectedAddressOf(&root))
1955+
return keyPath._projectMutableAddress(from: ptr)
19551956
}
19561957

19571958
// The release that ends the access scope is guaranteed to happen
@@ -1980,7 +1981,8 @@ func _setAtWritableKeyPath<Root, Value>(
19801981
value: value)
19811982
}
19821983
// TODO: we should be able to do this more efficiently than projecting.
1983-
let (addr, owner) = keyPath._projectMutableAddress(from: &root)
1984+
let ptr = UnsafePointer<Root>(Builtin.unprotectedAddressOf(&root))
1985+
let (addr, owner) = keyPath._projectMutableAddress(from: ptr)
19841986
addr.pointee = value
19851987
_fixLifetime(owner)
19861988
// FIXME: this needs a deallocation barrier to ensure that the
@@ -3277,7 +3279,7 @@ internal struct InstantiateKeyPathBuffer: KeyPathPatternVisitor {
32773279
_internalInvariant(_isPOD(T.self))
32783280
let size = MemoryLayout<T>.size
32793281
let (baseAddress, misalign) = adjustDestForAlignment(of: T.self)
3280-
withUnsafeBytes(of: value) {
3282+
_withUnprotectedUnsafeBytes(of: value) {
32813283
_memcpy(dest: baseAddress, src: $0.baseAddress.unsafelyUnwrapped,
32823284
size: UInt(size))
32833285
}

stdlib/public/core/MutableCollection.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,8 @@ extension MutableCollection {
488488
public func swap<T>(_ a: inout T, _ b: inout T) {
489489
// Semantically equivalent to (a, b) = (b, a).
490490
// Microoptimized to avoid retain/release traffic.
491-
let p1 = Builtin.addressof(&a)
492-
let p2 = Builtin.addressof(&b)
491+
let p1 = Builtin.unprotectedAddressOf(&a)
492+
let p2 = Builtin.unprotectedAddressOf(&b)
493493
_debugPrecondition(
494494
p1 != p2,
495495
"swapping a location with itself is not supported")

stdlib/public/core/Random.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ public struct SystemRandomNumberGenerator: RandomNumberGenerator, Sendable {
158158
@inlinable
159159
public mutating func next() -> UInt64 {
160160
var random: UInt64 = 0
161-
swift_stdlib_random(&random, MemoryLayout<UInt64>.size)
161+
let ptr = UnsafeMutablePointer<UInt64>(Builtin.unprotectedAddressOf(&random))
162+
swift_stdlib_random(ptr, MemoryLayout<UInt64>.size)
162163
return random
163164
}
164165
}

stdlib/public/core/SmallString.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ extension _SmallString {
221221
) rethrows -> Result {
222222
let count = self.count
223223
var raw = self.zeroTerminatedRawCodeUnits
224-
return try Swift.withUnsafeBytes(of: &raw) {
224+
return try Swift._withUnprotectedUnsafeBytes(of: &raw) {
225225
let rawPtr = $0.baseAddress._unsafelyUnwrappedUnchecked
226226
// Rebind the underlying (UInt64, UInt64) tuple to UInt8 for the
227227
// duration of the closure. Accessing self after this rebind is undefined.

stdlib/public/core/StringSwitch.swift

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,20 @@ func _findStringSwitchCaseWithCache(
6868
string: String,
6969
cache: inout _OpaqueStringSwitchCache) -> Int {
7070

71-
return withUnsafeMutableBytes(of: &cache) {
72-
(bufPtr: UnsafeMutableRawBufferPointer) -> Int in
73-
74-
let oncePtr = bufPtr.baseAddress!
75-
let cacheRawPtr = oncePtr + MemoryLayout<Builtin.Word>.stride
76-
let cachePtr = cacheRawPtr.bindMemory(to: _StringSwitchCache.self, capacity: 1)
77-
var context = _StringSwitchContext(cases: cases, cachePtr: cachePtr)
78-
withUnsafeMutablePointer(to: &context) { (context) -> () in
79-
Builtin.onceWithContext(oncePtr._rawValue, _createStringTableCache,
80-
context._rawValue)
81-
}
82-
let cache = cachePtr.pointee;
83-
if let idx = cache[string] {
84-
return idx
85-
}
86-
return -1
71+
let ptr = UnsafeMutableRawPointer(Builtin.unprotectedAddressOf(&cache))
72+
let oncePtr = ptr
73+
let cacheRawPtr = oncePtr + MemoryLayout<Builtin.Word>.stride
74+
let cachePtr = cacheRawPtr.bindMemory(to: _StringSwitchCache.self, capacity: 1)
75+
var context = _StringSwitchContext(cases: cases, cachePtr: cachePtr)
76+
withUnsafeMutablePointer(to: &context) { (context) -> () in
77+
Builtin.onceWithContext(oncePtr._rawValue, _createStringTableCache,
78+
context._rawValue)
79+
}
80+
let cache = cachePtr.pointee;
81+
if let idx = cache[string] {
82+
return idx
8783
}
84+
return -1
8885
}
8986

9087
/// Builds the string switch case.

stdlib/public/core/UnicodeScalar.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ extension Unicode.Scalar {
524524

525525
// The first code unit is in the least significant byte of codeUnits.
526526
codeUnits = codeUnits.littleEndian
527-
return try Swift.withUnsafePointer(to: &codeUnits) {
527+
return try Swift._withUnprotectedUnsafePointer(to: &codeUnits) {
528528
return try $0.withMemoryRebound(to: UInt8.self, capacity: 4) {
529529
return try body(UnsafeBufferPointer(start: $0, count: utf8Count))
530530
}

stdlib/public/core/VarArgs.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ public func _encodeBitsAsWords<T>(_ x: T) -> [Int] {
216216
var tmp = x
217217
// FIXME: use UnsafeMutablePointer.assign(from:) instead of memcpy.
218218
_memcpy(dest: UnsafeMutablePointer(result._baseAddressIfContiguous!),
219-
src: UnsafeMutablePointer(Builtin.addressof(&tmp)),
219+
src: UnsafeMutablePointer(Builtin.unprotectedAddressOf(&tmp)),
220220
size: UInt(MemoryLayout<T>.size))
221221
return result
222222
}

0 commit comments

Comments
 (0)