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

Commit acbc078

Browse files
committed
[#1800] Make ipfs.getFromDatastore IpnsEntry unmarshal fail gracefully
If any record is returned that fails to unmarshal into an pb.IpnsEntry, the error bubbles all the way up without properly checking the alternative key prefixes.
1 parent ace85ca commit acbc078

File tree

1 file changed

+27
-14
lines changed

1 file changed

+27
-14
lines changed

ipfs/resolve.go

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package ipfs
22

33
import (
44
"context"
5+
"fmt"
6+
"runtime/debug"
57
"time"
68

79
ipath "gx/ipfs/QmQAgv6Gaoe2tQpcabqwKXKChp2MZ7i3UXv9DqTTaxCaTR/go-path"
@@ -99,30 +101,41 @@ func ResolveAltRoot(n *core.IpfsNode, p peer.ID, altRoot string, timeout time.Du
99101
// under /ipns/persistentcache/<peerID> which returns only the value (the path)
100102
// inside the protobuf record.
101103
func getFromDatastore(datastore ds.Datastore, p peer.ID) (ipath.Path, error) {
102-
ival, err := datastore.Get(nativeIPNSRecordCacheKey(p))
103-
if err != nil {
104-
pth, err := datastore.Get(persistentCacheKey(p))
105-
if err != nil {
106-
if err == ds.ErrNotFound {
107-
return "", namesys.ErrResolveFailed
108-
}
109-
return "", err
110-
}
111-
return ipath.ParsePath(string(pth))
104+
rec, err := getCachedIPNSRecord(datastore, p)
105+
if err == nil {
106+
return ipath.ParsePath(string(rec.Value))
112107
}
113108

114-
rec := new(ipnspb.IpnsEntry)
115-
err = proto.Unmarshal(ival, rec)
109+
pth, err := datastore.Get(persistentCacheKey(p))
116110
if err != nil {
117-
return "", err
111+
if err == ds.ErrNotFound {
112+
return "", namesys.ErrResolveFailed
113+
}
114+
return "", fmt.Errorf("getting cached ipns path: %s", err.Error())
118115
}
119-
return ipath.ParsePath(string(rec.Value))
116+
return ipath.ParsePath(string(pth))
120117
}
121118

122119
func putToDatastoreCache(datastore ds.Datastore, p peer.ID, pth ipath.Path) error {
123120
return datastore.Put(persistentCacheKey(p), []byte(pth.String()))
124121
}
125122

123+
// getCachedIPNSRecord retrieves the full IPNSEntry from the provided datastore if present
124+
func getCachedIPNSRecord(store ds.Datastore, id peer.ID) (*ipnspb.IpnsEntry, error) {
125+
ival, err := store.Get(nativeIPNSRecordCacheKey(id))
126+
if err != nil {
127+
return nil, fmt.Errorf("getting cached ipns record: %s", err.Error())
128+
}
129+
rec := new(ipnspb.IpnsEntry)
130+
err = proto.Unmarshal(ival, rec)
131+
if err != nil {
132+
log.Errorf("failed parsing cached record for peer (%s): %s", id.Pretty(), err.Error())
133+
log.Debug(debug.Stack())
134+
return nil, fmt.Errorf("parsing cached ipns record: %s", err.Error())
135+
}
136+
return rec, nil
137+
}
138+
126139
// PutCachedPubkey persists the pubkey using the appropriate key prefix
127140
// from the provided datastore
128141
func PutCachedPubkey(store ds.Datastore, peerID string, pubkey []byte) error {

0 commit comments

Comments
 (0)