Skip to content

Commit add8eff

Browse files
Revert "[stdlib] prevent preventable buffer overflows when constructing Strings from C strings." (#42266)
1 parent 8b75d49 commit add8eff

File tree

6 files changed

+23
-511
lines changed

6 files changed

+23
-511
lines changed

stdlib/private/StdlibUnittest/StdlibUnittest.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,10 +2182,9 @@ func _getSystemVersionPlistProperty(_ propertyName: String) -> String? {
21822182
func _getSystemVersionPlistProperty(_ propertyName: String) -> String? {
21832183
var count = 0
21842184
sysctlbyname("kern.osproductversion", nil, &count, nil, 0)
2185-
return withUnsafeTemporaryAllocation(of: CChar.self, capacity: count) {
2186-
sysctlbyname("kern.osproductversion", $0.baseAddress, &count, nil, 0)
2187-
return String(cString: $0.baseAddress!)
2188-
}
2185+
var s = [CChar](repeating: 0, count: count)
2186+
sysctlbyname("kern.osproductversion", &s, &count, nil, 0)
2187+
return String(cString: &s)
21892188
}
21902189
#endif
21912190
#endif

stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -373,25 +373,25 @@ internal func reflect(instanceAddress: UInt,
373373
shouldUnwrapClassExistential: Bool = false) {
374374
while let command = readLine(strippingNewline: true) {
375375
switch command {
376-
case RequestInstanceKind:
376+
case String(validatingUTF8: RequestInstanceKind)!:
377377
sendValue(kind.rawValue)
378-
case RequestShouldUnwrapClassExistential:
378+
case String(validatingUTF8: RequestShouldUnwrapClassExistential)!:
379379
sendValue(shouldUnwrapClassExistential)
380-
case RequestInstanceAddress:
380+
case String(validatingUTF8: RequestInstanceAddress)!:
381381
sendValue(instanceAddress)
382-
case RequestReflectionInfos:
382+
case String(validatingUTF8: RequestReflectionInfos)!:
383383
sendReflectionInfos()
384-
case RequestImages:
384+
case String(validatingUTF8: RequestImages)!:
385385
sendImages()
386-
case RequestReadBytes:
386+
case String(validatingUTF8: RequestReadBytes)!:
387387
sendBytes()
388-
case RequestSymbolAddress:
388+
case String(validatingUTF8: RequestSymbolAddress)!:
389389
sendSymbolAddress()
390-
case RequestStringLength:
390+
case String(validatingUTF8: RequestStringLength)!:
391391
sendStringLength()
392-
case RequestPointerSize:
392+
case String(validatingUTF8: RequestPointerSize)!:
393393
sendPointerSize()
394-
case RequestDone:
394+
case String(validatingUTF8: RequestDone)!:
395395
return
396396
default:
397397
fatalError("Unknown request received: '\(Array(command.utf8))'!")

stdlib/public/core/CString.swift

Lines changed: 9 additions & 218 deletions
Original file line numberDiff line numberDiff line change
@@ -42,84 +42,22 @@ extension String {
4242
/// }
4343
/// // Prints "Caf�"
4444
///
45-
/// - Parameter nullTerminatedUTF8: A pointer to a null-terminated UTF-8 code sequence.
46-
public init(cString nullTerminatedUTF8: UnsafePointer<CChar>) {
47-
let len = UTF8._nullCodeUnitOffset(in: nullTerminatedUTF8)
48-
self = String._fromUTF8Repairing(
49-
UnsafeBufferPointer(start: nullTerminatedUTF8._asUInt8, count: len)).0
50-
}
51-
52-
@inlinable
53-
@_alwaysEmitIntoClient
54-
public init(cString nullTerminatedUTF8: [CChar]) {
55-
self = nullTerminatedUTF8.withUnsafeBytes {
56-
String(_checkingCString: $0.assumingMemoryBound(to: UInt8.self))
57-
}
58-
}
59-
60-
@_alwaysEmitIntoClient
61-
private init(_checkingCString bytes: UnsafeBufferPointer<UInt8>) {
62-
guard let length = bytes.firstIndex(of: 0) else {
63-
_preconditionFailure(
64-
"input of String.init(cString:) must be null-terminated"
65-
)
66-
}
45+
/// - Parameter cString: A pointer to a null-terminated UTF-8 code sequence.
46+
public init(cString: UnsafePointer<CChar>) {
47+
let len = UTF8._nullCodeUnitOffset(in: cString)
6748
self = String._fromUTF8Repairing(
68-
UnsafeBufferPointer(
69-
start: bytes.baseAddress._unsafelyUnwrappedUnchecked,
70-
count: length
71-
)
72-
).0
73-
}
74-
75-
@inlinable
76-
@_alwaysEmitIntoClient
77-
@available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)")
78-
public init(cString nullTerminatedUTF8: inout CChar) {
79-
guard nullTerminatedUTF8 == 0 else {
80-
_preconditionFailure(
81-
"input of String.init(cString:) must be null-terminated"
82-
)
83-
}
84-
self = ""
49+
UnsafeBufferPointer(start: cString._asUInt8, count: len)).0
8550
}
8651

8752
/// Creates a new string by copying the null-terminated UTF-8 data referenced
8853
/// by the given pointer.
8954
///
9055
/// This is identical to `init(cString: UnsafePointer<CChar>)` but operates on
9156
/// an unsigned sequence of bytes.
92-
public init(cString nullTerminatedUTF8: UnsafePointer<UInt8>) {
93-
let len = UTF8._nullCodeUnitOffset(in: nullTerminatedUTF8)
57+
public init(cString: UnsafePointer<UInt8>) {
58+
let len = UTF8._nullCodeUnitOffset(in: cString)
9459
self = String._fromUTF8Repairing(
95-
UnsafeBufferPointer(start: nullTerminatedUTF8, count: len)).0
96-
}
97-
98-
@inlinable
99-
@_alwaysEmitIntoClient
100-
public init(cString nullTerminatedUTF8: [UInt8]) {
101-
self = nullTerminatedUTF8.withUnsafeBufferPointer {
102-
String(_checkingCString: $0)
103-
}
104-
}
105-
106-
@inlinable
107-
@_alwaysEmitIntoClient
108-
@available(*, deprecated, message: "Use a copy of the String argument")
109-
public init(cString nullTerminatedUTF8: String) {
110-
self = nullTerminatedUTF8.withCString(String.init(cString:))
111-
}
112-
113-
@inlinable
114-
@_alwaysEmitIntoClient
115-
@available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)")
116-
public init(cString nullTerminatedUTF8: inout UInt8) {
117-
guard nullTerminatedUTF8 == 0 else {
118-
_preconditionFailure(
119-
"input of String.init(cString:) must be null-terminated"
120-
)
121-
}
122-
self = ""
60+
UnsafeBufferPointer(start: cString, count: len)).0
12361
}
12462

12563
/// Creates a new string by copying and validating the null-terminated UTF-8
@@ -157,40 +95,6 @@ extension String {
15795
self = str
15896
}
15997

160-
@inlinable
161-
@_alwaysEmitIntoClient
162-
public init?(validatingUTF8 cString: [CChar]) {
163-
guard let length = cString.firstIndex(of: 0) else {
164-
_preconditionFailure(
165-
"input of String.init(validatingUTF8:) must be null-terminated"
166-
)
167-
}
168-
guard let string = cString.prefix(length).withUnsafeBytes({
169-
String._tryFromUTF8($0.assumingMemoryBound(to: UInt8.self))
170-
}) else { return nil }
171-
172-
self = string
173-
}
174-
175-
@inlinable
176-
@_alwaysEmitIntoClient
177-
@available(*, deprecated, message: "Use a copy of the String argument")
178-
public init?(validatingUTF8 cString: String) {
179-
self = cString.withCString(String.init(cString:))
180-
}
181-
182-
@inlinable
183-
@_alwaysEmitIntoClient
184-
@available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)")
185-
public init?(validatingUTF8 cString: inout CChar) {
186-
guard cString == 0 else {
187-
_preconditionFailure(
188-
"input of String.init(validatingUTF8:) must be null-terminated"
189-
)
190-
}
191-
self = ""
192-
}
193-
19498
/// Creates a new string by copying the null-terminated data referenced by
19599
/// the given pointer using the specified encoding.
196100
///
@@ -262,77 +166,6 @@ extension String {
262166
return String._fromCodeUnits(
263167
codeUnits, encoding: encoding, repair: isRepairing)
264168
}
265-
266-
@_specialize(where Encoding == Unicode.UTF8)
267-
@_specialize(where Encoding == Unicode.UTF16)
268-
@inlinable // Fold away specializations
269-
@_alwaysEmitIntoClient
270-
public static func decodeCString<Encoding: _UnicodeEncoding>(
271-
_ cString: [Encoding.CodeUnit],
272-
as encoding: Encoding.Type,
273-
repairingInvalidCodeUnits isRepairing: Bool = true
274-
) -> (result: String, repairsMade: Bool)? {
275-
guard let length = cString.firstIndex(of: 0) else {
276-
_preconditionFailure(
277-
"input of decodeCString(_:as:repairingInvalidCodeUnits:) must be null-terminated"
278-
)
279-
}
280-
281-
if _fastPath(encoding == Unicode.UTF8.self) {
282-
return cString.prefix(length).withUnsafeBytes {
283-
buf -> (result: String, repairsMade: Bool)? in
284-
let codeUnits = buf.assumingMemoryBound(to: UInt8.self)
285-
if isRepairing {
286-
return String._fromUTF8Repairing(codeUnits)
287-
}
288-
else if let str = String._tryFromUTF8(codeUnits) {
289-
return (str, false)
290-
}
291-
return nil
292-
}
293-
}
294-
295-
return cString.prefix(length).withUnsafeBufferPointer {
296-
buf -> (result: String, repairsMade: Bool)? in
297-
String._fromCodeUnits(buf, encoding: encoding, repair: isRepairing)
298-
}
299-
}
300-
301-
@_specialize(where Encoding == Unicode.UTF8)
302-
@_specialize(where Encoding == Unicode.UTF16)
303-
@inlinable
304-
@_alwaysEmitIntoClient
305-
@available(*, deprecated, message: "Use a copy of the String argument")
306-
public static func decodeCString<Encoding: _UnicodeEncoding>(
307-
_ cString: String,
308-
as encoding: Encoding.Type,
309-
repairingInvalidCodeUnits isRepairing: Bool = true
310-
) -> (result: String, repairsMade: Bool)? {
311-
return cString.withCString(encodedAs: encoding) {
312-
String.decodeCString(
313-
$0, as: encoding, repairingInvalidCodeUnits: isRepairing
314-
)
315-
}
316-
}
317-
318-
@_specialize(where Encoding == Unicode.UTF8)
319-
@_specialize(where Encoding == Unicode.UTF16)
320-
@inlinable
321-
@_alwaysEmitIntoClient
322-
@available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)")
323-
public static func decodeCString<Encoding: _UnicodeEncoding>(
324-
_ cString: inout Encoding.CodeUnit,
325-
as encoding: Encoding.Type,
326-
repairingInvalidCodeUnits isRepairing: Bool = true
327-
) -> (result: String, repairsMade: Bool)? {
328-
guard cString == 0 else {
329-
_preconditionFailure(
330-
"input of decodeCString(_:as:repairingInvalidCodeUnits:) must be null-terminated"
331-
)
332-
}
333-
return ("", false)
334-
}
335-
336169
/// Creates a string from the null-terminated sequence of bytes at the given
337170
/// pointer.
338171
///
@@ -346,52 +179,10 @@ extension String {
346179
@_specialize(where Encoding == Unicode.UTF16)
347180
@inlinable // Fold away specializations
348181
public init<Encoding: Unicode.Encoding>(
349-
decodingCString nullTerminatedCodeUnits: UnsafePointer<Encoding.CodeUnit>,
182+
decodingCString ptr: UnsafePointer<Encoding.CodeUnit>,
350183
as sourceEncoding: Encoding.Type
351184
) {
352-
self = String.decodeCString(nullTerminatedCodeUnits, as: sourceEncoding)!.0
353-
}
354-
355-
@_specialize(where Encoding == Unicode.UTF8)
356-
@_specialize(where Encoding == Unicode.UTF16)
357-
@inlinable // Fold away specializations
358-
@_alwaysEmitIntoClient
359-
public init<Encoding: Unicode.Encoding>(
360-
decodingCString nullTerminatedCodeUnits: [Encoding.CodeUnit],
361-
as sourceEncoding: Encoding.Type
362-
) {
363-
self = String.decodeCString(nullTerminatedCodeUnits, as: sourceEncoding)!.0
364-
}
365-
366-
@_specialize(where Encoding == Unicode.UTF8)
367-
@_specialize(where Encoding == Unicode.UTF16)
368-
@inlinable
369-
@_alwaysEmitIntoClient
370-
@available(*, deprecated, message: "Use a copy of the String argument")
371-
public init<Encoding: _UnicodeEncoding>(
372-
decodingCString nullTerminatedCodeUnits: String,
373-
as sourceEncoding: Encoding.Type
374-
) {
375-
self = nullTerminatedCodeUnits.withCString(encodedAs: sourceEncoding) {
376-
String(decodingCString: $0, as: sourceEncoding.self)
377-
}
378-
}
379-
380-
@_specialize(where Encoding == Unicode.UTF8)
381-
@_specialize(where Encoding == Unicode.UTF16)
382-
@inlinable // Fold away specializations
383-
@_alwaysEmitIntoClient
384-
@available(*, deprecated, message: "Use String(_ scalar: Unicode.Scalar)")
385-
public init<Encoding: Unicode.Encoding>(
386-
decodingCString nullTerminatedCodeUnits: inout Encoding.CodeUnit,
387-
as sourceEncoding: Encoding.Type
388-
) {
389-
guard nullTerminatedCodeUnits == 0 else {
390-
_preconditionFailure(
391-
"input of String.init(decodingCString:as:) must be null-terminated"
392-
)
393-
}
394-
self = ""
185+
self = String.decodeCString(ptr, as: sourceEncoding)!.0
395186
}
396187
}
397188

test/Prototypes/PatternMatching.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,7 @@ extension Collection where Iterator.Element == UTF8.CodeUnit {
302302
a.reserveCapacity(count + 1)
303303
a.append(contentsOf: self)
304304
a.append(0)
305-
return a.withUnsafeBufferPointer {
306-
String(reflecting: String(cString: $0.baseAddress!))
307-
}
305+
return String(reflecting: String(cString: a))
308306
}
309307
}
310308

0 commit comments

Comments
 (0)