From e464ed39d2c5ea23b07b3e2f425c8d33757f054a Mon Sep 17 00:00:00 2001 From: team-humaki Date: Tue, 15 Sep 2026 12:25:53 -0700 Subject: [PATCH] NewJson: reject trailing data after the first JSON value --- simplejson.go | 16 +++++++++++++--- simplejson_test.go | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/simplejson.go b/simplejson.go index 486fe49..b825585 100644 --- a/simplejson.go +++ b/simplejson.go @@ -1,8 +1,10 @@ package simplejson import ( + "bytes" "encoding/json" "errors" + "io" "log" ) @@ -16,11 +18,19 @@ type Json struct { } // NewJson returns a pointer to a new `Json` object -// after unmarshaling `body` bytes +// after unmarshaling `body` bytes. Extra tokens after the first +// JSON value are rejected (json.Unmarshal would ignore them). func NewJson(body []byte) (*Json, error) { j := new(Json) - err := j.UnmarshalJSON(body) - if err != nil { + dec := json.NewDecoder(bytes.NewBuffer(body)) + dec.UseNumber() + if err := dec.Decode(&j.data); err != nil { + return nil, err + } + if _, err := dec.Token(); err != io.EOF { + if err == nil { + return nil, errors.New("invalid trailing data after JSON value") + } return nil, err } return j, nil diff --git a/simplejson_test.go b/simplejson_test.go index 2ddc89b..242b829 100644 --- a/simplejson_test.go +++ b/simplejson_test.go @@ -341,3 +341,25 @@ func TestPathWillOverwriteExisting(t *testing.T) { t.Errorf("got %#v", s) } } + +func TestNewJsonRejectsTrailingData(t *testing.T) { + // Issue #91: a quoted-prefix + extra tokens used to parse as the string "{". + body := `"{"client_id":"abc123","client_ip":"59.37.125.15","client_version":"1"}"` + js, err := NewJson([]byte(body)) + if err == nil { + t.Fatalf("expected error, got %#v", js.Interface()) + } + + js, err = NewJson([]byte(`{"a":1}{"b":2}`)) + if err == nil { + t.Fatalf("expected error for second JSON value, got %#v", js.Interface()) + } + + js, err = NewJson([]byte("{\"a\":1}\n ")) + if err != nil { + t.Fatalf("trailing whitespace should be ok: %v", err) + } + if v, _ := js.Get("a").Int(); v != 1 { + t.Errorf("got %#v", v) + } +}