From 563f4f606ffef4df8e21461821e2364a73776833 Mon Sep 17 00:00:00 2001 From: demoManito <1430482733@qq.com> Date: Wed, 29 May 2024 19:26:56 +0800 Subject: [PATCH] feat(binding/json): check validity when bind json Signed-off-by: demoManito <1430482733@qq.com> --- binding/json.go | 16 +++++++++++++++- binding/json_test.go | 22 ++++++++++++++++++++++ internal/json/go_json.go | 4 +++- internal/json/json.go | 2 ++ internal/json/jsoniter.go | 2 ++ internal/json/sonic.go | 2 ++ 6 files changed, 46 insertions(+), 2 deletions(-) diff --git a/binding/json.go b/binding/json.go index e21c2ee3..35037fb2 100644 --- a/binding/json.go +++ b/binding/json.go @@ -13,6 +13,11 @@ import ( "github.com/gin-gonic/gin/internal/json" ) +var ( + // ErrInvalidJSON invalid json + ErrInvalidJSON = errors.New("invalid JSON") +) + // EnableDecoderUseNumber is used to call the UseNumber method on the JSON // Decoder instance. UseNumber causes the Decoder to unmarshal a number into an // any as a Number instead of as a float64. @@ -34,10 +39,19 @@ func (jsonBinding) Bind(req *http.Request, obj any) error { if req == nil || req.Body == nil { return errors.New("invalid request") } - return decodeJSON(req.Body, obj) + body, _ := io.ReadAll(req.Body) + ok := json.Valid(body) + if !ok { + return ErrInvalidJSON + } + return decodeJSON(bytes.NewReader(body), obj) } func (jsonBinding) BindBody(body []byte, obj any) error { + ok := json.Valid(body) + if !ok { + return ErrInvalidJSON + } return decodeJSON(bytes.NewReader(body), obj) } diff --git a/binding/json_test.go b/binding/json_test.go index fbd5c527..cb175eff 100644 --- a/binding/json_test.go +++ b/binding/json_test.go @@ -5,6 +5,8 @@ package binding import ( + "bytes" + "net/http" "testing" "github.com/stretchr/testify/assert" @@ -18,6 +20,9 @@ func TestJSONBindingBindBody(t *testing.T) { err := jsonBinding{}.BindBody([]byte(`{"foo": "FOO"}`), &s) require.NoError(t, err) assert.Equal(t, "FOO", s.Foo) + + err = jsonBinding{}.BindBody([]byte(`{"foo": "FOO}`), &s) + assert.Equal(t, ErrInvalidJSON, err) } func TestJSONBindingBindBodyMap(t *testing.T) { @@ -27,4 +32,21 @@ func TestJSONBindingBindBodyMap(t *testing.T) { assert.Len(t, s, 2) assert.Equal(t, "FOO", s["foo"]) assert.Equal(t, "world", s["hello"]) + + err = jsonBinding{}.BindBody([]byte(`{"foo": "FOO","hello":"world}`), &s) + assert.Equal(t, ErrInvalidJSON, err) +} + +func TestTestJSONBindingBind(t *testing.T) { + var s struct { + Foo string `json:"foo"` + } + req, _ := http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(`{"foo":"FOO"}`)) + err := jsonBinding{}.Bind(req, &s) + require.NoError(t, err) + assert.Equal(t, "FOO", s.Foo) + + req, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(`{"foo":"FOO}`)) + err = jsonBinding{}.Bind(req, &s) + assert.Equal(t, ErrInvalidJSON, err) } diff --git a/internal/json/go_json.go b/internal/json/go_json.go index 47c35598..308ba06d 100644 --- a/internal/json/go_json.go +++ b/internal/json/go_json.go @@ -6,7 +6,7 @@ package json -import json "github.com/goccy/go-json" +import "github.com/goccy/go-json" var ( // Marshal is exported by gin/json package. @@ -19,4 +19,6 @@ var ( NewDecoder = json.NewDecoder // NewEncoder is exported by gin/json package. NewEncoder = json.NewEncoder + // Valid is exported by gin/json package. + Valid = json.Valid ) diff --git a/internal/json/json.go b/internal/json/json.go index c7ee83eb..53bedccc 100644 --- a/internal/json/json.go +++ b/internal/json/json.go @@ -19,4 +19,6 @@ var ( NewDecoder = json.NewDecoder // NewEncoder is exported by gin/json package. NewEncoder = json.NewEncoder + // Valid is exported by gin/json package. + Valid = json.Valid ) diff --git a/internal/json/jsoniter.go b/internal/json/jsoniter.go index 45ed16ba..c8aa69f5 100644 --- a/internal/json/jsoniter.go +++ b/internal/json/jsoniter.go @@ -20,4 +20,6 @@ var ( NewDecoder = json.NewDecoder // NewEncoder is exported by gin/json package. NewEncoder = json.NewEncoder + // Valid is exported by gin/json package. + Valid = json.Valid ) diff --git a/internal/json/sonic.go b/internal/json/sonic.go index 529e16d0..db9e954e 100644 --- a/internal/json/sonic.go +++ b/internal/json/sonic.go @@ -20,4 +20,6 @@ var ( NewDecoder = json.NewDecoder // NewEncoder is exported by gin/json package. NewEncoder = json.NewEncoder + // Valid is exported by gin/json package. + Valid = json.Valid )