swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.64k stars 10.38k forks source link

[SR-10079] Iterating over a reversed substring can crash #52481

Open martinr448 opened 5 years ago

martinr448 commented 5 years ago
Previous ID SR-10079
Radar None
Original Reporter @martinr448
Type Bug
Environment Tested with Xcode 10.1 (Swift 4.2) and Xcode 10.2 beta 3 (Swift 5).
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Standard Library | |Labels | Bug, RunTimeCrash | |Assignee | None | |Priority | Medium | md5: 9ba13aeb1c246a44632281938881173b

Issue Description:

Iterating over a ReversedCollection<String.SubSequence> can crash if the substring starts within an extended grapheme cluster:

let string = "abc\r\nxyz"
let idx = string.range(of: "\n")!.lowerBound
let substring = string[idx...]
let rev = substring.reversed()

let revString = String(rev) // Fatal error: Out of bounds: index < startIndex

The same crash happens with any of the following:

let arr = Array(rev)
for c in rev { print(c) }
print(rev.last!)
theblixguy commented 5 years ago

Hmm this seems to crash in `public subscript(i: Index) -> Character {}` in `Substring.swift`. When I print the start and end indices of `rev`, then I get empty indices. Printing random elements works but fails when printing the newline character with the same crash. Reversing `rev` and creating a String works as well.

belkadan commented 5 years ago

range(of:) is implemented in terms of NSString and thus doesn't understand grapheme clusters. :-( cc @milseman