Skip to content

Commit a94a50b

Browse files
committed
Escape double quotes and add tests for dotgraph labels
1 parent 1a94d86 commit a94a50b

File tree

8 files changed

+54
-8
lines changed

8 files changed

+54
-8
lines changed

internal/graph/dotgraph.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"io"
2020
"math"
2121
"path/filepath"
22+
"regexp"
2223
"strings"
2324

2425
"github.com/google/pprof/internal/measurement"
@@ -127,7 +128,7 @@ func (b *builder) addLegend() {
127128
}
128129
title := labels[0]
129130
fmt.Fprintf(b, `subgraph cluster_L { "%s" [shape=box fontsize=16`, title)
130-
fmt.Fprintf(b, ` label="%s\l"`, strings.Join(labels, `\l`))
131+
fmt.Fprintf(b, ` label="%s\l"`, escapeDoubleQuotes(strings.Join(labels, `\l`)))
131132
if b.config.LegendURL != "" {
132133
fmt.Fprintf(b, ` URL="%s" target="_blank"`, b.config.LegendURL)
133134
}
@@ -472,3 +473,8 @@ func min64(a, b int64) int64 {
472473
}
473474
return b
474475
}
476+
477+
func escapeDoubleQuotes(s string) string {
478+
re := regexp.MustCompile(`\\([\s\S])|(")`)
479+
return re.ReplaceAllString(s, "\\$1$2")
480+
}

internal/graph/dotgraph_test.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func baseAttrsAndConfig() (*DotAttributes, *DotConfig) {
178178
}
179179
c := &DotConfig{
180180
Title: "testtitle",
181-
Labels: []string{"label1", "label2"},
181+
Labels: []string{"label1", "label2", `label3: "foo"`},
182182
Total: 100,
183183
FormatValue: func(v int64) string {
184184
return strconv.FormatInt(v, 10)
@@ -326,6 +326,46 @@ func TestTagCollapse(t *testing.T) {
326326
}
327327
}
328328

329+
func TestEscapeDoubleQuotes(t *testing.T) {
330+
for _, tc := range []struct {
331+
desc string
332+
input string
333+
want string
334+
}{
335+
{
336+
desc: "with multiple doubles quotes",
337+
input: `label: "foo" and "bar"`,
338+
want: `label: \"foo\" and \"bar\"`,
339+
},
340+
{
341+
desc: "with already escaped doubles quotes",
342+
input: `label: \"foo\" and \"bar\"`,
343+
want: `label: \"foo\" and \"bar\"`,
344+
},
345+
{
346+
desc: "with escaped character but no doubles quotes",
347+
input: `label: \$foo and bar`,
348+
want: `label: \$foo and bar`,
349+
},
350+
{
351+
desc: "with escaped backslash but not escaped doubles quotes",
352+
input: `label: \\"foo" and bar`,
353+
want: `label: \\\"foo\" and bar`,
354+
},
355+
{
356+
desc: "with two double quotes together",
357+
input: `label: ""`,
358+
want: `label: \"\"`,
359+
},
360+
} {
361+
t.Run(tc.desc, func(t *testing.T) {
362+
if got := escapeDoubleQuotes(tc.input); got != tc.want {
363+
t.Errorf("escapeDoubleQuotes(%s) = %s, want %s", tc.input, got, tc.want)
364+
}
365+
})
366+
}
367+
}
368+
329369
func tagString(t []*Tag) string {
330370
var ret []string
331371
for _, s := range t {

internal/graph/testdata/compose1.dot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
digraph "testtitle" {
22
node [style=filled fillcolor="#f8f8f8"]
3-
subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\l" tooltip="testtitle"] }
3+
subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\llabel3: \"foo\"\l" tooltip="testtitle"] }
44
N1 [label="src\n10 (10.00%)\nof 25 (25.00%)" id="node1" fontsize=22 shape=box tooltip="src (25)" color="#b23c00" fillcolor="#edddd5"]
55
N2 [label="dest\n15 (15.00%)\nof 25 (25.00%)" id="node2" fontsize=24 shape=box tooltip="dest (25)" color="#b23c00" fillcolor="#edddd5"]
66
N1 -> N2 [label=" 10" weight=11 color="#b28559" tooltip="src -> dest (10)" labeltooltip="src -> dest (10)"]

internal/graph/testdata/compose2.dot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
digraph "testtitle" {
22
node [style=filled fillcolor="#f8f8f8"]
3-
subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\l" tooltip="testtitle"] }
3+
subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\llabel3: \"foo\"\l" tooltip="testtitle"] }
44
N1 [label="SRC10 (10.00%)\nof 25 (25.00%)" id="node1" fontsize=24 shape=folder tooltip="src (25)" color="#b23c00" fillcolor="#edddd5" style="bold,filled" peripheries=2 URL="www.google.com" target="_blank"]
55
N2 [label="dest\n0 of 25 (25.00%)" id="node2" fontsize=8 shape=box tooltip="dest (25)" color="#b23c00" fillcolor="#edddd5"]
66
N1 -> N2 [label=" 10" weight=11 color="#b28559" tooltip="src -> dest (10)" labeltooltip="src -> dest (10)"]

internal/graph/testdata/compose3.dot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
digraph "testtitle" {
22
node [style=filled fillcolor="#f8f8f8"]
3-
subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\l" tooltip="testtitle"] }
3+
subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\llabel3: \"foo\"\l" tooltip="testtitle"] }
44
N1 [label="src\n10 (10.00%)\nof 25 (25.00%)" id="node1" fontsize=22 shape=box tooltip="src (25)" color="#b23c00" fillcolor="#edddd5"]
55
N1_0 [label = "tag1" id="N1_0" fontsize=8 shape=box3d tooltip="10"]
66
N1 -> N1_0 [label=" 10" weight=100 tooltip="10" labeltooltip="10"]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
digraph "testtitle" {
22
node [style=filled fillcolor="#f8f8f8"]
3-
subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\l" tooltip="testtitle"] }
3+
subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\llabel3: \"foo\"\l" tooltip="testtitle"] }
44
}

internal/graph/testdata/compose5.dot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
digraph "testtitle" {
22
node [style=filled fillcolor="#f8f8f8"]
3-
subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\l" tooltip="testtitle"] }
3+
subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\llabel3: \"foo\"\l" tooltip="testtitle"] }
44
N1 [label="src\n10 (10.00%)\nof 25 (25.00%)" id="node1" fontsize=22 shape=box tooltip="src (25)" color="#b23c00" fillcolor="#edddd5"]
55
N1_0 [label = "tag1" id="N1_0" fontsize=8 shape=box3d tooltip="10"]
66
N1 -> N1_0 [label=" 10" weight=100 tooltip="10" labeltooltip="10"]

internal/graph/testdata/compose6.dot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
digraph "testtitle" {
22
node [style=filled fillcolor="#f8f8f8"]
3-
subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\l" URL="http://example.com" target="_blank" tooltip="testtitle"] }
3+
subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\llabel3: \"foo\"\l" URL="http://example.com" target="_blank" tooltip="testtitle"] }
44
N1 [label="src\n10 (10.00%)\nof 25 (25.00%)" id="node1" fontsize=22 shape=box tooltip="src (25)" color="#b23c00" fillcolor="#edddd5"]
55
N2 [label="dest\n15 (15.00%)\nof 25 (25.00%)" id="node2" fontsize=24 shape=box tooltip="dest (25)" color="#b23c00" fillcolor="#edddd5"]
66
N1 -> N2 [label=" 10" weight=11 color="#b28559" tooltip="src -> dest (10)" labeltooltip="src -> dest (10)"]

0 commit comments

Comments
 (0)