Skip to content

Commit 6472997

Browse files
committed
[cxx-interop] Handle std::strings with \0 character
Previously the conversion mechanism called `std::string::c_str` and passed it to `String(cString:)` which accepts a null-terminated string. If the string contains a `\0` character, this failed to initialize the entire string properly.
1 parent 6c518bd commit 6472997

File tree

2 files changed

+11
-1
lines changed

2 files changed

+11
-1
lines changed

stdlib/public/Cxx/std/String.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@ extension std.string: ExpressibleByStringLiteral {
2727

2828
extension String {
2929
public init(cxxString: std.string) {
30-
self.init(cString: cxxString.__c_strUnsafe())
30+
let buffer = UnsafeBufferPointer<CChar>(
31+
start: cxxString.__c_strUnsafe(),
32+
count: cxxString.size())
33+
self = buffer.withMemoryRebound(to: UInt8.self) {
34+
String(decoding: $0, as: UTF8.self)
35+
}
3136
withExtendedLifetime(cxxString) {}
3237
}
3338
}

test/Interop/Cxx/stdlib/overlay/std-string-overlay.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ StdStringOverlayTestSuite.test("std::string <=> Swift.String") {
3030
expectEqual(cxx5.size(), 10)
3131
let swift5 = String(cxxString: cxx5)
3232
expectEqual(swift5, "emoji_🤖")
33+
34+
let cxx6 = std.string("xyz\0abc")
35+
expectEqual(cxx6.size(), 7)
36+
let swift6 = String(cxxString: cxx6)
37+
expectEqual(swift6, "xyz\0abc")
3338
}
3439

3540
extension std.string.const_iterator: UnsafeCxxInputIterator {

0 commit comments

Comments
 (0)