[stdlib] Fix issue with UTF16 index(_:offsetBy:limitedBy) (#12469)
diff --git a/stdlib/public/core/StringUTF16.swift b/stdlib/public/core/StringUTF16.swift
index b848fe1..6db190d 100644
--- a/stdlib/public/core/StringUTF16.swift
+++ b/stdlib/public/core/StringUTF16.swift
@@ -167,7 +167,7 @@
) -> Index? {
// FIXME: swift-3-indexing-model: range check i?
let d = i.encodedOffset.distance(to: limit.encodedOffset)
- if (d > 0) ? (d < n) : (d > n) {
+ if (d >= 0) ? (d < n) : (d > n) {
return nil
}
return Index(encodedOffset: i.encodedOffset.advanced(by: n))
diff --git a/test/Interpreter/SDK/Foundation_test.swift b/test/Interpreter/SDK/Foundation_test.swift
index fbcb182..50dfc96 100644
--- a/test/Interpreter/SDK/Foundation_test.swift
+++ b/test/Interpreter/SDK/Foundation_test.swift
@@ -177,6 +177,14 @@
let nsrFrom = NSRange(b..., in: s)
expectEqual(nsrFrom.location,5)
expectEqual(nsrFrom.length, 5)
+
+ expectNil(Range(NSRange(location: 100, length: 0), in: s))
+ expectNil(Range(NSRange(location: 0, length: 100), in: s))
+
+ let empty = ""
+ expectNil(Range(NSRange(location: 1, length: 0), in: empty))
+ expectNil(Range(NSRange(location: 0, length: 1), in: empty))
+ expectNotNil(Range(NSRange(location: 0, length: 0), in: empty))
// FIXME: enable once indices conform to RangeExpression
// let nsrFull = NSRange(s.indices, in: s)
diff --git a/test/stdlib/StringTraps.swift b/test/stdlib/StringTraps.swift
index 8a0e74c..3f22129 100644
--- a/test/stdlib/StringTraps.swift
+++ b/test/stdlib/StringTraps.swift
@@ -18,7 +18,7 @@
{ _isFastAssertConfiguration() },
reason: "this trap is not guaranteed to happen in -Ounchecked"))
.code {
- var s = "abc"
+ let s = "abc"
var i = s.startIndex
i = s.index(after: i)
i = s.index(before: i)
@@ -31,7 +31,7 @@
{ _isFastAssertConfiguration() },
reason: "this trap is not guaranteed to happen in -Ounchecked"))
.code {
- var s = "abc"
+ let s = "abc"
var i = s.startIndex
i = s.index(after: i)
i = s.index(after: i)
@@ -45,13 +45,13 @@
{ _isFastAssertConfiguration() },
reason: "this trap is not guaranteed to happen in -Ounchecked"))
.code {
- var s = "abc"
+ let s = "abc"
var i = s.startIndex
i = s.index(after: i)
i = s.index(after: i)
i = s.index(after: i)
expectCrashLater()
- s[i]
+ _ = s[i]
}
StringTraps.test("UTF8ViewEndIndexSuccessor")
@@ -59,7 +59,7 @@
{ _isFastAssertConfiguration() },
reason: "this trap is not guaranteed to happen in -Ounchecked"))
.code {
- var s = "abc"
+ let s = "abc"
var i = s.utf8.startIndex
i = s.utf8.index(after: i)
i = s.utf8.index(after: i)
@@ -73,13 +73,13 @@
{ _isFastAssertConfiguration() },
reason: "this trap is not guaranteed to happen in -Ounchecked"))
.code {
- var s = "abc"
+ let s = "abc"
var i = s.utf8.startIndex
i = s.utf8.index(after: i)
i = s.utf8.index(after: i)
i = s.utf8.index(after: i)
expectCrashLater()
- s.utf8[i]
+ _ = s.utf8[i]
}
StringTraps.test("UTF16ViewSubscript/DecrementedStartIndex")
@@ -87,11 +87,11 @@
{ _isFastAssertConfiguration() },
reason: "this trap is not guaranteed to happen in -Ounchecked"))
.code {
- var s = "abc"
+ let s = "abc"
var i = s.utf16.startIndex
expectCrashLater()
i = s.utf16.index(before: i)
- s.utf16[i]
+ _ = s.utf16[i]
}
StringTraps.test("UTF16ViewSubscript/endIndex")
@@ -105,7 +105,36 @@
i = s.utf16.index(after: i)
i = s.utf16.index(after: i)
expectCrashLater()
- s.utf16[i]
+ _ = s.utf16[i]
+}
+
+StringTraps.test("UTF16ViewIndex/offsetLimited")
+ .code {
+ let sa = "foo"
+ let u16a = sa.utf16
+ let s16 = sa + "🤦🏻♀️"
+ let u16 = s16.utf16
+
+ let iaBegin = u16a.index(sa.startIndex, offsetBy: 99, limitedBy: sa.endIndex)
+ expectNil(iaBegin)
+ let iaEnd = u16a.index(sa.endIndex, offsetBy: 99, limitedBy: sa.endIndex)
+ expectNil(iaEnd)
+ let i16Begin = u16.index(u16.startIndex, offsetBy: 99, limitedBy: u16.endIndex)
+ expectNil(i16Begin)
+ let i16End = u16.index(u16.startIndex, offsetBy: 99, limitedBy: u16.endIndex)
+ expectNil(i16End)
+}
+
+StringTraps.test("UTF16ViewIndex/offsetCrash")
+ .skip(.custom(
+ { _isFastAssertConfiguration() },
+ reason: "this trap is not guaranteed to happen in -Ounchecked"))
+ .code {
+ let s16 = "foo🤦🏻♀️"
+ let u16 = s16.utf16
+ expectCrashLater()
+ let i = u16.index(u16.startIndex, offsetBy: 99)
+ _ = s16.utf16[i]
}
runAllTests()