Skip to content

Commit 696fb5e

Browse files
committed
cmd/internal/objabi: add inverse of PathToPrefix
Add PrefixToPath, which can be used to convert a package path in a symbol name back to the original package path. For #61577. Change-Id: Ifbe8c852a7f41ff9b81ad48b92a26a0e1b046777 Reviewed-on: https://go-review.googlesource.com/c/go/+/529557 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Reviewed-by: Cherry Mui <[email protected]>
1 parent d1ef967 commit 696fb5e

File tree

2 files changed

+74
-8
lines changed

2 files changed

+74
-8
lines changed

src/cmd/internal/objabi/path.go

+38-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
package objabi
66

7-
import "strings"
7+
import (
8+
"fmt"
9+
"strconv"
10+
"strings"
11+
)
812

913
// PathToPrefix converts raw string to the prefix that will be used in the
1014
// symbol table. All control characters, space, '%' and '"', as well as
@@ -39,3 +43,36 @@ func PathToPrefix(s string) string {
3943

4044
return string(p)
4145
}
46+
47+
// PrefixToPath is the inverse of PathToPrefix, replacing escape sequences with
48+
// the original character.
49+
func PrefixToPath(s string) (string, error) {
50+
percent := strings.IndexByte(s, '%')
51+
if percent == -1 {
52+
return s, nil
53+
}
54+
55+
p := make([]byte, 0, len(s))
56+
for i := 0; i < len(s); {
57+
if s[i] != '%' {
58+
p = append(p, s[i])
59+
i++
60+
continue
61+
}
62+
if i+2 >= len(s) {
63+
// Not enough characters remaining to be a valid escape
64+
// sequence.
65+
return "", fmt.Errorf("malformed prefix %q: escape sequence must contain two hex digits", s)
66+
}
67+
68+
b, err := strconv.ParseUint(s[i+1:i+3], 16, 8)
69+
if err != nil {
70+
// Not a valid escape sequence.
71+
return "", fmt.Errorf("malformed prefix %q: escape sequence %q must contain two hex digits", s, s[i:i+3])
72+
}
73+
74+
p = append(p, byte(b))
75+
i += 3
76+
}
77+
return string(p), nil
78+
}

src/cmd/internal/objabi/path_test.go

+36-7
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import (
1111
"testing"
1212
)
1313

14-
func TestPathToPrefix(t *testing.T) {
15-
tests := []struct {
16-
Path string
17-
Expected string
18-
}{{"foo/bar/v1", "foo/bar/v1"},
14+
var escapeTests = []struct {
15+
Path string
16+
Escaped string
17+
}{
18+
{"foo/bar/v1", "foo/bar/v1"},
1919
{"foo/bar/v.1", "foo/bar/v%2e1"},
2020
{"f.o.o/b.a.r/v1", "f.o.o/b.a.r/v1"},
2121
{"f.o.o/b.a.r/v.1", "f.o.o/b.a.r/v%2e1"},
@@ -30,9 +30,38 @@ func TestPathToPrefix(t *testing.T) {
3030
{"%foo%bar", "%25foo%25bar"},
3131
{"\x01\x00\x7F☺", "%01%00%7f%e2%98%ba"},
3232
}
33+
34+
func TestPathToPrefix(t *testing.T) {
35+
for _, tc := range escapeTests {
36+
if got := PathToPrefix(tc.Path); got != tc.Escaped {
37+
t.Errorf("expected PathToPrefix(%s) = %s, got %s", tc.Path, tc.Escaped, got)
38+
}
39+
}
40+
}
41+
42+
func TestPrefixToPath(t *testing.T) {
43+
for _, tc := range escapeTests {
44+
got, err := PrefixToPath(tc.Escaped)
45+
if err != nil {
46+
t.Errorf("expected PrefixToPath(%s) err = nil, got %v", tc.Escaped, err)
47+
}
48+
if got != tc.Path {
49+
t.Errorf("expected PrefixToPath(%s) = %s, got %s", tc.Escaped, tc.Path, got)
50+
}
51+
}
52+
}
53+
54+
func TestPrefixToPathError(t *testing.T) {
55+
tests := []string{
56+
"foo%",
57+
"foo%1",
58+
"foo%%12",
59+
"foo%1g",
60+
}
3361
for _, tc := range tests {
34-
if got := PathToPrefix(tc.Path); got != tc.Expected {
35-
t.Errorf("expected PathToPrefix(%s) = %s, got %s", tc.Path, tc.Expected, got)
62+
_, err := PrefixToPath(tc)
63+
if err == nil {
64+
t.Errorf("expected PrefixToPath(%s) err != nil, got nil", tc)
3665
}
3766
}
3867
}

0 commit comments

Comments
 (0)