Skip to content
This repository was archived by the owner on Jun 20, 2023. It is now read-only.

Commit 72733e3

Browse files
authored
Merge pull request #21 from ipfs/fix_rigorous_sizing_checks
Rigorous sizing checks
2 parents 207cdc1 + a144aab commit 72733e3

8 files changed

+87
-95
lines changed

.gx/lastpubver

-1
This file was deleted.

.travis.yml

-4
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,8 @@ go:
99
env:
1010
global:
1111
- GOTFLAGS="-race"
12-
matrix:
13-
- BUILD_DEPTYPE=gx
1412
- BUILD_DEPTYPE=gomod
1513

16-
1714
# disable travis install
1815
install:
1916
- true
@@ -24,7 +21,6 @@ script:
2421

2522
cache:
2623
directories:
27-
- $GOPATH/src/gx
2824
- $GOPATH/pkg/mod
2925
- $HOME/.cache/go-build
3026

Makefile

-18
This file was deleted.

README.md

-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ The package provides a `SizeSplitter` which creates chunks of equal size and it
3131
> go get github.com/ipfs/go-ipfs-chunker
3232
```
3333

34-
It uses [Gx](https://github.com/whyrusleeping/gx) to manage dependencies. You can use `make all` to build it with the `gx` dependencies.
35-
3634
## Usage
3735

3836
```

package.json

-47
This file was deleted.

parse.go

+24-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,20 @@ import (
88
"strings"
99
)
1010

11+
const (
12+
// DefaultBlockSize is the chunk size that splitters produce (or aim to).
13+
DefaultBlockSize int64 = 1024 * 256
14+
15+
// No leaf block should contain more than 1MiB of payload data ( wrapping overhead aside )
16+
// This effectively mandates the maximum chunk size
17+
// See discussion at https://github.com/ipfs/go-ipfs-chunker/pull/21#discussion_r369124879 for background
18+
ChunkSizeLimit int = 1048576
19+
)
20+
1121
var (
1222
ErrRabinMin = errors.New("rabin min must be greater than 16")
13-
ErrSize = errors.New("chunker size muster greater than 0")
23+
ErrSize = errors.New("chunker size must be greater than 0")
24+
ErrSizeMax = fmt.Errorf("chunker parameters may not exceed the maximum chunk size of %d", ChunkSizeLimit)
1425
)
1526

1627
// FromString returns a Splitter depending on the given string:
@@ -28,6 +39,8 @@ func FromString(r io.Reader, chunker string) (Splitter, error) {
2839
return nil, err
2940
} else if size <= 0 {
3041
return nil, ErrSize
42+
} else if size > ChunkSizeLimit {
43+
return nil, ErrSizeMax
3144
}
3245
return NewSizeSplitter(r, int64(size)), nil
3346

@@ -51,6 +64,8 @@ func parseRabinString(r io.Reader, chunker string) (Splitter, error) {
5164
size, err := strconv.Atoi(parts[1])
5265
if err != nil {
5366
return nil, err
67+
} else if int(float32(size)*1.5) > ChunkSizeLimit { // FIXME - this will be addressed in a subsequent PR
68+
return nil, ErrSizeMax
5469
}
5570
return NewRabin(r, uint64(size)), nil
5671
case 4:
@@ -84,6 +99,14 @@ func parseRabinString(r io.Reader, chunker string) (Splitter, error) {
8499
return nil, err
85100
}
86101

102+
if min >= avg {
103+
return nil, errors.New("incorrect format: rabin-min must be smaller than rabin-avg")
104+
} else if avg >= max {
105+
return nil, errors.New("incorrect format: rabin-avg must be smaller than rabin-max")
106+
} else if max > ChunkSizeLimit {
107+
return nil, ErrSizeMax
108+
}
109+
87110
return NewRabinMinMax(r, uint64(min), uint64(avg), uint64(max)), nil
88111
default:
89112
return nil, errors.New("incorrect format (expected 'rabin' 'rabin-[avg]' or 'rabin-[min]-[avg]-[max]'")

parse_test.go

+63-19
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,79 @@ package chunk
22

33
import (
44
"bytes"
5+
"fmt"
56
"testing"
67
)
78

9+
const (
10+
testTwoThirdsOfChunkLimit = 2 * (float32(ChunkSizeLimit) / float32(3))
11+
)
12+
813
func TestParseRabin(t *testing.T) {
9-
max := 1000
10-
r := bytes.NewReader(randBuf(t, max))
11-
chk1 := "rabin-18-25-32"
12-
chk2 := "rabin-15-23-31"
13-
_, err := parseRabinString(r, chk1)
14+
r := bytes.NewReader(randBuf(t, 1000))
15+
16+
_, err := FromString(r, "rabin-18-25-32")
1417
if err != nil {
1518
t.Errorf(err.Error())
1619
}
17-
_, err = parseRabinString(r, chk2)
18-
if err == ErrRabinMin {
19-
t.Log("it should be ErrRabinMin here.")
20+
21+
_, err = FromString(r, "rabin-15-23-31")
22+
if err != ErrRabinMin {
23+
t.Fatalf("Expected an 'ErrRabinMin' error, got: %#v", err)
24+
}
25+
26+
_, err = FromString(r, "rabin-20-20-21")
27+
if err == nil || err.Error() != "incorrect format: rabin-min must be smaller than rabin-avg" {
28+
t.Fatalf("Expected an arg-out-of-order error, got: %#v", err)
29+
}
30+
31+
_, err = FromString(r, "rabin-19-21-21")
32+
if err == nil || err.Error() != "incorrect format: rabin-avg must be smaller than rabin-max" {
33+
t.Fatalf("Expected an arg-out-of-order error, got: %#v", err)
34+
}
35+
36+
_, err = FromString(r, fmt.Sprintf("rabin-19-21-%d", ChunkSizeLimit))
37+
if err != nil {
38+
t.Fatalf("Expected success, got: %#v", err)
39+
}
40+
41+
_, err = FromString(r, fmt.Sprintf("rabin-19-21-%d", 1+ChunkSizeLimit))
42+
if err != ErrSizeMax {
43+
t.Fatalf("Expected 'ErrSizeMax', got: %#v", err)
44+
}
45+
46+
_, err = FromString(r, fmt.Sprintf("rabin-%.0f", testTwoThirdsOfChunkLimit))
47+
if err != nil {
48+
t.Fatalf("Expected success, got: %#v", err)
49+
}
50+
51+
_, err = FromString(r, fmt.Sprintf("rabin-%.0f", 1+testTwoThirdsOfChunkLimit))
52+
if err != ErrSizeMax {
53+
t.Fatalf("Expected 'ErrSizeMax', got: %#v", err)
2054
}
55+
2156
}
2257

2358
func TestParseSize(t *testing.T) {
24-
max := 1000
25-
r := bytes.NewReader(randBuf(t, max))
26-
size1 := "size-0"
27-
size2 := "size-32"
28-
_, err := FromString(r, size1)
29-
if err == ErrSize {
30-
t.Log("it should be ErrSize here.")
31-
}
32-
_, err = FromString(r, size2)
33-
if err == ErrSize {
34-
t.Fatal(err)
59+
r := bytes.NewReader(randBuf(t, 1000))
60+
61+
_, err := FromString(r, "size-0")
62+
if err != ErrSize {
63+
t.Fatalf("Expected an 'ErrSize' error, got: %#v", err)
64+
}
65+
66+
_, err = FromString(r, "size-32")
67+
if err != nil {
68+
t.Fatalf("Expected success, got: %#v", err)
69+
}
70+
71+
_, err = FromString(r, fmt.Sprintf("size-%d", ChunkSizeLimit))
72+
if err != nil {
73+
t.Fatalf("Expected success, got: %#v", err)
74+
}
75+
76+
_, err = FromString(r, fmt.Sprintf("size-%d", 1+ChunkSizeLimit))
77+
if err != ErrSizeMax {
78+
t.Fatalf("Expected 'ErrSizeMax', got: %#v", err)
3579
}
3680
}

splitting.go

-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ import (
1313

1414
var log = logging.Logger("chunk")
1515

16-
// DefaultBlockSize is the chunk size that splitters produce (or aim to).
17-
var DefaultBlockSize int64 = 1024 * 256
18-
1916
// A Splitter reads bytes from a Reader and creates "chunks" (byte slices)
2017
// that can be used to build DAG nodes.
2118
type Splitter interface {

0 commit comments

Comments
 (0)