From eb767edcf733e793e27ecd18f00bc17ec0a09b46 Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Tue, 24 May 2022 20:45:29 +1000 Subject: [PATCH] fix(codecs): coerce cid.Undef to null in dag{json,cbor} output Otherwise we end up with invalid output. dag-cbor: 0xd82a4100 d8 2a # tag(42) 41 # bytes(1) 00 # "\x00" dag-json: {"/":"b"} Fixes: https://github.com/ipld/go-ipld-prime/issues/246 --- codec/dagcbor/marshal.go | 3 +++ codec/dagcbor/marshal_test.go | 16 ++++++++++++++++ codec/dagjson/marshal.go | 3 +++ codec/dagjson/marshal_test.go | 25 +++++++++++++++++++++++++ 4 files changed, 47 insertions(+) create mode 100644 codec/dagjson/marshal_test.go diff --git a/codec/dagcbor/marshal.go b/codec/dagcbor/marshal.go index 6798d050..608f8a3e 100644 --- a/codec/dagcbor/marshal.go +++ b/codec/dagcbor/marshal.go @@ -144,6 +144,9 @@ func marshal(n datamodel.Node, tk *tok.Token, sink shared.TokenSink, options Enc } switch lnk := v.(type) { case cidlink.Link: + if !lnk.Cid.Defined() { + return fmt.Errorf("encoding undefined CIDs are not supported by this codec") + } tk.Type = tok.TBytes tk.Bytes = append([]byte{0}, lnk.Bytes()...) tk.Tagged = true diff --git a/codec/dagcbor/marshal_test.go b/codec/dagcbor/marshal_test.go index 50eacf6c..7fc87f6b 100644 --- a/codec/dagcbor/marshal_test.go +++ b/codec/dagcbor/marshal_test.go @@ -7,7 +7,11 @@ import ( "time" qt "github.com/frankban/quicktest" + "github.com/ipfs/go-cid" + "github.com/ipld/go-ipld-prime" "github.com/ipld/go-ipld-prime/datamodel" + "github.com/ipld/go-ipld-prime/fluent/qp" + cidlink "github.com/ipld/go-ipld-prime/linking/cid" basicnode "github.com/ipld/go-ipld-prime/node/basic" "github.com/ipld/go-ipld-prime/testutil/garbage" ) @@ -68,3 +72,15 @@ func TestEncodedLength(t *testing.T) { } }) } + +func TestMarshalUndefCid(t *testing.T) { + link, err := cid.Decode("bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi") + qt.Assert(t, err, qt.IsNil) + node, err := qp.BuildMap(basicnode.Prototype.Any, -1, func(ma datamodel.MapAssembler) { + qp.MapEntry(ma, "UndefCid", qp.Link(cidlink.Link{Cid: cid.Undef})) + qp.MapEntry(ma, "DefCid", qp.Link(cidlink.Link{Cid: link})) + }) + qt.Assert(t, err, qt.IsNil) + _, err = ipld.Encode(node, Encode) + qt.Assert(t, err, qt.ErrorMatches, "encoding undefined CIDs are not supported by this codec") +} diff --git a/codec/dagjson/marshal.go b/codec/dagjson/marshal.go index de894c4a..8e1bba2a 100644 --- a/codec/dagjson/marshal.go +++ b/codec/dagjson/marshal.go @@ -257,6 +257,9 @@ func Marshal(n datamodel.Node, sink shared.TokenSink, options EncodeOptions) err } switch lnk := v.(type) { case cidlink.Link: + if !lnk.Cid.Defined() { + return fmt.Errorf("encoding undefined CIDs are not supported by this codec") + } // Precisely four tokens to emit: tk.Type = tok.TMapOpen tk.Length = 1 diff --git a/codec/dagjson/marshal_test.go b/codec/dagjson/marshal_test.go new file mode 100644 index 00000000..542d2986 --- /dev/null +++ b/codec/dagjson/marshal_test.go @@ -0,0 +1,25 @@ +package dagjson + +import ( + "testing" + + qt "github.com/frankban/quicktest" + cid "github.com/ipfs/go-cid" + "github.com/ipld/go-ipld-prime" + "github.com/ipld/go-ipld-prime/datamodel" + "github.com/ipld/go-ipld-prime/fluent/qp" + cidlink "github.com/ipld/go-ipld-prime/linking/cid" + "github.com/ipld/go-ipld-prime/node/basicnode" +) + +func TestMarshalUndefCid(t *testing.T) { + link, err := cid.Decode("bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi") + qt.Assert(t, err, qt.IsNil) + node, err := qp.BuildMap(basicnode.Prototype.Any, -1, func(ma datamodel.MapAssembler) { + qp.MapEntry(ma, "UndefCid", qp.Link(cidlink.Link{Cid: cid.Undef})) + qp.MapEntry(ma, "DefCid", qp.Link(cidlink.Link{Cid: link})) + }) + qt.Assert(t, err, qt.IsNil) + _, err = ipld.Encode(node, Encode) + qt.Assert(t, err, qt.ErrorMatches, "encoding undefined CIDs are not supported by this codec") +}