Compare commits

..

11 Commits

Author SHA1 Message Date
Daniel Martí
c616415150 amend the CidFromReader slice extension math
The append+make slice extension idiom works, but note that append uses
the slice's length as its base. We need to append the number of bytes
required for length to reach cidLength, not the capacity.

The added test case panicked before this change, and works now:

	--- FAIL: TestReadCidsFromBuffer (0.00s)
	panic: runtime error: slice bounds out of range [:73] with capacity 64 [recovered]
		panic: runtime error: slice bounds out of range [:73] with capacity 64

	goroutine 37 [running]:
	testing.tRunner.func1.2({0x570d60, 0xc000016438})
		testing/testing.go:1203 +0x24e
	testing.tRunner.func1()
		testing/testing.go:1206 +0x218
	panic({0x570d60, 0xc000016438})
		runtime/panic.go:1038 +0x215
	github.com/ipfs/go-cid.CidFromReader({0x5b0e20, 0xc000010900})
		github.com/ipfs/go-cid/cid.go:803 +0x75f
	github.com/ipfs/go-cid.TestReadCidsFromBuffer(0xc00014ba00)
		github.com/ipfs/go-cid/cid_test.go:710 +0x625
	testing.tRunner(0xc00014ba00, 0x58af38)
		testing/testing.go:1253 +0x102
	created by testing.(*T).Run
		testing/testing.go:1300 +0x35a
	exit status 2
	FAIL	github.com/ipfs/go-cid	0.004s
2021-07-16 09:47:08 +01:00
Daniel Martí
c4c8760a80 implement CidFromReader
And reuse two CidFromBytes tests for it, which includes both CIDv0 and
CIDv1 cases as inputs, as well as some inputs that should error.

Fixes #126.
2021-07-15 01:01:22 +01:00
Steven Allen
8e9280df3d Merge pull request #118 from ipfs/multihash-update
Update go-multihash.  Now uses registry system.
2021-06-25 17:23:48 -07:00
Eric Myhre
b4bcfe45c9 Update go-multihash.
You can't see it from here, but go-mulithash now uses registry system,
so it's reasonably possible to introduce new hashers, and to use
(some parts of!) go-multihash without bringing in lots of transitive
dependencies.

The main package of go-multihash still brings in everything
transitively that it did before, so go-cid's transitives aren't
shrinking, and no code is changing here... but it's closer.
If we did cut over to the new go-mulithash/core, we could make
many transitive dependencies become optional.
2021-06-25 16:05:47 -07:00
Marten Seemann
979bf3fb85 Merge pull request #125 from ipfs/web3-bot/sync
sync: update CI config files
2021-06-01 12:40:31 -07:00
web3-bot
95ec98a9cc update .github/workflows/go-check.yml 2021-06-01 16:53:30 +00:00
web3-bot
1c23d3b694 update .github/workflows/go-test.yml 2021-06-01 16:53:30 +00:00
web3-bot
5b5d1329c5 update .github/workflows/automerge.yml 2021-06-01 16:53:30 +00:00
web3-bot
a42c04af93 sync: update CI config files (#124) 2021-05-12 15:13:58 +00:00
Steven Allen
0582f6b9b2 Merge pull request #122 from iand/chore/repo-health
chore: fixups from running go vet, go fmt and staticcheck
2021-05-10 08:32:22 -07:00
Ian Davis
0717510dfb chore: fixups from running go vet, go fmt and staticcheck 2021-05-07 15:43:00 +01:00
12 changed files with 402 additions and 172 deletions

51
.github/workflows/automerge.yml vendored Normal file
View File

@@ -0,0 +1,51 @@
# File managed by web3-bot. DO NOT EDIT.
# See https://github.com/protocol/.github/ for details.
# Automatically merge pull requests opened by web3-bot, as soon as (and only if) all tests pass.
# This reduces the friction associated with updating with our workflows.
on: [ pull_request ]
name: Automerge
jobs:
automerge-check:
if: github.event.pull_request.user.login == 'web3-bot'
runs-on: ubuntu-latest
outputs:
status: ${{ steps.should-automerge.outputs.status }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Check if we should automerge
id: should-automerge
run: |
for commit in $(git rev-list --first-parent origin/${{ github.event.pull_request.base.ref }}..${{ github.event.pull_request.head.sha }}); do
committer=$(git show --format=$'%ce' -s $commit)
echo "Committer: $committer"
if [[ "$committer" != "web3-bot@users.noreply.github.com" ]]; then
echo "Commit $commit wasn't committed by web3-bot, but by $committer."
echo "::set-output name=status::false"
exit
fi
done
echo "::set-output name=status::true"
automerge:
needs: automerge-check
runs-on: ubuntu-latest
if: ${{ needs.automerge-check.outputs.status == 'true' }}
steps:
- name: Wait on tests
uses: lewagon/wait-on-check-action@bafe56a6863672c681c3cf671f5e10b20abf2eaa # v0.2
with:
ref: ${{ github.event.pull_request.head.sha }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
running-workflow-name: 'automerge' # the name of this job
- name: Merge PR
uses: pascalgn/automerge-action@741c311a47881be9625932b0a0de1b0937aab1ae # v0.13.1
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
MERGE_LABELS: ""
MERGE_METHOD: "squash"
MERGE_DELETE_BRANCH: true

50
.github/workflows/go-check.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
# File managed by web3-bot. DO NOT EDIT.
# See https://github.com/protocol/.github/ for details.
on: [push, pull_request]
name: Go Checks
jobs:
unit:
runs-on: ubuntu-latest
name: All
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- uses: actions/setup-go@v2
with:
go-version: "1.16.x"
- name: Install staticcheck
run: go install honnef.co/go/tools/cmd/staticcheck@434f5f3816b358fe468fa83dcba62d794e7fe04b # 2021.1 (v0.2.0)
- name: Check that go.mod is tidy
uses: protocol/multiple-go-modules@v1.0
with:
run: |
go mod tidy
if [[ -n $(git ls-files --other --exclude-standard --directory -- go.sum) ]]; then
echo "go.sum was added by go mod tidy"
exit 1
fi
git diff --exit-code -- go.sum go.mod
- name: gofmt
if: ${{ success() || failure() }} # run this step even if the previous one failed
run: |
out=$(gofmt -s -l .)
if [[ -n "$out" ]]; then
echo $out | awk '{print "::error file=" $0 ",line=0,col=0::File is not gofmt-ed."}'
exit 1
fi
- name: go vet
if: ${{ success() || failure() }} # run this step even if the previous one failed
uses: protocol/multiple-go-modules@v1.0
with:
run: go vet ./...
- name: staticcheck
if: ${{ success() || failure() }} # run this step even if the previous one failed
uses: protocol/multiple-go-modules@v1.0
with:
run: |
set -o pipefail
staticcheck ./... | sed -e 's@\(.*\)\.go@./\1.go@g'

47
.github/workflows/go-test.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
# File managed by web3-bot. DO NOT EDIT.
# See https://github.com/protocol/.github/ for details.
on: [push, pull_request]
name: Go Test
jobs:
unit:
strategy:
fail-fast: false
matrix:
os: [ "ubuntu", "windows", "macos" ]
go: [ "1.15.x", "1.16.x" ]
runs-on: ${{ matrix.os }}-latest
name: ${{ matrix.os}} (go ${{ matrix.go }})
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go }}
- name: Go information
run: |
go version
go env
- name: Run tests
uses: protocol/multiple-go-modules@v1.0
with:
run: go test -v -coverprofile coverage.txt ./...
- name: Run tests (32 bit)
if: ${{ matrix.os != 'macos' }} # can't run 32 bit tests on OSX.
uses: protocol/multiple-go-modules@v1.0
env:
GOARCH: 386
with:
run: go test -v ./...
- name: Run tests with race detector
if: ${{ matrix.os == 'ubuntu' }} # speed things up. Windows and OSX VMs are slow
uses: protocol/multiple-go-modules@v1.0
with:
run: go test -v -race ./...
- name: Upload coverage to Codecov
uses: codecov/codecov-action@a1ed4b322b4b38cb846afb5a0ebfa17086917d27 # v1.5.0
with:
file: coverage.txt
env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }}

View File

@@ -1,30 +0,0 @@
os:
- linux
language: go
go:
- 1.11.x
env:
global:
- GOTFLAGS="-race"
matrix:
- BUILD_DEPTYPE=gomod
# disable travis install
install:
- true
script:
- bash <(curl -s https://raw.githubusercontent.com/ipfs/ci-helpers/master/travis-ci/run-standard-tests.sh)
cache:
directories:
- $GOPATH/pkg/mod
- $HOME/.cache/go-build
notifications:
email: false

View File

@@ -88,7 +88,7 @@ if c1.Equals(c2) {
```go ```go
// To check if some data matches a given cid, // To check if some data matches a given cid,
// Get your CIDs prefix, and use that to sum the data in question: // Get your CIDs prefix, and use that to sum the data in question:
other, err := c.Prefix().SumStream(myFile) other, err := c.Prefix().Sum(mydata)
if err != nil {...} if err != nil {...}
if !c.Equals(other) { if !c.Equals(other) {

View File

@@ -1,8 +1,6 @@
package cid package cid
import ( import (
"io"
mh "github.com/multiformats/go-multihash" mh "github.com/multiformats/go-multihash"
) )
@@ -43,14 +41,6 @@ func (p V0Builder) Sum(data []byte) (Cid, error) {
return Cid{string(hash)}, nil return Cid{string(hash)}, nil
} }
func (p V0Builder) SumStream(r io.Reader) (Cid, error) {
hash, err := mh.SumStream(r, mh.SHA2_256, -1)
if err != nil {
return Undef, err
}
return Cid{string(hash)}, nil
}
func (p V0Builder) GetCodec() uint64 { func (p V0Builder) GetCodec() uint64 {
return DagProtobuf return DagProtobuf
} }
@@ -74,18 +64,6 @@ func (p V1Builder) Sum(data []byte) (Cid, error) {
return NewCidV1(p.Codec, hash), nil return NewCidV1(p.Codec, hash), nil
} }
func (p V1Builder) SumStream(r io.Reader) (Cid, error) {
mhLen := p.MhLength
if mhLen <= 0 {
mhLen = -1
}
hash, err := mh.SumStream(r, p.MhType, mhLen)
if err != nil {
return Undef, err
}
return NewCidV1(p.Codec, hash), nil
}
func (p V1Builder) GetCodec() uint64 { func (p V1Builder) GetCodec() uint64 {
return p.Codec return p.Codec
} }

View File

@@ -1,7 +1,6 @@
package cid package cid
import ( import (
"bytes"
"testing" "testing"
mh "github.com/multiformats/go-multihash" mh "github.com/multiformats/go-multihash"
@@ -17,15 +16,6 @@ func TestV0Builder(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
reader := bytes.NewReader(data)
c1a, err := format.SumStream(reader)
if err != nil {
t.Fatal(err)
}
if !c1a.Equals(c1) {
t.Fatal("Sum and SumStream create different cids")
}
// Construct c2 // Construct c2
hash, err := mh.Sum(data, mh.SHA2_256, -1) hash, err := mh.Sum(data, mh.SHA2_256, -1)
if err != nil { if err != nil {
@@ -39,16 +29,6 @@ func TestV0Builder(t *testing.T) {
if c1.Prefix() != c2.Prefix() { if c1.Prefix() != c2.Prefix() {
t.Fatal("prefixes mismatch") t.Fatal("prefixes mismatch")
} }
reader.Seek(0, 0)
hash, err = mh.SumStream(reader, mh.SHA2_256, -1)
if err != nil {
t.Fatal(err)
}
c2 = NewCidV0(hash)
if !c1.Equals(c2) {
t.Fatal("Sum and SumStream create different cids")
}
} }
func TestV1Builder(t *testing.T) { func TestV1Builder(t *testing.T) {
@@ -61,15 +41,6 @@ func TestV1Builder(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
reader := bytes.NewReader(data)
c1a, err := format.SumStream(reader)
if err != nil {
t.Fatal(err)
}
if !c1a.Equals(c1) {
t.Fatal("Sum and SumStream create different cids")
}
// Construct c2 // Construct c2
hash, err := mh.Sum(data, mh.SHA2_256, -1) hash, err := mh.Sum(data, mh.SHA2_256, -1)
if err != nil { if err != nil {

178
cid.go
View File

@@ -185,10 +185,12 @@ func NewCidV1(codecType uint64, mhash mh.Multihash) Cid {
return Cid{string(buf[:n+hashlen])} return Cid{string(buf[:n+hashlen])}
} }
var _ encoding.BinaryMarshaler = Cid{} var (
var _ encoding.BinaryUnmarshaler = (*Cid)(nil) _ encoding.BinaryMarshaler = Cid{}
var _ encoding.TextMarshaler = Cid{} _ encoding.BinaryUnmarshaler = (*Cid)(nil)
var _ encoding.TextUnmarshaler = (*Cid)(nil) _ encoding.TextMarshaler = Cid{}
_ encoding.TextUnmarshaler = (*Cid)(nil)
)
// Cid represents a self-describing content addressed // Cid represents a self-describing content addressed
// identifier. It is formed by a Version, a Codec (which indicates // identifier. It is formed by a Version, a Codec (which indicates
@@ -564,7 +566,7 @@ type Prefix struct {
// and return a newly constructed Cid with the resulting multihash. // and return a newly constructed Cid with the resulting multihash.
func (p Prefix) Sum(data []byte) (Cid, error) { func (p Prefix) Sum(data []byte) (Cid, error) {
length := p.MhLength length := p.MhLength
if p.MhType == mh.ID { if p.MhType == mh.IDENTITY {
length = -1 length = -1
} }
@@ -589,36 +591,6 @@ func (p Prefix) Sum(data []byte) (Cid, error) {
} }
} }
// SumStream uses the information in a prefix, and data read from a io.Reader,
// to perform a multihash.SumStream() and return a newly constructed Cid with
// the resulting multihash.
func (p Prefix) SumStream(r io.Reader) (Cid, error) {
length := p.MhLength
if p.MhType == mh.ID {
length = -1
}
if p.Version == 0 && (p.MhType != mh.SHA2_256 ||
(p.MhLength != 32 && p.MhLength != -1)) {
return Undef, fmt.Errorf("invalid v0 prefix")
}
hash, err := mh.SumStream(r, p.MhType, length)
if err != nil {
return Undef, err
}
switch p.Version {
case 0:
return NewCidV0(hash), nil
case 1:
return NewCidV1(p.Codec, hash), nil
default:
return Undef, fmt.Errorf("invalid cid version")
}
}
// Bytes returns a byte representation of a Prefix. It looks like: // Bytes returns a byte representation of a Prefix. It looks like:
// //
// <version><codec><mh-type><mh-length> // <version><codec><mh-type><mh-length>
@@ -708,3 +680,139 @@ func CidFromBytes(data []byte) (int, Cid, error) {
return l, Cid{string(data[0:l])}, nil return l, Cid{string(data[0:l])}, nil
} }
func toBufByteReader(r io.Reader, dst []byte) *bufByteReader {
// If the reader already implements ByteReader, use it directly.
// Otherwise, use a fallback that does 1-byte Reads.
if br, ok := r.(io.ByteReader); ok {
return &bufByteReader{direct: br, dst: dst}
}
return &bufByteReader{fallback: r, dst: dst}
}
type bufByteReader struct {
direct io.ByteReader
fallback io.Reader
dst []byte
}
func (r *bufByteReader) ReadByte() (byte, error) {
// The underlying reader has ReadByte; use it.
if br := r.direct; br != nil {
b, err := br.ReadByte()
if err != nil {
return 0, err
}
r.dst = append(r.dst, b)
return b, nil
}
// Fall back to a one-byte Read.
// TODO: consider reading straight into dst,
// once we have benchmarks and if they prove that to be faster.
var p [1]byte
if _, err := io.ReadFull(r.fallback, p[:]); err != nil {
return 0, err
}
r.dst = append(r.dst, p[0])
return p[0], nil
}
// CidFromReader reads a precise number of bytes for a CID from a given reader.
// It returns the number of bytes read, the CID, and any error encountered.
// The number of bytes read is accurate even if a non-nil error is returned.
//
// It's recommended to supply a reader that buffers and implements io.ByteReader,
// as CidFromReader has to do many single-byte reads to decode varints.
// If the argument only implements io.Reader, single-byte Read calls are used instead.
func CidFromReader(r io.Reader) (int, Cid, error) {
// 64 bytes is enough for any CIDv0,
// and it's enough for most CIDv1s in practice.
// If the digest is too long, we'll allocate more.
br := toBufByteReader(r, make([]byte, 0, 64))
// We read the first varint, to tell if this is a CIDv0 or a CIDv1.
// The varint package wants a io.ByteReader, so we must wrap our io.Reader.
vers, err := varint.ReadUvarint(br)
if err != nil {
return len(br.dst), Undef, err
}
// If we have a CIDv0, read the rest of the bytes and cast the buffer.
if vers == mh.SHA2_256 {
if n, err := io.ReadFull(r, br.dst[1:34]); err != nil {
return len(br.dst) + n, Undef, err
}
br.dst = br.dst[:34]
h, err := mh.Cast(br.dst)
if err != nil {
return len(br.dst), Undef, err
}
return len(br.dst), Cid{string(h)}, nil
}
if vers != 1 {
return len(br.dst), Undef, fmt.Errorf("expected 1 as the cid version number, got: %d", vers)
}
// CID block encoding multicodec.
_, err = varint.ReadUvarint(br)
if err != nil {
return len(br.dst), Undef, err
}
// We could replace most of the code below with go-multihash's ReadMultihash.
// Note that it would save code, but prevent reusing buffers.
// Plus, we already have a ByteReader now.
mhStart := len(br.dst)
// Multihash hash function code.
_, err = varint.ReadUvarint(br)
if err != nil {
return len(br.dst), Undef, err
}
// Multihash digest length.
mhl, err := varint.ReadUvarint(br)
if err != nil {
return len(br.dst), Undef, err
}
// Refuse to make large allocations to prevent OOMs due to bugs.
const maxDigestAlloc = 32 << 20 // 32MiB
if mhl > maxDigestAlloc {
return len(br.dst), Undef, fmt.Errorf("refusing to allocate %d bytes for a digest", mhl)
}
// Fine to convert mhl to int, given maxDigestAlloc.
prefixLength := len(br.dst)
cidLength := prefixLength + int(mhl)
if cidLength > cap(br.dst) {
// If the multihash digest doesn't fit in our initial 64 bytes,
// efficiently extend the slice via append+make.
br.dst = append(br.dst, make([]byte, cidLength-len(br.dst))...)
} else {
// The multihash digest fits inside our buffer,
// so just extend its capacity.
br.dst = br.dst[:cidLength]
}
if n, err := io.ReadFull(r, br.dst[prefixLength:cidLength]); err != nil {
// We can't use len(br.dst) here,
// as we've only read n bytes past prefixLength.
return prefixLength + n, Undef, err
}
// This simply ensures the multihash is valid.
// TODO: consider removing this bit, as it's probably redundant;
// for now, it helps ensure consistency with CidFromBytes.
_, _, err = mh.MHFromBytes(br.dst[mhStart:])
if err != nil {
return len(br.dst), Undef, err
}
return len(br.dst), Cid{string(br.dst)}, nil
}

View File

@@ -4,7 +4,6 @@ package cid
func Fuzz(data []byte) int { func Fuzz(data []byte) int {
cid, err := Cast(data) cid, err := Cast(data)
if err != nil { if err != nil {
return 0 return 0
} }

View File

@@ -4,10 +4,12 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"math/rand" "math/rand"
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
"testing/iotest"
mbase "github.com/multiformats/go-multibase" mbase "github.com/multiformats/go-multibase"
mh "github.com/multiformats/go-multihash" mh "github.com/multiformats/go-multihash"
@@ -82,7 +84,7 @@ func TestPrefixSum(t *testing.T) {
// Test creating CIDs both manually and with Prefix. // Test creating CIDs both manually and with Prefix.
// Tests: https://github.com/ipfs/go-cid/issues/83 // Tests: https://github.com/ipfs/go-cid/issues/83
for _, hashfun := range []uint64{ for _, hashfun := range []uint64{
mh.ID, mh.SHA3, mh.SHA2_256, mh.IDENTITY, mh.SHA3, mh.SHA2_256,
} { } {
h1, err := mh.Sum([]byte("TEST"), hashfun, -1) h1, err := mh.Sum([]byte("TEST"), hashfun, -1)
if err != nil { if err != nil {
@@ -388,7 +390,6 @@ func TestNewPrefixV0(t *testing.T) {
if c1.Prefix() != c2.Prefix() { if c1.Prefix() != c2.Prefix() {
t.Fatal("prefixes mismatch") t.Fatal("prefixes mismatch")
} }
} }
func TestInvalidV0Prefix(t *testing.T) { func TestInvalidV0Prefix(t *testing.T) {
@@ -512,13 +513,13 @@ func TestParse(t *testing.T) {
} }
assertions := [][]interface{}{ assertions := [][]interface{}{
[]interface{}{NewCidV0(h), theHash}, {NewCidV0(h), theHash},
[]interface{}{NewCidV0(h).Bytes(), theHash}, {NewCidV0(h).Bytes(), theHash},
[]interface{}{h, theHash}, {h, theHash},
[]interface{}{theHash, theHash}, {theHash, theHash},
[]interface{}{"/ipfs/" + theHash, theHash}, {"/ipfs/" + theHash, theHash},
[]interface{}{"https://ipfs.io/ipfs/" + theHash, theHash}, {"https://ipfs.io/ipfs/" + theHash, theHash},
[]interface{}{"http://localhost:8080/ipfs/" + theHash, theHash}, {"http://localhost:8080/ipfs/" + theHash, theHash},
} }
assert := func(arg interface{}, expected string) error { assert := func(arg interface{}, expected string) error {
@@ -666,6 +667,7 @@ func TestReadCidsFromBuffer(t *testing.T) {
"k2cwueckqkibutvhkr4p2ln2pjcaxaakpd9db0e7j7ax1lxhhxy3ekpv", "k2cwueckqkibutvhkr4p2ln2pjcaxaakpd9db0e7j7ax1lxhhxy3ekpv",
"Qmf5Qzp6nGBku7CEn2UQx4mgN8TW69YUok36DrGa6NN893", "Qmf5Qzp6nGBku7CEn2UQx4mgN8TW69YUok36DrGa6NN893",
"zb2rhZi1JR4eNc2jBGaRYJKYM8JEB4ovenym8L1CmFsRAytkz", "zb2rhZi1JR4eNc2jBGaRYJKYM8JEB4ovenym8L1CmFsRAytkz",
"bafkqarjpmzuwyzltorxxezjpkvcfgqkfjfbfcvslivje2vchkzdu6rckjjcfgtkolaze6mssjqzeyn2ekrcfatkjku2vowseky3fswkfkm2deqkrju3e2",
} }
var cids []Cid var cids []Cid
@@ -693,18 +695,59 @@ func TestReadCidsFromBuffer(t *testing.T) {
if cur != len(buf) { if cur != len(buf) {
t.Fatal("had trailing bytes") t.Fatal("had trailing bytes")
} }
// The same, but now with CidFromReader.
// In multiple forms, to catch more io interface bugs.
for _, r := range []io.Reader{
// implements io.ByteReader
bytes.NewReader(buf),
// tiny reads, no io.ByteReader
iotest.OneByteReader(bytes.NewReader(buf)),
} {
cur = 0
for _, expc := range cids {
n, c, err := CidFromReader(r)
if err != nil {
t.Fatal(err)
}
if c != expc {
t.Fatal("cids mismatched")
}
cur += n
}
if cur != len(buf) {
t.Fatal("had trailing bytes")
}
}
} }
func TestBadCidFromBytes(t *testing.T) { func TestBadCidInput(t *testing.T) {
l, c, err := CidFromBytes([]byte{mh.SHA2_256, 32, 0x00}) for _, name := range []string{
if err == nil { "FromBytes",
t.Fatal("expected not-enough-bytes for V0 CidFromBytes") "FromReader",
} {
t.Run(name, func(t *testing.T) {
usingReader := name == "FromReader"
fromBytes := CidFromBytes
if usingReader {
fromBytes = func(data []byte) (int, Cid, error) {
return CidFromReader(bytes.NewReader(data))
} }
if l != 0 { }
t.Fatal("expected length=0 from bad CidFromBytes")
l, c, err := fromBytes([]byte{mh.SHA2_256, 32, 0x00})
if err == nil {
t.Fatal("expected not-enough-bytes for V0 CID")
}
if !usingReader && l != 0 {
t.Fatal("expected length==0 from bad CID")
} else if usingReader && l == 0 {
t.Fatal("expected length!=0 from bad CID")
} }
if c != Undef { if c != Undef {
t.Fatal("expected Undef CID from bad CidFromBytes") t.Fatal("expected Undef CID from bad CID")
} }
c, err = Decode("bafkreie5qrjvaw64n4tjm6hbnm7fnqvcssfed4whsjqxzslbd3jwhsk3mm") c, err = Decode("bafkreie5qrjvaw64n4tjm6hbnm7fnqvcssfed4whsjqxzslbd3jwhsk3mm")
@@ -715,30 +758,36 @@ func TestBadCidFromBytes(t *testing.T) {
copy(byts, c.Bytes()) copy(byts, c.Bytes())
byts[1] = 0x80 // bad codec varint byts[1] = 0x80 // bad codec varint
byts[2] = 0x00 byts[2] = 0x00
l, c, err = CidFromBytes(byts) l, c, err = fromBytes(byts)
if err == nil { if err == nil {
t.Fatal("expected not-enough-bytes for V1 CidFromBytes") t.Fatal("expected not-enough-bytes for V1 CID")
} }
if l != 0 { if !usingReader && l != 0 {
t.Fatal("expected length=0 from bad CidFromBytes") t.Fatal("expected length==0 from bad CID")
} else if usingReader && l == 0 {
t.Fatal("expected length!=0 from bad CID")
} }
if c != Undef { if c != Undef {
t.Fatal("expected Undef CID from bad CidFromBytes") t.Fatal("expected Undef CID from bad CID")
} }
copy(byts, c.Bytes()) copy(byts, c.Bytes())
byts[2] = 0x80 // bad multihash varint byts[2] = 0x80 // bad multihash varint
byts[3] = 0x00 byts[3] = 0x00
l, c, err = CidFromBytes(byts) l, c, err = fromBytes(byts)
if err == nil { if err == nil {
t.Fatal("expected not-enough-bytes for V1 CidFromBytes") t.Fatal("expected not-enough-bytes for V1 CID")
} }
if l != 0 { if !usingReader && l != 0 {
t.Fatal("expected length=0 from bad CidFromBytes") t.Fatal("expected length==0 from bad CID")
} else if usingReader && l == 0 {
t.Fatal("expected length!=0 from bad CID")
} }
if c != Undef { if c != Undef {
t.Fatal("expected Undef CID from bad CidFromBytes") t.Fatal("expected Undef CID from bad CidFromBytes")
} }
})
}
} }
func TestBadParse(t *testing.T) { func TestBadParse(t *testing.T) {

3
go.mod
View File

@@ -2,8 +2,9 @@ module github.com/ipfs/go-cid
require ( require (
github.com/multiformats/go-multibase v0.0.3 github.com/multiformats/go-multibase v0.0.3
github.com/multiformats/go-multihash v0.0.16-0.20210406191223-75ae3688857d github.com/multiformats/go-multihash v0.0.15
github.com/multiformats/go-varint v0.0.6 github.com/multiformats/go-varint v0.0.6
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf // indirect
) )
go 1.15 go 1.15

12
go.sum
View File

@@ -13,17 +13,23 @@ github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ8
github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM=
github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk=
github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc=
github.com/multiformats/go-multihash v0.0.16-0.20210406191223-75ae3688857d h1:xUl/JcLVtafS0n5X8guAExxDS/mJUGoL31p/FlNtC8o= github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM=
github.com/multiformats/go-multihash v0.0.16-0.20210406191223-75ae3688857d/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg=
github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY=
github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf h1:B2n+Zi5QeYRDAEodEu72OS36gmTWjgpXr2+cWcBW90o=
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY=
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=