forked from TrueCloudLab/restic
internal/restic: Fix ID.UnmarshalJSON, ParseID
ID.UnmarshalJSON accepted non-JSON input with ' as the string delimiter. Also, the error message for non-hex input was less informative than it could be and it performed too many checks. Changed ParseID to keep the error messages consistent.
This commit is contained in:
parent
0e155fd9a6
commit
d03460010f
1 changed files with 12 additions and 28 deletions
|
@ -6,8 +6,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/restic/restic/internal/errors"
|
|
||||||
|
|
||||||
"github.com/minio/sha256-simd"
|
"github.com/minio/sha256-simd"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,14 +22,13 @@ type ID [idSize]byte
|
||||||
|
|
||||||
// ParseID converts the given string to an ID.
|
// ParseID converts the given string to an ID.
|
||||||
func ParseID(s string) (ID, error) {
|
func ParseID(s string) (ID, error) {
|
||||||
b, err := hex.DecodeString(s)
|
if len(s) != hex.EncodedLen(idSize) {
|
||||||
|
return ID{}, fmt.Errorf("invalid length for ID: %q", s)
|
||||||
if err != nil {
|
|
||||||
return ID{}, errors.Wrap(err, "hex.DecodeString")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(b) != idSize {
|
b, err := hex.DecodeString(s)
|
||||||
return ID{}, errors.New("invalid length for hash")
|
if err != nil {
|
||||||
|
return ID{}, fmt.Errorf("invalid ID: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
id := ID{}
|
id := ID{}
|
||||||
|
@ -96,34 +93,21 @@ func (id ID) MarshalJSON() ([]byte, error) {
|
||||||
// UnmarshalJSON parses the JSON-encoded data and stores the result in id.
|
// UnmarshalJSON parses the JSON-encoded data and stores the result in id.
|
||||||
func (id *ID) UnmarshalJSON(b []byte) error {
|
func (id *ID) UnmarshalJSON(b []byte) error {
|
||||||
// check string length
|
// check string length
|
||||||
if len(b) < 2 {
|
if len(b) != len(`""`)+hex.EncodedLen(idSize) {
|
||||||
return fmt.Errorf("invalid ID: %q", b)
|
return fmt.Errorf("invalid length for ID: %q", b)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(b)%2 != 0 {
|
if b[0] != '"' {
|
||||||
return fmt.Errorf("invalid ID length: %q", b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check string delimiters
|
|
||||||
if b[0] != '"' && b[0] != '\'' {
|
|
||||||
return fmt.Errorf("invalid start of string: %q", b[0])
|
return fmt.Errorf("invalid start of string: %q", b[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
last := len(b) - 1
|
// Strip JSON string delimiters. The json.Unmarshaler contract says we get
|
||||||
if b[0] != b[last] {
|
// a valid JSON value, so we don't need to check that b[len(b)-1] == '"'.
|
||||||
return fmt.Errorf("starting string delimiter (%q) does not match end (%q)", b[0], b[last])
|
b = b[1 : len(b)-1]
|
||||||
}
|
|
||||||
|
|
||||||
// strip JSON string delimiters
|
|
||||||
b = b[1:last]
|
|
||||||
|
|
||||||
if len(b) != 2*len(id) {
|
|
||||||
return fmt.Errorf("invalid length for ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := hex.Decode(id[:], b)
|
_, err := hex.Decode(id[:], b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "hex.Decode")
|
return fmt.Errorf("invalid ID: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in a new issue