Skip to content

Commit

Permalink
Revive TestSmallerLengthHashID, and add a special case for identity m…
Browse files Browse the repository at this point in the history
…ultihash that rejects truncations.

See #136 (comment)
for discussion.

This change means Sum behaves slightly differently for identity
multihashes than it does for any other multihash.  I'm not keeping
score on the number of ways identity multihash is weird anymore,
just documenting it and keeping tests passing.

The error message is lifted from the old `sumID` function verbatim.
  • Loading branch information
warpfork committed Mar 10, 2021
1 parent cbd218c commit e0e9752
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 1 deletion.
2 changes: 1 addition & 1 deletion multihash.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ func Decode(buf []byte) (*DecodedMultihash, error) {
// Encode a hash digest along with the specified function code.
// Note: the length is derived from the length of the digest itself.
//
// The error return is legacy; it is always nil.
// The error return is legacy; it is always nil.1
func Encode(buf []byte, code uint64) ([]byte, error) {
// FUTURE: this function always causes heap allocs... but when used, this value is almost always going to be appended to another buffer (either as part of CID creation, or etc) -- should this whole function be rethought and alternatives offered?
newBuf := make([]byte, varint.UvarintSize(code)+varint.UvarintSize(uint64(len(buf)))+len(buf))
Expand Down
7 changes: 7 additions & 0 deletions sum.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package multihash

import (
"errors"
"fmt"
)

// ErrSumNotSupported is returned when the Sum function code is not implemented
Expand All @@ -27,13 +28,19 @@ func Sum(data []byte, code uint64, length int) (Multihash, error) {
sum := hasher.Sum(nil)

// Deal with any truncation.
// Unless it's an identity multihash. Those have different rules.
if length < 0 {
length = hasher.Size()
}
if len(sum) < length {
return nil, ErrLenTooLarge
}
if length >= 0 {
if code == IDENTITY {
if length != len(sum) {
return nil, fmt.Errorf("the length of the identity hash (%d) must be equal to the length of the data (%d)", length, len(sum))
}
}
sum = sum[:length]
}

Expand Down
27 changes: 27 additions & 0 deletions sum_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,33 @@ func BenchmarkBlake2B(b *testing.B) {
}
}

func TestSmallerLengthHashID(t *testing.T) {

data := []byte("Identity hash input data.")
dataLength := len(data)

// Normal case: `length == len(data)`.
_, err := multihash.Sum(data, multihash.ID, dataLength)
if err != nil {
t.Fatal(err)
}

// Unconstrained length (-1): also allowed.
_, err = multihash.Sum(data, multihash.ID, -1)
if err != nil {
t.Fatal(err)
}

// Any other variation of those two scenarios should fail.
for l := (dataLength - 1); l >= 0; l-- {
_, err = multihash.Sum(data, multihash.ID, l)
if err == nil {
t.Fatal(fmt.Sprintf("identity hash of length %d smaller than data length %d didn't fail",
l, dataLength))
}
}
}

func TestTooLargeLength(t *testing.T) {
_, err := multihash.Sum([]byte("test"), multihash.SHA2_256, 33)
if err != multihash.ErrLenTooLarge {
Expand Down

0 comments on commit e0e9752

Please sign in to comment.