From 8caa4eef050cf248159a1462122de5bf8de71525 Mon Sep 17 00:00:00 2001 From: Yi Duan Date: Fri, 25 Feb 2022 18:00:57 +0800 Subject: [PATCH] fix: check nil pointer for `Marshaler` (#194) --- encoder/compiler.go | 2 +- issue_test/issue182_test.go | 94 +++++++++++++++++++++++++++++++++++++ issue_test/issue58_test.go | 7 ++- 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 issue_test/issue182_test.go diff --git a/encoder/compiler.go b/encoder/compiler.go index ed79795..a84b658 100644 --- a/encoder/compiler.go +++ b/encoder/compiler.go @@ -839,7 +839,7 @@ func (self *_Compiler) compileMarshaler(p *_Program, op _Op, vt reflect.Type, mt vk := vt.Kind() /* direct receiver */ - if vk != reflect.Ptr || !vt.Elem().Implements(mt) { + if vk != reflect.Ptr { p.rtt(op, vt) return } diff --git a/issue_test/issue182_test.go b/issue_test/issue182_test.go new file mode 100644 index 0000000..984eb5b --- /dev/null +++ b/issue_test/issue182_test.go @@ -0,0 +1,94 @@ +/* +* Copyright 2021 ByteDance Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ + +package issue_test + +import ( + `encoding/json` + `strconv` + `testing` + + `github.com/bytedance/sonic` + `github.com/stretchr/testify/require` +) + +type MarshalerWrap struct { + A *ValueMarshaler + B ValueMarshaler + C *PointerMarshaler + D PointerMarshaler + + E *ValueTextMarshaler + F ValueTextMarshaler + G *PointerTextMarshaler + H PointerTextMarshaler +} + +type ValueMarshaler struct { + X int +} + +func (v ValueMarshaler) MarshalJSON() ([]byte, error) { + return []byte(strconv.Itoa(v.X)), nil +} + +type PointerMarshaler struct { + X int +} + +func (v *PointerMarshaler) MarshalJSON() ([]byte, error) { + return []byte(strconv.Itoa(v.X)), nil +} + +type ValueTextMarshaler struct { + X int +} + +func (v ValueTextMarshaler) MarshalText() ([]byte, error) { + return []byte(strconv.Itoa(v.X)), nil +} + +type PointerTextMarshaler struct { + X int +} + +func (v *PointerTextMarshaler) MarshalText() ([]byte, error) { + return []byte(strconv.Itoa(v.X)), nil +} + +func TestIssue182(t *testing.T) { + v0 := MarshalerWrap{} + ret, err := json.Marshal(v0) + rets, errs := sonic.Marshal(v0) + require.Equal(t, err, errs) + require.Equal(t, string(ret), string(rets)) + ret, err = json.Marshal(&v0) + rets, errs = sonic.Marshal(&v0) + require.Equal(t, err, errs) + require.Equal(t, string(ret), string(rets)) + + v1 := MarshalerWrap{A:&ValueMarshaler{}, C:&PointerMarshaler{}, E: &ValueTextMarshaler{}, G:&PointerTextMarshaler{}} + ret, err = json.Marshal(v1) + rets, errs = sonic.Marshal(v1) + require.Equal(t, err, errs) + require.Equal(t, string(ret), string(rets)) + ret, err = json.Marshal(&v1) + rets, errs = sonic.Marshal(&v1) + require.Equal(t, err, errs) + require.Equal(t, string(ret), string(rets)) +} + + diff --git a/issue_test/issue58_test.go b/issue_test/issue58_test.go index 20ff2b7..7b9e1e6 100644 --- a/issue_test/issue58_test.go +++ b/issue_test/issue58_test.go @@ -19,6 +19,7 @@ package issue_test import ( . `github.com/bytedance/sonic` `testing` + `encoding/json` `github.com/stretchr/testify/require` ) @@ -38,5 +39,9 @@ func TestIssue58_NilPointerOnValueMethod(t *testing.T) { }{} buf, err := Marshal(v) require.NoError(t, err) - require.Equal(t, []byte(`{"X":null,"Y":"pointer"}`), buf) + require.Equal(t, []byte(`{"X":null,"Y":null}`), buf) + buf, err = json.Marshal(v) + require.NoError(t, err) + require.Equal(t, []byte(`{"X":null,"Y":null}`), buf) + }