From 6b19ca8b0ba9c694c7ce74e96a8a9f3e41fe8156 Mon Sep 17 00:00:00 2001 From: Petar Maymounkov Date: Thu, 26 May 2022 12:05:56 -0700 Subject: [PATCH 1/4] add option to not parse beyond end of structure --- codec/dagjson/unmarshal.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/codec/dagjson/unmarshal.go b/codec/dagjson/unmarshal.go index 637aa3a7..6bc05b83 100644 --- a/codec/dagjson/unmarshal.go +++ b/codec/dagjson/unmarshal.go @@ -32,6 +32,10 @@ type DecodeOptions struct { // If true, parse DAG-JSON `{"/":{"bytes":"base64 bytes..."}}` as a Bytes kind // node rather than nested plain maps ParseBytes bool + + // If true, the decoder stops reading from the stream at the end of the JSON structure. + // I.e. it does not slurp remaining whitespaces and EOF. + DontParseBeyondEnd bool } // Decode deserializes data from the given io.Reader and feeds it into the given datamodel.NodeAssembler. @@ -43,6 +47,9 @@ func (cfg DecodeOptions) Decode(na datamodel.NodeAssembler, r io.Reader) error { if err != nil { return err } + if cfg.DontParseBeyondEnd { + return nil + } // Slurp any remaining whitespace. // This behavior may be due for review. // (This is relevant if our reader is tee'ing bytes to a hasher, and From d7f1bd2f6330d1fe218d7863a75ac83f20dbc352 Mon Sep 17 00:00:00 2001 From: Petar Maymounkov Date: Tue, 7 Jun 2022 08:23:02 -0700 Subject: [PATCH 2/4] add test --- codec/dagjson/nongreedy_test.go | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 codec/dagjson/nongreedy_test.go diff --git a/codec/dagjson/nongreedy_test.go b/codec/dagjson/nongreedy_test.go new file mode 100644 index 00000000..892bcd5d --- /dev/null +++ b/codec/dagjson/nongreedy_test.go @@ -0,0 +1,36 @@ +package dagjson + +import ( + "bytes" + "testing" + + "github.com/ipld/go-ipld-prime/datamodel" + "github.com/ipld/go-ipld-prime/node/basicnode" +) + +func TestNonGreedy(t *testing.T) { + buf := bytes.NewBufferString(`{"a": 1}{"b": 2}`) + opts := DecodeOptions{ + ParseLinks: false, + ParseBytes: false, + DontParseBeyondEnd: true, + } + nb1 := basicnode.Prototype.Map.NewBuilder() + err := opts.Decode(nb1, buf) + if err != nil { + t.Fatalf("first decode (%v)", err) + } + n1 := nb1.Build() + if n1.Kind() != datamodel.Kind_Map { + t.Errorf("expecting a map") + } + nb2 := basicnode.Prototype.Map.NewBuilder() + err = opts.Decode(nb2, buf) + if err != nil { + t.Fatalf("second decode (%v)", err) + } + n2 := nb2.Build() + if n2.Kind() != datamodel.Kind_Map { + t.Errorf("expecting a map") + } +} From 9ec03893a1f106cd3d02d4a7f08503f96ca7186e Mon Sep 17 00:00:00 2001 From: Petar Maymounkov Date: Tue, 7 Jun 2022 08:25:36 -0700 Subject: [PATCH 3/4] comment --- codec/dagjson/unmarshal.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/codec/dagjson/unmarshal.go b/codec/dagjson/unmarshal.go index 6bc05b83..b51f4dac 100644 --- a/codec/dagjson/unmarshal.go +++ b/codec/dagjson/unmarshal.go @@ -34,7 +34,10 @@ type DecodeOptions struct { ParseBytes bool // If true, the decoder stops reading from the stream at the end of the JSON structure. - // I.e. it does not slurp remaining whitespaces and EOF. + // i.e. it does not slurp remaining whitespaces and EOF. + // As per standard IPLD behavior, the parser considers the entire block to be + // part of the JSON structure and will error if there is extraneous + // non-whitespace data. DontParseBeyondEnd bool } From f0c1fdf6c6adf23988529c143019f71242eafd0e Mon Sep 17 00:00:00 2001 From: Petar Maymounkov Date: Tue, 7 Jun 2022 09:01:21 -0700 Subject: [PATCH 4/4] add to test --- codec/dagjson/nongreedy_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/codec/dagjson/nongreedy_test.go b/codec/dagjson/nongreedy_test.go index 892bcd5d..b6b03a4f 100644 --- a/codec/dagjson/nongreedy_test.go +++ b/codec/dagjson/nongreedy_test.go @@ -24,6 +24,9 @@ func TestNonGreedy(t *testing.T) { if n1.Kind() != datamodel.Kind_Map { t.Errorf("expecting a map") } + if _, err := n1.LookupByString("a"); err != nil { + t.Fatalf("missing fist key") + } nb2 := basicnode.Prototype.Map.NewBuilder() err = opts.Decode(nb2, buf) if err != nil { @@ -33,4 +36,7 @@ func TestNonGreedy(t *testing.T) { if n2.Kind() != datamodel.Kind_Map { t.Errorf("expecting a map") } + if _, err := n2.LookupByString("b"); err != nil { + t.Fatalf("missing second key") + } }