Skip to content

Commit 5edcd77

Browse files
committed
chekc that size input to newHamtShard is a power of two
License: MIT Signed-off-by: Jeromy <[email protected]>
1 parent c25778c commit 5edcd77

File tree

4 files changed

+59
-20
lines changed

4 files changed

+59
-20
lines changed

unixfs/hamt/hamt.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,23 +64,31 @@ type child interface {
6464
Label() string
6565
}
6666

67-
func NewHamtShard(dserv dag.DAGService, size int) *HamtShard {
68-
ds := makeHamtShard(dserv, size)
67+
func NewHamtShard(dserv dag.DAGService, size int) (*HamtShard, error) {
68+
ds, err := makeHamtShard(dserv, size)
69+
if err != nil {
70+
return nil, err
71+
}
72+
6973
ds.bitfield = big.NewInt(0)
7074
ds.nd = new(dag.ProtoNode)
7175
ds.hashFunc = HashMurmur3
72-
return ds
76+
return ds, nil
7377
}
7478

75-
func makeHamtShard(ds dag.DAGService, size int) *HamtShard {
79+
func makeHamtShard(ds dag.DAGService, size int) (*HamtShard, error) {
80+
lg2s := int(math.Log2(float64(size)))
81+
if 1<<uint(lg2s) != size {
82+
return nil, fmt.Errorf("hamt size should be a power of two")
83+
}
7684
maxpadding := fmt.Sprintf("%X", size-1)
7785
return &HamtShard{
78-
tableSizeLg2: int(math.Log2(float64(size))),
86+
tableSizeLg2: lg2s,
7987
prefixPadStr: fmt.Sprintf("%%0%dX", len(maxpadding)),
8088
maxpadlen: len(maxpadding),
8189
tableSize: size,
8290
dserv: ds,
83-
}
91+
}, nil
8492
}
8593

8694
func NewHamtFromDag(dserv dag.DAGService, nd node.Node) (*HamtShard, error) {
@@ -102,7 +110,11 @@ func NewHamtFromDag(dserv dag.DAGService, nd node.Node) (*HamtShard, error) {
102110
return nil, fmt.Errorf("only murmur3 supported as hash function")
103111
}
104112

105-
ds := makeHamtShard(dserv, int(pbd.GetFanout()))
113+
ds, err := makeHamtShard(dserv, int(pbd.GetFanout()))
114+
if err != nil {
115+
return nil, err
116+
}
117+
106118
ds.nd = pbnd.Copy().(*dag.ProtoNode)
107119
ds.children = make([]child, len(pbnd.Links()))
108120
ds.bitfield = new(big.Int).SetBytes(pbd.GetData())
@@ -446,13 +458,16 @@ func (ds *HamtShard) modifyValue(ctx context.Context, hv *hashBits, key string,
446458
return nil
447459

448460
default: // replace value with another shard, one level deeper
449-
ns := NewHamtShard(ds.dserv, ds.tableSize)
461+
ns, err := NewHamtShard(ds.dserv, ds.tableSize)
462+
if err != nil {
463+
return err
464+
}
450465
chhv := &hashBits{
451466
b: hash([]byte(child.key)),
452467
consumed: hv.consumed,
453468
}
454469

455-
err := ns.modifyValue(ctx, hv, key, val)
470+
err = ns.modifyValue(ctx, hv, key, val)
456471
if err != nil {
457472
return err
458473
}

unixfs/hamt/hamt_stress_test.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@ func validateOpSetCompletion(t *testing.T, s *HamtShard, keep, temp []string) er
117117

118118
func executeOpSet(t *testing.T, ds dag.DAGService, width int, ops []testOp) (*HamtShard, error) {
119119
ctx := context.TODO()
120-
s := NewHamtShard(ds, width)
120+
s, err := NewHamtShard(ds, width)
121+
if err != nil {
122+
return nil, err
123+
}
124+
121125
e := ft.EmptyDirNode()
122126
ds.Add(e)
123127

@@ -188,7 +192,11 @@ func genOpSet(seed int64, keep, temp []string) []testOp {
188192

189193
// executes the given op set with a repl to allow easier debugging
190194
func debugExecuteOpSet(ds dag.DAGService, width int, ops []testOp) (*HamtShard, error) {
191-
s := NewHamtShard(ds, width)
195+
s, err := NewHamtShard(ds, width)
196+
if err != nil {
197+
return nil, err
198+
}
199+
192200
e := ft.EmptyDirNode()
193201
ds.Add(e)
194202
ctx := context.TODO()
@@ -236,7 +244,11 @@ mainloop:
236244
}
237245
}
238246
case "restart":
239-
s = NewHamtShard(ds, width)
247+
var err error
248+
s, err = NewHamtShard(ds, width)
249+
if err != nil {
250+
panic(err)
251+
}
240252
i = -1
241253
continue mainloop
242254
case "print":

unixfs/hamt/hamt_test.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func makeDir(ds dag.DAGService, size int) ([]string, *HamtShard, error) {
3030
}
3131

3232
func makeDirWidth(ds dag.DAGService, size, width int) ([]string, *HamtShard, error) {
33-
s := NewHamtShard(ds, width)
33+
s, _ := NewHamtShard(ds, width)
3434

3535
var dirs []string
3636
for i := 0; i < size; i++ {
@@ -136,7 +136,7 @@ func TestBasicSet(t *testing.T) {
136136

137137
func TestDirBuilding(t *testing.T) {
138138
ds := mdtest.Mock()
139-
s := NewHamtShard(ds, 256)
139+
s, _ := NewHamtShard(ds, 256)
140140

141141
_, s, err := makeDir(ds, 200)
142142
if err != nil {
@@ -159,7 +159,7 @@ func TestDirBuilding(t *testing.T) {
159159

160160
func TestShardReload(t *testing.T) {
161161
ds := mdtest.Mock()
162-
s := NewHamtShard(ds, 256)
162+
s, _ := NewHamtShard(ds, 256)
163163
ctx := context.Background()
164164

165165
_, s, err := makeDir(ds, 200)
@@ -287,7 +287,7 @@ func TestSetAfterMarshal(t *testing.T) {
287287

288288
func TestDuplicateAddShard(t *testing.T) {
289289
ds := mdtest.Mock()
290-
dir := NewHamtShard(ds, 256)
290+
dir, _ := NewHamtShard(ds, 256)
291291
nd := new(dag.ProtoNode)
292292
ctx := context.Background()
293293

@@ -410,7 +410,7 @@ func TestRemoveElemsAfterMarshal(t *testing.T) {
410410

411411
func TestBitfieldIndexing(t *testing.T) {
412412
ds := mdtest.Mock()
413-
s := NewHamtShard(ds, 256)
413+
s, _ := NewHamtShard(ds, 256)
414414

415415
set := func(i int) {
416416
s.bitfield.SetBit(s.bitfield, i, 1)
@@ -444,7 +444,7 @@ func TestBitfieldIndexing(t *testing.T) {
444444
// itself.
445445
func TestSetHamtChild(t *testing.T) {
446446
ds := mdtest.Mock()
447-
s := NewHamtShard(ds, 256)
447+
s, _ := NewHamtShard(ds, 256)
448448
ctx := context.Background()
449449

450450
e := ft.EmptyDirNode()
@@ -519,7 +519,7 @@ func printDiff(ds dag.DAGService, a, b *dag.ProtoNode) {
519519

520520
func BenchmarkHAMTSet(b *testing.B) {
521521
ds := mdtest.Mock()
522-
sh := NewHamtShard(ds, 256)
522+
sh, _ := NewHamtShard(ds, 256)
523523
nd, err := sh.Node()
524524
if err != nil {
525525
b.Fatal(err)
@@ -550,3 +550,10 @@ func BenchmarkHAMTSet(b *testing.B) {
550550
nd = out
551551
}
552552
}
553+
554+
func TestHamtBadSize(t *testing.T) {
555+
_, err := NewHamtShard(nil, 7)
556+
if err == nil {
557+
t.Fatal("should have failed to construct hamt with bad size")
558+
}
559+
}

unixfs/io/dirbuilder.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,12 @@ func (d *Directory) AddChild(ctx context.Context, name string, nd node.Node) err
8585
}
8686

8787
func (d *Directory) switchToSharding(ctx context.Context) error {
88-
d.shard = hamt.NewHamtShard(d.dserv, DefaultShardWidth)
88+
s, err := hamt.NewHamtShard(d.dserv, DefaultShardWidth)
89+
if err != nil {
90+
return err
91+
}
92+
93+
d.shard = s
8994
for _, lnk := range d.dirnode.Links() {
9095
cnd, err := d.dserv.Get(ctx, lnk.Cid)
9196
if err != nil {

0 commit comments

Comments
 (0)