Skip to content

Conversation

@jmschonfeld
Copy link
Contributor

_NSCFString.getBytes does not currently read/respect the provided max buffer length when writing bytes out to the provided buffer. When an insufficiently sized buffer is provided, a buffer overflow occurs. This appeared as a symptom in plutil where reading a plist with a long unicode string would cause a buffer overflow since the UTF16 count was small enough for plutil to use a stack buffer instead of a dynamically-sized heap buffer, but the UTF8 count was long enough that writing the bytes overflows the stack buffer. This PR resolves the issue by breaking during byte iteration when we reach the max buffer length.

@jmschonfeld
Copy link
Contributor Author

@swift-ci test

@jmschonfeld
Copy link
Contributor Author

This caused a new test failure:

[2025-11-11T20:35:39.977Z] Test Suite 'TestMeasurement' started at 2025-11-11 20:35:39.877
[2025-11-11T20:35:39.977Z] Test Case 'TestMeasurement.testCodingRoundtrip' started at 2025-11-11 20:35:39.877
[2025-11-11T20:35:39.977Z] TestFoundation/Utilities.swift:247: error: TestMeasurement.testCodingRoundtrip : XCTAssertTrue failed - The fixture with identifier 'NSMeasurement-Angle' failed to match after an in-memory roundtrip.
[2025-11-11T20:35:39.977Z] Test Case 'TestMeasurement.testCodingRoundtrip' failed (0.003 seconds)

This failure doesn't occur on the base release/6.2 branch so it appears to be due to this change and needs further investigation. I suspect it's related to round tripping the symbol property of the angle measurement which likely uses a non-ASCII string

@jmschonfeld
Copy link
Contributor Author

@swift-ci please test

if let buffer = buffer {
for (idx, character) in encodingView.enumerated() {
if idx >= maxBufLen { break }
if encoding == CFStringEncoding(kCFStringEncodingASCII) && !Unicode.ASCII.isASCII(character) { break }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line fixes the unit test failure. The issue was that this fix exposes the bug mentioned above on line 154:

// TODO: Don't treat many encodings like they are UTF8

Currently if the requested encoding is UTF8/ISOLatin1/MacRoman/ASCII/non-lossy ASCII we just encode UTF-8. Previously, we incorrectly reported the convertedLength as the UTF-8 length, but this fix updated that to correctly report the UTF-16 length processed. In plist encoding, when encoding a string the CoreFoundation code attempts getting ASCII bytes and if that fails it gets UTF-16 bytes encoded instead. Previously, it believed that the ASCII conversion failed because the reported UTF-8 length mismatched the known UTF-16 length. Now that the return value is correctly reporting the converted length, it began "passing" and thinking that it could encode the non-ASCII string as ASCII instead of falling over to UTF-16.

As a stopgap, this fixes the ASCII encoding by failing if we hit a non-ASCII character. We also need to do this same behavior (as the comment suggests) for the other non-UTF8 encodings here (and/or actually encode them properly 🙂). That's a larger change that I'm proposing we do as a followup since this is effectively already broken for the other encodings and I don't think it makes it worse (just perhaps more discoverable) and the other encodings are likely far less common than ASCII.

@jmschonfeld
Copy link
Contributor Author

@swift-ci please test

@jmschonfeld
Copy link
Contributor Author

@swift-ci please test Windows platform

1 similar comment
@jmschonfeld
Copy link
Contributor Author

@swift-ci please test Windows platform

Copy link
Contributor

@Catfish-Man Catfish-Man left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for catching this

@jmschonfeld jmschonfeld merged commit f3a7a34 into swiftlang:release/6.2 Dec 11, 2025
2 checks passed
@jmschonfeld jmschonfeld deleted the string-bytes-overflow branch December 11, 2025 18:37
jmschonfeld added a commit to jmschonfeld/swift-corelibs-foundation that referenced this pull request Dec 11, 2025
* Fix buffer overflow in _NSCFString.getBytes

* Fix unit test failure

* Fix test_dateParseAndFormatWithJapaneseCalendar
jmschonfeld added a commit that referenced this pull request Dec 12, 2025
* Fix buffer overflow in _NSCFString.getBytes

* Fix unit test failure

* Fix test_dateParseAndFormatWithJapaneseCalendar
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Segmentation fault when Linux plutil tries to convert a single non-ascii string of sufficiently long size to binary plist.

3 participants