Skip to content

Commit 7f91a50

Browse files
committed
add tests for C++ symbol demangling
1 parent 5626571 commit 7f91a50

File tree

2 files changed

+52
-19
lines changed

2 files changed

+52
-19
lines changed

stdlib/public/runtime/Demangle.cpp

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,21 +1112,18 @@ namespace swift {
11121112

11131113
if (outputBufferSize) {
11141114
bufferSize = *outputBufferSize;
1115-
*outputBufferSize = resultLen;
1115+
if (!outputBuffer) {
1116+
// cxa_demangle always \0 terminates the strings, however since we're relying on the initialized
1117+
// count when forming Spans around the results from this func, we don't need to rely on null-terminated strings.
1118+
*outputBufferSize = resultLen - 1;
1119+
return result;
1120+
} else {
1121+
*outputBufferSize = resultLen - 1; // ignore the trailing
1122+
}
11161123
}
11171124

1118-
if (outputBuffer == nullptr) {
1119-
return result;
1120-
}
1121-
1122-
size_t toCopy = std::min(
1123-
shouldNullTerminateString ? (bufferSize - 1) : bufferSize,
1124-
shouldNullTerminateString ? (resultLen - 1) : resultLen
1125-
);
1125+
size_t toCopy = std::min(bufferSize, resultLen);
11261126
::memcpy(outputBuffer, result, toCopy);
1127-
if (shouldNullTerminateString) {
1128-
outputBuffer[toCopy] = '\0';
1129-
}
11301127

11311128
free(result);
11321129

test/Concurrency/Runtime/RuntimeDemangle.swift

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ if #available(SwiftStdlib 6.3, *) {
3030
expectEqual(demangle("_$sSS7cStringSSSPys4Int8VG_tcfC"), "Swift.String.init(cString: Swift.UnsafePointer<Swift.Int8>) -> Swift.String")
3131
}
3232

33-
DemangleTests.test("Span API") {
34-
func test(body: (inout OutputSpan<UTF8.CodeUnit>) -> ()) {
35-
let buffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: 140)
36-
var outputSpan = OutputSpan<UTF8.CodeUnit>(buffer: buffer, initializedCount: 0)
33+
func test(body: (inout OutputSpan<UTF8.CodeUnit>) -> ()) {
34+
let buffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: 140)
35+
var outputSpan = OutputSpan<UTF8.CodeUnit>(buffer: buffer, initializedCount: 0)
3736

38-
defer { buffer.deallocate() }
37+
defer { buffer.deallocate() }
3938

40-
body(&outputSpan)
41-
}
39+
body(&outputSpan)
40+
}
4241

42+
DemangleTests.test("Span API") {
4343
// First, test that the buffer is still empty after failed demanglings.
4444
test { outputSpan in
4545
let res = demangle("abc123".utf8Span, into: &outputSpan)
@@ -136,6 +136,42 @@ if #available(SwiftStdlib 6.3, *) {
136136
expectEqual(String(copying: try! UTF8Span(validating: smolOutputSpan.span)), "Smol.Int")
137137
}
138138

139+
DemangleTests.test("String API - demangle C++ symbols") {
140+
expectEqual(demangle("_ZN7MyClass6methodEi"), "MyClass::method(int)")
141+
expectEqual(demangle("_ZNKSt6vectorIiSaIiEE4sizeEv"), "std::vector<int, std::allocator<int>>::size() const")
142+
}
143+
144+
DemangleTests.test("String API - demangle C++ symbols, illegal") {
145+
expectEqual(demangle("_ZNKSt6vectorIiSaIiEEv"), nil)
146+
}
147+
148+
DemangleTests.test("Span API - demangle C++ symbols") {
149+
test { outputSpan in
150+
let res = demangle("_ZN7MyClass6methodEi".utf8Span, into: &outputSpan)
151+
let demangled = String(copying: try! UTF8Span(validating: outputSpan.span))
152+
print("res = \(demangled) len:\(demangled.count)")
153+
expectEqual(res, .success)
154+
expectEqual(demangled, "MyClass::method(int)")
155+
}
156+
test { outputSpan in
157+
let res = demangle("_ZNKSt6vectorIiSaIiEE4sizeEv".utf8Span, into: &outputSpan)
158+
let demangled = String(copying: try! UTF8Span(validating: outputSpan.span))
159+
print("res = \(demangled) len:\(demangled.count)")
160+
expectEqual(res, .success)
161+
expectEqual(demangled, "std::vector<int, std::allocator<int>>::size() const")
162+
}
163+
}
164+
165+
DemangleTests.test("Span API - demangle C++ symbols, too small buffer") {
166+
let smolBuffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: 12)
167+
var smolOutputSpan = OutputSpan<UTF8.CodeUnit>(buffer: smolBuffer, initializedCount: 0)
168+
defer { smolBuffer.deallocate() }
169+
170+
let fail = demangle("_ZN7MyClass6methodEi".utf8Span, into: &smolOutputSpan)
171+
expectEqual(fail, .truncated(9))
172+
expectEqual(String(copying: try! UTF8Span(validating: smolOutputSpan.span)), "MyClass::met")
173+
}
174+
139175
}
140176

141177
runAllTests()

0 commit comments

Comments
 (0)