From 62af02e76fe808134b06b75c8108a98c079ac8bc Mon Sep 17 00:00:00 2001 From: Alex Cameron Date: Mon, 9 Mar 2020 11:58:12 +0000 Subject: [PATCH] [XRay] Sanitize DOT labels in graph output Summary: Bugzilla: https://bugs.llvm.org/show_bug.cgi?id=39701 This patch is to convert certain characters to their XML escape sequences when generating labels for a DOT graph. I had trouble reproducing the exact issue described on the tracker. I ran `llvm-xray graph` on a log from a test program that included function templates but wasn't able to get the `dot` tool to complain about the `<` and `>` characters. The documentation also suggests that the escape sequences should only be necessary when using HTML string labels which XRay doesn't use (`label=<...>` as opposed to `label="..."`). Perhaps newer versions of Graphviz silently handle this in the case of quoted-string labels. In any case, the generated labels still look correct after this patch and should also fix the reporter's issue. I was a bit unsure how to add a test for this since the existing tests seem to only care about `func-id` rather than giving an actual name. If you could give me a hint on the best way to go about this, that'd be much appreciated! Reviewers: dberris Reviewed By: dberris Subscribers: lebedev.ri, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D69461 --- llvm/tools/llvm-xray/xray-graph.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/llvm/tools/llvm-xray/xray-graph.cpp b/llvm/tools/llvm-xray/xray-graph.cpp index f836f9b..522609b 100644 --- a/llvm/tools/llvm-xray/xray-graph.cpp +++ b/llvm/tools/llvm-xray/xray-graph.cpp @@ -163,6 +163,30 @@ static void updateStat(GraphRenderer::TimeStat &S, int64_t L) { S.Sum += L; } +// Labels in a DOT graph must be legal XML strings so it's necessary to escape +// certain characters. +static std::string escapeString(StringRef Label) { + std::string Str; + Str.reserve(Label.size()); + for (const auto C : Label) { + switch (C) { + case '&': + Str.append("&"); + break; + case '<': + Str.append("<"); + break; + case '>': + Str.append(">"); + break; + default: + Str.push_back(C); + break; + } + } + return Str; +} + // Evaluates an XRay record and performs accounting on it. // // If the record is an ENTER record it pushes the FuncID and TSC onto a @@ -398,8 +422,9 @@ void GraphRenderer::exportGraphAsDOT(raw_ostream &OS, StatType ET, StatType EC, if (V.first == 0) continue; OS << "F" << V.first << " [label=\"" << (VT != StatType::NONE ? "{" : "") - << (VA.SymbolName.size() > 40 ? VA.SymbolName.substr(0, 40) + "..." - : VA.SymbolName); + << escapeString(VA.SymbolName.size() > 40 + ? VA.SymbolName.substr(0, 40) + "..." + : VA.SymbolName); if (VT != StatType::NONE) OS << "|" << VA.S.getString(VT) << "}\""; else -- 2.7.4