Skip to content

Commit 3f01f85

Browse files
committed
[Demangling] Add error handling to the remangler.
Mangling can fail, usually because the Node structure has been built incorrectly or because something isn't supported with the old remangler. We shouldn't just terminate the program when that happens, particularly if it happens because someone has passed bad data to the demangler. rdar://79725187
1 parent 3c610db commit 3f01f85

File tree

19 files changed

+276
-97
lines changed

19 files changed

+276
-97
lines changed

include/swift/Demangling/Demangle.h

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -512,42 +512,94 @@ enum class OperatorKind {
512512
Infix,
513513
};
514514

515+
/// A mangling error, which consists of an error code and a Node pointer
516+
struct ManglingError {
517+
enum Code {
518+
Success = 0,
519+
Uninitialized,
520+
TooComplex,
521+
BadNodeKind,
522+
BadNominalTypeKind,
523+
NotAStorageNode,
524+
UnsupportedNodeKind,
525+
UnexpectedBuiltinVectorType,
526+
UnexpectedBuiltinType,
527+
};
528+
529+
Code code;
530+
NodePointer node;
531+
532+
ManglingError() : code(Uninitialized), node(nullptr) {}
533+
ManglingError(Code c, NodePointer n = nullptr) : code(c), node(n) {}
534+
535+
bool isSuccess() const { return code == Success; }
536+
};
537+
538+
/// Used as a return type for mangling functions that may fail
539+
template <typename T>
540+
class ManglingErrorOr {
541+
private:
542+
ManglingError err_;
543+
T value_;
544+
545+
public:
546+
ManglingErrorOr() : err_() {}
547+
ManglingErrorOr(ManglingError::Code code, NodePointer node = nullptr)
548+
: err_(code, node) {}
549+
ManglingErrorOr(const ManglingError &err) : err_(err) {}
550+
ManglingErrorOr(const T &t) : err_(ManglingError::Success), value_(t) {}
551+
ManglingErrorOr(T &&t) : err_(ManglingError::Success), value_(std::move(t)) {}
552+
553+
bool isSuccess() const { return err_.code == ManglingError::Success; }
554+
555+
ManglingError::Code errorCode() const { return err_.code; }
556+
NodePointer errorNode() const { return err_.node; }
557+
558+
const T &result() const {
559+
assert(isSuccess());
560+
return value_;
561+
}
562+
};
563+
515564
/// Remangle a demangled parse tree.
516-
std::string mangleNode(NodePointer root);
565+
ManglingErrorOr<std::string> mangleNode(NodePointer root);
517566

518567
using SymbolicResolver =
519568
llvm::function_ref<Demangle::NodePointer (SymbolicReferenceKind,
520569
const void *)>;
521570

522571
/// Remangle a demangled parse tree, using a callback to resolve
523572
/// symbolic references.
524-
std::string mangleNode(NodePointer root, SymbolicResolver resolver);
573+
ManglingErrorOr<std::string> mangleNode(NodePointer root, SymbolicResolver resolver);
525574

526575
/// Remangle a demangled parse tree, using a callback to resolve
527576
/// symbolic references.
528577
///
529578
/// The returned string is owned by \p Factory. This means \p Factory must stay
530579
/// alive as long as the returned string is used.
531-
llvm::StringRef mangleNode(NodePointer root, SymbolicResolver resolver,
532-
NodeFactory &Factory);
580+
ManglingErrorOr<llvm::StringRef> mangleNode(NodePointer root,
581+
SymbolicResolver resolver,
582+
NodeFactory &Factory);
533583

534584
/// Remangle in the old mangling scheme.
535585
///
536586
/// This is only used for objc-runtime names.
537-
std::string mangleNodeOld(NodePointer root);
587+
ManglingErrorOr<std::string> mangleNodeOld(NodePointer root);
538588

539589
/// Remangle in the old mangling scheme.
540590
///
541591
/// This is only used for objc-runtime names.
542592
/// The returned string is owned by \p Factory. This means \p Factory must stay
543593
/// alive as long as the returned string is used.
544-
llvm::StringRef mangleNodeOld(NodePointer node, NodeFactory &Factory);
594+
ManglingErrorOr<llvm::StringRef> mangleNodeOld(NodePointer node,
595+
NodeFactory &Factory);
545596

546597
/// Remangle in the old mangling scheme and embed the name in "_Tt<name>_".
547598
///
548599
/// The returned string is null terminated and owned by \p Factory. This means
549600
/// \p Factory must stay alive as long as the returned string is used.
550-
const char *mangleNodeAsObjcCString(NodePointer node, NodeFactory &Factory);
601+
ManglingErrorOr<const char *> mangleNodeAsObjcCString(NodePointer node,
602+
NodeFactory &Factory);
551603

552604
/// Transform the node structure to a string.
553605
///

include/swift/Demangling/TypeDecoder.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,8 +608,13 @@ class TypeDecoder {
608608
return decodeMangledType(genericArgs->getChild(0), depth + 1);
609609
}
610610
case NodeKind::BuiltinTypeName: {
611-
auto mangledName = Demangle::mangleNode(Node);
612-
return Builder.createBuiltinType(Node->getText().str(), mangledName);
611+
auto mangling = Demangle::mangleNode(Node);
612+
if (!mangling.isSuccess()) {
613+
return MAKE_NODE_TYPE_ERROR(Node,
614+
"failed to mangle node (%d)",
615+
mangling.errorCode());
616+
}
617+
return Builder.createBuiltinType(Node->getText().str(), mangling.result());
613618
}
614619
case NodeKind::Metatype:
615620
case NodeKind::ExistentialMetatype: {

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ class TypeRefBuilder {
289289
void clearNodeFactory() { Dem.clear(); }
290290

291291
BuiltType decodeMangledType(Node *node);
292-
292+
293293
///
294294
/// Factory methods for all TypeRef kinds
295295
///
@@ -300,12 +300,20 @@ class TypeRefBuilder {
300300
}
301301

302302
llvm::Optional<std::string> createTypeDecl(Node *node, bool &typeAlias) {
303-
return Demangle::mangleNode(node);
303+
auto mangling = Demangle::mangleNode(node);
304+
if (!mangling.isSuccess()) {
305+
return llvm::None;
306+
}
307+
return mangling.result();
304308
}
305309

306310
BuiltProtocolDecl
307311
createProtocolDecl(Node *node) {
308-
return std::make_pair(Demangle::mangleNode(node), false);
312+
auto mangling = Demangle::mangleNode(node);
313+
if (!mangling.isSuccess()) {
314+
return llvm::None;
315+
}
316+
return std::make_pair(mangling.result(), false);
309317
}
310318

311319
BuiltProtocolDecl
@@ -395,12 +403,16 @@ class TypeRefBuilder {
395403

396404
return underlyingTy->subst(*this, subs);
397405
}
398-
406+
407+
auto mangling = mangleNode(opaqueDescriptor,
408+
SymbolicResolver(),
409+
Dem);
410+
if (!mangling.isSuccess())
411+
return nullptr;
412+
399413
// Otherwise, build a type ref that represents the opaque type.
400414
return OpaqueArchetypeTypeRef::create(*this,
401-
mangleNode(opaqueDescriptor,
402-
SymbolicResolver(),
403-
Dem),
415+
mangling.result(),
404416
nodeToString(opaqueDescriptor),
405417
ordinal,
406418
genericArgs);

include/swift/Remote/MetadataReader.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,11 @@ class MetadataReader {
933933
if (!node || node->getKind() != Node::Kind::Type)
934934
return BuiltType();
935935

936-
auto name = Demangle::mangleNode(node);
936+
auto mangling = Demangle::mangleNode(node);
937+
if (!mangling.isSuccess())
938+
return BuiltType();
939+
auto name = mangling.result();
940+
937941
auto BuiltForeign = Builder.createForeignClassType(std::move(name));
938942
TypeCache[MetadataAddress] = BuiltForeign;
939943
return BuiltForeign;

lib/AST/ASTDemangler.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,11 @@ Type ASTBuilder::resolveOpaqueType(NodePointer opaqueDescriptor,
250250
auto definingDecl = opaqueDescriptor->getChild(0);
251251
auto definingGlobal = Factory.createNode(Node::Kind::Global);
252252
definingGlobal->addChild(definingDecl, Factory);
253-
auto mangledName = mangleNode(definingGlobal);
254-
253+
auto mangling = mangleNode(definingGlobal);
254+
if (!mangling.isSuccess())
255+
return Type();
256+
auto mangledName = mangling.result();
257+
255258
auto moduleNode = findModuleNode(definingDecl);
256259
if (!moduleNode)
257260
return Type();
@@ -935,7 +938,10 @@ ASTBuilder::findDeclContext(NodePointer node) {
935938
if (!module) return nullptr;
936939

937940
// Look up the local type by its mangling.
938-
auto mangledName = Demangle::mangleNode(node);
941+
auto mangling = Demangle::mangleNode(node);
942+
if (!mangling.isSuccess()) return nullptr;
943+
auto mangledName = mangling.result();
944+
939945
auto decl = module->lookupLocalType(mangledName);
940946
if (!decl) return nullptr;
941947

lib/AST/ASTMangler.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,11 @@ std::string ASTMangler::mangleSILDifferentiabilityWitness(StringRef originalName
547547
Demangler demangler;
548548
auto *node = mangleSILDifferentiabilityWitnessAsNode(
549549
originalName, kind, config, demangler);
550-
return mangleNode(node);
550+
auto mangling = mangleNode(node);
551+
if (!mangling.isSuccess()) {
552+
llvm_unreachable("unexpected mangling failure");
553+
}
554+
return mangling.result();
551555
}
552556
beginManglingWithoutPrefix();
553557
appendOperator(originalName);
@@ -721,8 +725,11 @@ std::string ASTMangler::mangleObjCRuntimeName(const NominalTypeDecl *Nominal) {
721725
TyMangling->addChild(Ty, Dem);
722726
Node *NewGlobal = Dem.createNode(Node::Kind::Global);
723727
NewGlobal->addChild(TyMangling, Dem);
724-
std::string OldName = mangleNodeOld(NewGlobal);
725-
return OldName;
728+
auto mangling = mangleNodeOld(NewGlobal);
729+
if (!mangling.isSuccess()) {
730+
llvm_unreachable("unexpected mangling failure");
731+
}
732+
return mangling.result();
726733
#endif
727734
}
728735

lib/Basic/Mangler.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,12 @@ void Mangler::verify(StringRef nameStr) {
176176
llvm::errs() << "Can't demangle: " << nameStr << '\n';
177177
abort();
178178
}
179-
std::string Remangled = mangleNode(Root);
179+
auto mangling = mangleNode(Root);
180+
if (!mangling.isSuccess()) {
181+
llvm::errs() << "Can't remangle: " << nameStr << '\n';
182+
abort();
183+
}
184+
std::string Remangled = mangling.result();
180185
if (Remangled == nameStr)
181186
return;
182187

lib/Demangling/OldRemangler.cpp

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,18 @@ namespace {
7474
};
7575
};
7676

77-
void mangle(Node *node, unsigned depth) {
77+
ManglingError mangle(Node *node, unsigned depth) {
7878
if (depth > Remangler::MaxDepth) {
79-
// FIXME: error handling needs doing properly (rdar://79725187)
80-
unreachable("too complex to remangle");
79+
return ManglingError(ManglingError::TooComplex, node);
8180
}
8281

8382
switch (node->getKind()) {
8483
#define NODE(ID) \
8584
case Node::Kind::ID: \
86-
return mangle##ID(node, depth);
85+
mangle##ID(node, depth); return ManglingError(ManglingError::Success);
8786
#include "swift/Demangling/DemangleNodes.def"
8887
}
89-
unreachable("bad demangling tree node");
88+
return ManglingError(ManglingError::BadNodeKind, node);
9089
}
9190

9291
void mangleGenericArgs(Node *node, EntityContext &ctx, unsigned depth);
@@ -2403,32 +2402,41 @@ void Remangler::mangleCanonicalPrespecializedGenericTypeCachingOnceToken(
24032402
}
24042403

24052404
/// The top-level interface to the remangler.
2406-
std::string Demangle::mangleNodeOld(NodePointer node) {
2407-
if (!node) return "";
2405+
ManglingErrorOr<std::string>
2406+
Demangle::mangleNodeOld(NodePointer node) {
2407+
if (!node) return std::string();
24082408

24092409
NodeFactory Factory;
24102410
Remangler remangler(Factory);
2411-
remangler.mangle(node, 0);
2411+
ManglingError err = remangler.mangle(node, 0);
2412+
if (!err.isSuccess())
2413+
return err;
24122414

24132415
return remangler.str();
24142416
}
24152417

2416-
llvm::StringRef Demangle::mangleNodeOld(NodePointer node, NodeFactory &Factory) {
2417-
if (!node) return "";
2418+
ManglingErrorOr<llvm::StringRef>
2419+
Demangle::mangleNodeOld(NodePointer node, NodeFactory &Factory) {
2420+
if (!node) return llvm::StringRef();
24182421

24192422
Remangler remangler(Factory);
2420-
remangler.mangle(node, 0);
2423+
ManglingError err = remangler.mangle(node, 0);
2424+
if (!err.isSuccess())
2425+
return err;
24212426

24222427
return remangler.getBufferStr();
24232428
}
24242429

2425-
const char *Demangle::mangleNodeAsObjcCString(NodePointer node,
2426-
NodeFactory &Factory) {
2430+
ManglingErrorOr<const char *>
2431+
Demangle::mangleNodeAsObjcCString(NodePointer node,
2432+
NodeFactory &Factory) {
24272433
assert(node);
24282434

24292435
Remangler remangler(Factory);
24302436
remangler.append("_Tt");
2431-
remangler.mangle(node, 0);
2437+
ManglingError err = remangler.mangle(node, 0);
2438+
if (!err.isSuccess())
2439+
return err;
24322440
remangler.append(StringRef("_", 2)); // Include the trailing 0 char.
24332441

24342442
return remangler.getBufferStr().data();

0 commit comments

Comments
 (0)