Skip to content

Commit 628b0f6

Browse files
Jorroposchomatisgammazero
authored
ipld/unixfs/hamt: catch panic in walkChildren (#393)
* ipld/unixfs/hamt: catch panic in walkChildren * Add test for nil link and shard * rename test * Update CHANGELOG.md --------- Co-authored-by: Lucas Molas <[email protected]> Co-authored-by: Andrew Gillis <[email protected]>
1 parent 171b0b7 commit 628b0f6

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ The following emojis are used to highlight certain changes:
2121
### Removed
2222

2323
### Fixed
24+
= `unixfs/hamt` Log error instead of panic if both link and shard are nil [#393](https://github.com/ipfs/boxo/pull/393)
2425

2526
### Security
2627

ipld/unixfs/hamt/hamt.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,19 @@ import (
2929
"os"
3030
"sync"
3131

32-
"golang.org/x/sync/errgroup"
33-
3432
format "github.com/ipfs/boxo/ipld/unixfs"
3533
"github.com/ipfs/boxo/ipld/unixfs/internal"
3634

3735
dag "github.com/ipfs/boxo/ipld/merkledag"
3836
bitfield "github.com/ipfs/go-bitfield"
3937
cid "github.com/ipfs/go-cid"
4038
ipld "github.com/ipfs/go-ipld-format"
39+
logging "github.com/ipfs/go-log/v2"
40+
"golang.org/x/sync/errgroup"
4141
)
4242

43+
var log = logging.Logger("unixfs-hamt")
44+
4345
const (
4446
// HashMurmur3 is the multiformats identifier for Murmur3
4547
HashMurmur3 uint64 = 0x22
@@ -430,8 +432,13 @@ type listCidsAndShards struct {
430432
func (ds *Shard) walkChildren(processLinkValues func(formattedLink *ipld.Link) error) (*listCidsAndShards, error) {
431433
res := &listCidsAndShards{}
432434

433-
for idx, lnk := range ds.childer.links {
434-
if nextShard := ds.childer.children[idx]; nextShard == nil {
435+
for i, nextShard := range ds.childer.children {
436+
if nextShard == nil {
437+
lnk := ds.childer.link(i)
438+
if lnk == nil {
439+
log.Warnf("internal HAMT error: both link and shard nil at pos %d, dumping shard: %+v", i, *ds)
440+
return nil, fmt.Errorf("internal HAMT error: both link and shard nil, check log")
441+
}
435442
lnkLinkType, err := ds.childLinkType(lnk)
436443
if err != nil {
437444
return nil, err
@@ -454,7 +461,6 @@ func (ds *Shard) walkChildren(processLinkValues func(formattedLink *ipld.Link) e
454461
default:
455462
return nil, errors.New("unsupported shard link type")
456463
}
457-
458464
} else {
459465
if nextShard.val != nil {
460466
formattedLink := &ipld.Link{

ipld/unixfs/hamt/hamt_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,3 +749,24 @@ func TestHamtBadSize(t *testing.T) {
749749
}
750750
}
751751
}
752+
753+
func TestHamtNilLinkAndShard(t *testing.T) {
754+
shard, err := NewShard(nil, 1024)
755+
if err != nil {
756+
t.Fatal(err)
757+
}
758+
shard.childer = shard.childer.makeChilder(nil, []*ipld.Link{nil})
759+
nextShard, err := shard.walkChildren(func(_ *ipld.Link) error {
760+
t.Fatal("processLinkValues function should not have been called")
761+
return nil
762+
})
763+
if err == nil {
764+
t.Fatal("expected error")
765+
}
766+
if err.Error() != "internal HAMT error: both link and shard nil, check log" {
767+
t.Fatal("did not get expected error")
768+
}
769+
if nextShard != nil {
770+
t.Fatal("nextShard should be nil")
771+
}
772+
}

0 commit comments

Comments
 (0)