Merge pull request #97 from ipfs/fix/parse-panic

fix parsing issues and nits
This commit is contained in:
Steven Allen
2019-12-03 09:50:46 -05:00
committed by GitHub
3 changed files with 38 additions and 13 deletions

View File

@@ -38,7 +38,7 @@ func (p V0Builder) Sum(data []byte) (Cid, error) {
if err != nil {
return Undef, err
}
return NewCidV0(hash), nil
return Cid{string(hash)}, nil
}
func (p V0Builder) GetCodec() uint64 {

38
cid.go
View File

@@ -137,25 +137,39 @@ var CodecToStr = map[uint64]string{
DashTx: "dash-tx",
}
// NewCidV0 returns a Cid-wrapped multihash.
// They exist to allow IPFS to work with Cids while keeping
// compatibility with the plain-multihash format used used in IPFS.
// NewCidV1 should be used preferentially.
func NewCidV0(mhash mh.Multihash) Cid {
// tryNewCidV0 tries to convert a multihash into a CIDv0 CID and returns an
// error on failure.
func tryNewCidV0(mhash mh.Multihash) (Cid, error) {
// Need to make sure hash is valid for CidV0 otherwise we will
// incorrectly detect it as CidV1 in the Version() method
dec, err := mh.Decode(mhash)
if err != nil {
panic(err)
return Undef, err
}
if dec.Code != mh.SHA2_256 || dec.Length != 32 {
panic("invalid hash for cidv0")
return Undef, fmt.Errorf("invalid hash for cidv0 %d-%d", dec.Code, dec.Length)
}
return Cid{string(mhash)}
return Cid{string(mhash)}, nil
}
// NewCidV0 returns a Cid-wrapped multihash.
// They exist to allow IPFS to work with Cids while keeping
// compatibility with the plain-multihash format used used in IPFS.
// NewCidV1 should be used preferentially.
//
// Panics if the multihash isn't sha2-256.
func NewCidV0(mhash mh.Multihash) Cid {
c, err := tryNewCidV0(mhash)
if err != nil {
panic(err)
}
return c
}
// NewCidV1 returns a new Cid using the given multicodec-packed
// content type.
//
// Panics if the multihash is invalid.
func NewCidV1(codecType uint64, mhash mh.Multihash) Cid {
hashlen := len(mhash)
// two 8 bytes (max) numbers plus hash
@@ -203,7 +217,7 @@ func Parse(v interface{}) (Cid, error) {
case []byte:
return Cast(v2)
case mh.Multihash:
return NewCidV0(v2), nil
return tryNewCidV0(v2)
case Cid:
return v2, nil
default:
@@ -234,7 +248,7 @@ func Decode(v string) (Cid, error) {
return Undef, err
}
return NewCidV0(hash), nil
return tryNewCidV0(hash)
}
_, data, err := mbase.Decode(v)
@@ -589,7 +603,7 @@ func PrefixFromBytes(buf []byte) (Prefix, error) {
}
func CidFromBytes(data []byte) (int, Cid, error) {
if len(data) > 2 && data[0] == 18 && data[1] == 32 {
if len(data) > 2 && data[0] == mh.SHA2_256 && data[1] == 32 {
if len(data) < 34 {
return 0, Undef, fmt.Errorf("not enough bytes for cid v0")
}
@@ -599,7 +613,7 @@ func CidFromBytes(data []byte) (int, Cid, error) {
return 0, Undef, err
}
return 34, NewCidV0(h), nil
return 34, Cid{string(h)}, nil
}
vers, n := binary.Uvarint(data)

View File

@@ -584,3 +584,14 @@ func TestReadCidsFromBuffer(t *testing.T) {
t.Fatal("had trailing bytes")
}
}
func TestBadParse(t *testing.T) {
hash, err := mh.Sum([]byte("foobar"), mh.SHA3_256, -1)
if err != nil {
t.Fatal(err)
}
_, err = Parse(hash)
if err == nil {
t.Fatal("expected to fail to parse an invalid CIDv1 CID")
}
}