Skip to content

Commit 4bf4fba

Browse files
committed
Merge pull request #2169 from apple/demangle
[runtime] Fortify the swift_demangle API.
2 parents 3abe479 + eac72f0 commit 4bf4fba

File tree

6 files changed

+137
-29
lines changed

6 files changed

+137
-29
lines changed

include/swift/Runtime/Portability.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===--- Portability.h -----------------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Includes stub APIs that make the portable runtime easier to write.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_RUNTIME_PORTABILITY_H
18+
#define SWIFT_RUNTIME_PORTABILITY_H
19+
#include <stddef.h>
20+
21+
size_t _swift_strlcpy(char *dst, const char *src, size_t maxlen);
22+
23+
#endif

stdlib/public/core/Misc.swift

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -121,30 +121,6 @@ func _typeByName(_ name: String) -> Any.Type? {
121121
return type
122122
}
123123
}
124-
125-
@warn_unused_result
126-
@_silgen_name("swift_stdlib_demangleName")
127-
func _stdlib_demangleNameImpl(
128-
_ mangledName: UnsafePointer<UInt8>,
129-
_ mangledNameLength: UInt,
130-
_ demangledName: UnsafeMutablePointer<String>)
131-
132-
// NB: This function is not used directly in the Swift codebase, but is
133-
// exported for Xcode support. Please coordinate before changing.
134-
@warn_unused_result
135-
public // @testable
136-
func _stdlib_demangleName(_ mangledName: String) -> String {
137-
let mangledNameUTF8 = Array(mangledName.utf8)
138-
return mangledNameUTF8.withUnsafeBufferPointer {
139-
(mangledNameUTF8) in
140-
let (_, demangledName) = _withUninitializedString {
141-
_stdlib_demangleNameImpl(
142-
mangledNameUTF8.baseAddress!, UInt(mangledNameUTF8.endIndex),
143-
$0)
144-
}
145-
return demangledName
146-
}
147-
}
148124

149125
/// Returns `floor(log(x))`. This equals to the position of the most
150126
/// significant non-zero bit, or 63 - number-of-zeros before it.

stdlib/public/runtime/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ set(swift_runtime_sources
4747
MetadataLookup.cpp
4848
Mutex.cpp
4949
Once.cpp
50+
Portability.cpp
5051
ProtocolConformance.cpp
5152
Reflection.cpp
5253
RuntimeEntrySymbols.cpp

stdlib/public/runtime/Portability.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===--- Portability.cpp - -----------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===---------------------------------------------------------------------===//
12+
//
13+
// Implementations of the stub APIs that make portable runtime easier to write.
14+
//
15+
//===---------------------------------------------------------------------===//
16+
17+
#include "swift/Runtime/Portability.h"
18+
#include <cstring>
19+
20+
size_t _swift_strlcpy(char *dst, const char *src, size_t maxlen) {
21+
const size_t srclen = std::strlen(src);
22+
if (srclen < maxlen) {
23+
std::memmove(dst, src, srclen + 1);
24+
} else if (maxlen != 0) {
25+
std::memmove(dst, src, maxlen - 1);
26+
dst[maxlen - 1] = '\0';
27+
}
28+
return srclen;
29+
}

stdlib/public/runtime/Reflection.mm

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/Runtime/Enum.h"
1818
#include "swift/Basic/Demangle.h"
1919
#include "swift/Runtime/Debug.h"
20+
#include "swift/Runtime/Portability.h"
2021
#include "Private.h"
2122
#include <cassert>
2223
#include <cstdio>
@@ -1190,16 +1191,63 @@ static Mirror ObjC_getMirrorForSuperclass(Class sup,
11901191
}
11911192

11921193
// NB: This function is not used directly in the Swift codebase, but is
1193-
// exported for Xcode support. Please coordinate before changing.
1194+
// exported for Xcode support and is used by the sanitizers. Please coordinate
1195+
// before changing.
1196+
//
1197+
/// Demangles a Swift symbol name.
1198+
///
1199+
/// \param mangledName is the symbol name that needs to be demangled.
1200+
/// \param mangledNameLength is the length of the string that should be
1201+
/// demangled.
1202+
/// \param outputBuffer is the user provided buffer where the demangled name
1203+
/// will be placed. If nullptr, a new buffer will be malloced. In that case,
1204+
/// the user of this API is responsible for freeing the returned buffer.
1205+
/// \param outputBufferSize is the size of the output buffer. If the demangled
1206+
/// name does not fit into the outputBuffer, the output will be truncated and
1207+
/// the size will be updated, indicating how large the buffer should be.
1208+
/// \param flags can be used to select the demangling style. TODO: We should
1209+
//// define what these will be.
1210+
/// \returns the demangled name. Returns nullptr if the input String is not a
1211+
/// Swift mangled name.
11941212
SWIFT_RUNTIME_EXPORT
1195-
extern "C" void swift_stdlib_demangleName(const char *mangledName,
1196-
size_t mangledNameLength,
1197-
String *demangledName) {
1213+
extern "C" char *swift_demangle(const char *mangledName,
1214+
size_t mangledNameLength,
1215+
char *outputBuffer,
1216+
size_t *outputBufferSize,
1217+
uint32_t flags) {
1218+
if (flags != 0) {
1219+
swift::fatalError(0, "Only 'flags' value of '0' is currently supported.");
1220+
}
1221+
if (outputBuffer != nullptr && outputBufferSize == nullptr) {
1222+
swift::fatalError(0, "'outputBuffer' is passed but the size is 'nullptr'.");
1223+
}
1224+
1225+
// Check if we are dealing with Swift mangled name, otherwise, don't try
1226+
// to demangle and send indication to the user.
1227+
if (mangledName[0] != '_' || mangledName[1] != 'T') {
1228+
return nullptr;
1229+
}
1230+
1231+
// Demangle the name.
11981232
auto options = Demangle::DemangleOptions();
11991233
options.DisplayDebuggerGeneratedModule = false;
12001234
auto result =
12011235
Demangle::demangleSymbolAsString(mangledName,
12021236
mangledNameLength,
12031237
options);
1204-
new (demangledName) String(result.data(), result.size());
1238+
1239+
// If the output buffer is not provided, malloc memory ourselves.
1240+
if (outputBuffer == nullptr || *outputBufferSize == 0) {
1241+
return strdup(result.c_str());
1242+
}
1243+
1244+
// Indicate a failure if the result does not fit and will be truncated
1245+
// and set the required outputBufferSize.
1246+
if (*outputBufferSize < result.length() + 1) {
1247+
*outputBufferSize = result.length() + 1;
1248+
}
1249+
1250+
// Copy into the provided buffer.
1251+
_swift_strlcpy(outputBuffer, result.c_str(), *outputBufferSize);
1252+
return outputBuffer;
12051253
}

test/1_stdlib/Runtime.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,37 @@ import StdlibUnittest
99
import SwiftShims
1010

1111

12+
@warn_unused_result
13+
@_silgen_name("swift_demangle")
14+
public
15+
func _stdlib_demangleImpl(
16+
mangledName: UnsafePointer<UInt8>?,
17+
mangledNameLength: UInt,
18+
outputBuffer: UnsafeMutablePointer<UInt8>?,
19+
outputBufferSize: UnsafeMutablePointer<UInt>?,
20+
flags: UInt32
21+
) -> UnsafeMutablePointer<CChar>?
22+
23+
@warn_unused_result
24+
func _stdlib_demangleName(_ mangledName: String) -> String {
25+
return mangledName.nulTerminatedUTF8.withUnsafeBufferPointer {
26+
(mangledNameUTF8) in
27+
28+
let demangledNamePtr = _stdlib_demangleImpl(
29+
mangledName: mangledNameUTF8.baseAddress,
30+
mangledNameLength: UInt(mangledNameUTF8.count - 1),
31+
outputBuffer: nil,
32+
outputBufferSize: nil,
33+
flags: 0)
34+
35+
if let demangledNamePtr = demangledNamePtr {
36+
let demangledName = String(cString: demangledNamePtr)
37+
_swift_stdlib_free(demangledNamePtr)
38+
return demangledName
39+
}
40+
return mangledName
41+
}
42+
}
1243

1344
var swiftObjectCanaryCount = 0
1445
class SwiftObjectCanary {

0 commit comments

Comments
 (0)