Skip to content

Commit 4678496

Browse files
authored
Merge pull request #41613 from lorentey/string-encoding-views-index-validation
[test] stdlib/StringTraps: Add some coverage for foreign traps in UTF-8/16 views
2 parents 58826ed + 33bb68c commit 4678496

File tree

1 file changed

+94
-1
lines changed

1 file changed

+94
-1
lines changed

test/stdlib/StringTraps.swift

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
// UNSUPPORTED: OS=wasi
1111

1212
import StdlibUnittest
13+
#if _runtime(_ObjC)
14+
import Foundation // For NSString
15+
#endif
1316

1417
let testSuiteSuffix = _isDebugAssertConfiguration() ? "_debug" : "_release"
1518

@@ -131,7 +134,7 @@ StringTraps.test("UTF16ViewSubscript/endIndex")
131134
{ _isFastAssertConfiguration() },
132135
reason: "this trap is not guaranteed to happen in -Ounchecked"))
133136
.code {
134-
var s = "abc"
137+
let s = "abc"
135138
var i = s.utf16.startIndex
136139
i = s.utf16.index(after: i)
137140
i = s.utf16.index(after: i)
@@ -260,5 +263,95 @@ StringTraps.test("UnicodeScalarView index(after:) trap on i > endIndex")
260263
i = s.unicodeScalars.index(after: i)
261264
}
262265

266+
StringTraps.test("UnicodeScalarView index(before:) trap on i > endIndex")
267+
.skip(
268+
.custom({ _isFastAssertConfiguration() },
269+
reason: "trap is not guaranteed to happen in -Ounchecked"))
270+
.code {
271+
guard #available(SwiftStdlib 5.7, *) else { return }
272+
273+
let long = "abcd"
274+
var i = long.unicodeScalars.endIndex
275+
276+
let s = "abc"
277+
expectCrashLater()
278+
i = s.unicodeScalars.index(before: i)
279+
}
280+
281+
#if _runtime(_ObjC)
282+
StringTraps.test("UTF8View foreign index(after:) trap on i > endIndex")
283+
.skip(
284+
.custom({ _isFastAssertConfiguration() },
285+
reason: "trap is not guaranteed to happen in -Ounchecked"))
286+
.code {
287+
guard #available(SwiftStdlib 5.7, *) else { return }
288+
289+
let long = "🐘 This is a quite large string, with lots of data"
290+
let short = ("🐭 I'm much smaller" as NSString) as String
291+
292+
var i = long.utf8.endIndex
293+
expectCrashLater()
294+
// Note: we expect that `short` will be UTF-16 encoded here -- this trap only
295+
// happens on the foreign path. For native/shared strings, the UTF-8 view's
296+
// `index(after:)` is essentially doing a simple `i + 1`, like Array does.
297+
i = short.utf8.index(after: i)
298+
}
299+
#endif
300+
301+
#if _runtime(_ObjC)
302+
StringTraps.test("UTF8View foreign index(before:) trap on i > endIndex")
303+
.skip(
304+
.custom({ _isFastAssertConfiguration() },
305+
reason: "trap is not guaranteed to happen in -Ounchecked"))
306+
.code {
307+
guard #available(SwiftStdlib 5.7, *) else { return }
308+
309+
let long = "🐘 This is a quite large string, with lots of data"
310+
let short = ("🐭 I'm much smaller" as NSString) as String
311+
312+
var i = long.utf8.endIndex
313+
expectCrashLater()
314+
// Note: we expect that `short` will be UTF-16 encoded here -- this trap only
315+
// happens on the foreign path. For native/shared strings, the UTF-8 view's
316+
// `index(before:)` is essentially doing a simple `i - 1`, like Array does.
317+
// (Following the unconditional i != startIndex check.)
318+
i = short.utf8.index(before: i)
319+
}
320+
#endif
321+
322+
#if _runtime(_ObjC)
323+
StringTraps.test("UTF8View foreign index(after:) trap on i == endIndex")
324+
.skip(
325+
.custom({ _isFastAssertConfiguration() },
326+
reason: "trap is not guaranteed to happen in -Ounchecked"))
327+
.code {
328+
guard #available(SwiftStdlib 5.7, *) else { return }
329+
330+
let s = ("🦧 The Librarian" as NSString) as String
331+
332+
var i = s.utf8.endIndex
333+
expectCrashLater()
334+
// Note: we expect that `short` will be UTF-16 encoded here -- this trap only
335+
// happens on the foreign path. For native/shared strings, the UTF-8 view's
336+
// `index(after:)` is essentially doing a simple `i + 1`, like Array does.
337+
i = s.utf8.index(after: i)
338+
}
339+
#endif
340+
341+
#if _runtime(_ObjC)
342+
StringTraps.test("UTF8View foreign index(before:) trap on i == startIndex")
343+
.skip(
344+
.custom({ _isFastAssertConfiguration() },
345+
reason: "trap is not guaranteed to happen in -Ounchecked"))
346+
.code {
347+
guard #available(SwiftStdlib 5.7, *) else { return }
348+
349+
let s = ("🦧 The Librarian" as NSString) as String
350+
var i = s.utf8.startIndex
351+
expectCrashLater()
352+
i = s.utf8.index(before: i)
353+
}
354+
#endif
355+
263356
runAllTests()
264357

0 commit comments

Comments
 (0)