NSString.getBytes does not crash even when an invalid range is passed.

When we pass some special words, NSString.getBytes does not crash even when we pass an invalid range.

It seems a bug.

The below code is an example.

func testNSStringGetBytes() {
    let originalString: String = "􁜁あ"

    let bufferSize = 256
    var buffer = [UInt8](repeating: 0, count: bufferSize)
    var usedLength = 0
    // An invalid range is passed
    let range = NSRange(location: 0, length: originalString.count + 1)
    var remainingRange = NSRange()

    (originalString as NSString)
        .getBytes(
            &buffer,
            maxLength: bufferSize,
            usedLength: &usedLength,
            encoding: String.Encoding.utf8.rawValue,
            options: [],
            range: range,
            remaining: &remainingRange
        )

    print("Used Length: \(usedLength)")
    print("Buffer: \(buffer[0..<usedLength])")

    if remainingRange.length > 0 {
        print("Did not convert the whole string. Remaining range: \(remainingRange)")
    } else {
        print("Entire string was converted successfully.")
    }
}

Consider this:

let originalString: String = "􁜁あ"
print(originalString.count)
print(originalString.utf16.count)

It prints:

2
3

When working with NSString ranges, you have to working UTF-16 code points, but the Swift count returns the Swift character count (where a character is an extended grapheme cluster. That means that this code isn’t doing what you think it’s doing:

let range = NSRange(location: 0, length: originalString.count + 1)

If you want to build an NSRange for a Swift string, you need to use NSRange.init(_:in:). For example this:

let range = NSRange(originalString.startIndex..<originalString.endIndex, in: originalString)

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

NSString.getBytes does not crash even when an invalid range is passed.
 
 
Q