fix: change CID breaking logic when parsing ipld.ErrNotFound
This commit was moved from ipfs/go-ipfs-http-client@a3b49352bfd1b885567018092a06f303de18b7aa
Jorropo committed
Apr 2, 2022 at 03:25 UTC
54f6e90870c61a686f57b0bd0f1ad4923615897b
2 files changed
+16
-26
client/httpapi/errors.go
+9
-15
@@ -47,18 +47,6 @@ func parseErrNotFoundWithFallbackToError(msg error) error {
47
return msg
48
}
49
50
-// Use a string to move it into RODATA
51
-// print("".join("\\x01" if chr(i) not in string.ascii_letters + string.digits else "\\x00" for i in range(ord('z')+1)))
52
-const notAsciiLetterOrDigitsLUT = "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
53
-
54
-func notAsciiLetterOrDigits(r rune) bool {
55
- if r > 'z' {
56
- return true
57
- }
58
-
59
- return notAsciiLetterOrDigitsLUT[r] > 0
60
-}
61
-
50
//lint:ignore ST1008 this function is not using the error as a mean to return failure but it massages it to return the correct type
51
func parseErrNotFound(msg string) (error, bool) {
52
if msg == "" {
@@ -76,6 +64,12 @@ func parseErrNotFound(msg string) (error, bool) {
64
return nil, false
65
}
66
67
+// Assume CIDs break on:
68
+// - Whitespaces: " \t\n\r\v\f"
69
+// - Semicolon: ";" this is to parse ipld.ErrNotFound wrapped in multierr
70
+// - Double Quotes: "\"" this is for parsing %q and %#v formating
71
+const cidBreakSet = " \t\n\r\v\f;\""
72
+
73
//lint:ignore ST1008 using error as values
74
func parseIPLDErrNotFound(msg string) (error, bool) {
75
// The patern we search for is:
@@ -99,9 +93,9 @@ func parseIPLDErrNotFound(msg string) (error, bool) {
93
c = cid.Undef
94
postIndex = len("node")
95
} else {
102
- // Assume that CIDs only contain a-zA-Z0-9 characters.
103
- // This is true because go-ipld-format use go-cid#Cid.String which use base{3{2,6},58}.
104
- postIndex = strings.IndexFunc(msgPostKey, notAsciiLetterOrDigits)
96
+ postIndex = strings.IndexFunc(msgPostKey, func(r rune) bool {
97
+ return strings.ContainsAny(string(r), cidBreakSet)
98
+ })
99
if postIndex < 0 {
100
postIndex = len(msgPostKey)
101
}
client/httpapi/errors_test.go
+7
-11
@@ -3,7 +3,6 @@ package httpapi
3
import (
4
"errors"
5
"fmt"
6
- "strings"
6
"testing"
7
8
"github.com/ipfs/go-cid"
@@ -36,12 +35,17 @@ func TestParseIPLDNotFound(t *testing.T) {
35
t.Errorf("expected empty string to give no error; got %T %q", err, err.Error())
36
}
37
39
- for _, wrap := range [...]string{
38
+ cidBreaks := make([]string, len(cidBreakSet))
39
+ for i, v := range cidBreakSet {
40
+ cidBreaks[i] = "%w" + string(v)
41
+ }
42
+
43
+ for _, wrap := range append(cidBreaks,
44
"",
45
"merkledag: %w",
46
"testing: %w the test",
47
"%w is wrong",
44
- } {
48
+ ) {
49
for _, err := range [...]error{
50
errors.New("ipld: could not find "),
51
errors.New("ipld: could not find Bad_CID"),
@@ -79,11 +83,3 @@ func TestBlockstoreNotFoundMatchingIPLDErrNotFound(t *testing.T) {
83
doParseIpldNotFoundTest(t, err)
84
}
85
}
82
-
83
-func TestNotAsciiLetterOrDigits(t *testing.T) {
84
- for i := rune(0); i <= 256; i++ {
85
- if notAsciiLetterOrDigits(i) != !strings.ContainsAny(string(i), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") {
86
- t.Errorf("%q is incorrectly identified", i)
87
- }
88
- }
89
-}