Skip to content

Commit 0592727

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 d89a517 commit 0592727

11 files changed

+53
-25
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/LifetimeManager.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,11 @@ public func _withUnprotectedUnsafeMutablePointer<T, Result>(
9292
_ body: (UnsafeMutablePointer<T>) throws -> Result
9393
) rethrows -> Result
9494
{
95+
#if $BuiltinUnprotectedAddressOf
9596
return try body(UnsafeMutablePointer<T>(Builtin.unprotectedAddressOf(&value)))
97+
#else
98+
return try body(UnsafeMutablePointer<T>(Builtin.addressof(&value)))
99+
#endif
96100
}
97101

98102
/// Invokes the given closure with a pointer to the given argument.
@@ -167,7 +171,11 @@ public func _withUnprotectedUnsafePointer<T, Result>(
167171
_ body: (UnsafePointer<T>) throws -> Result
168172
) rethrows -> Result
169173
{
174+
#if $BuiltinUnprotectedAddressOf
170175
return try body(UnsafePointer<T>(Builtin.unprotectedAddressOf(&value)))
176+
#else
177+
return try body(UnsafePointer<T>(Builtin.addressof(&value)))
178+
#endif
171179
}
172180

173181
extension String {

stdlib/public/core/MutableCollection.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,13 @@ 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+
#if $BuiltinUnprotectedAddressOf
492+
let p1 = Builtin.unprotectedAddressOf(&a)
493+
let p2 = Builtin.unprotectedAddressOf(&b)
494+
#else
491495
let p1 = Builtin.addressof(&a)
492496
let p2 = Builtin.addressof(&b)
497+
#endif
493498
_debugPrecondition(
494499
p1 != p2,
495500
"swapping a location with itself is not supported")

stdlib/public/core/Random.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,12 @@ 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+
#if $BuiltinUnprotectedAddressOf
162+
let ptr = UnsafeMutablePointer<UInt64>(Builtin.unprotectedAddressOf(&random))
163+
#else
164+
let ptr = UnsafeMutablePointer<UInt64>(Builtin.addressof(&random))
165+
#endif
166+
swift_stdlib_random(ptr, MemoryLayout<UInt64>.size)
162167
return random
163168
}
164169
}

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/UnsafeRawBufferPointer.swift.gyb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,11 @@ public func _withUnprotectedUnsafeBytes<T, Result>(
10921092
of value: T,
10931093
_ body: (UnsafeRawBufferPointer) throws -> Result
10941094
) rethrows -> Result {
1095+
#if $BuiltinUnprotectedAddressOf
10951096
let addr = UnsafeRawPointer(Builtin.unprotectedAddressOfBorrow(value))
1097+
#else
1098+
let addr = UnsafeRawPointer(Builtin.addressof(value))
1099+
#endif
10961100
let buffer = UnsafeRawBufferPointer(start: addr, count: MemoryLayout<T>.size)
10971101
return try body(buffer)
10981102
}

stdlib/public/core/VarArgs.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,15 @@ public func _encodeBitsAsWords<T>(_ x: T) -> [Int] {
215215
_internalInvariant(!result.isEmpty)
216216
var tmp = x
217217
// FIXME: use UnsafeMutablePointer.assign(from:) instead of memcpy.
218+
#if $BuiltinUnprotectedAddressOf
219+
_memcpy(dest: UnsafeMutablePointer(result._baseAddressIfContiguous!),
220+
src: UnsafeMutablePointer(Builtin.unprotectedAddressOf(&tmp)),
221+
size: UInt(MemoryLayout<T>.size))
222+
#else
218223
_memcpy(dest: UnsafeMutablePointer(result._baseAddressIfContiguous!),
219224
src: UnsafeMutablePointer(Builtin.addressof(&tmp)),
220225
size: UInt(MemoryLayout<T>.size))
226+
#endif
221227
return result
222228
}
223229

0 commit comments

Comments
 (0)