2
0
Fork 0
mirror of https://github.com/ii64/sonic.git synced 2026-06-21 00:46:43 +08:00

fix: fix nil pointer on value receiver (#58)

This commit is contained in:
chenzhuoyu 2021-07-28 16:51:07 +08:00 committed by Oxygen
parent e88411dafe
commit c2ea100389
2 changed files with 63 additions and 2 deletions

View file

@ -416,7 +416,7 @@ func (self *_Compiler) compileRec(p *_Program, sp int, vt reflect.Type, pv bool)
/* check for `json.Marshaler` */
if vt.Implements(jsonMarshalerType) {
p.rtt(_OP_marshal, vt)
self.compileMarshaler(p, _OP_marshal, vt, jsonMarshalerType)
return
}
@ -428,7 +428,7 @@ func (self *_Compiler) compileRec(p *_Program, sp int, vt reflect.Type, pv bool)
/* check for `encoding.TextMarshaler` */
if vt.Implements(encodingTextMarshalerType) {
p.rtt(_OP_marshal_text, vt)
self.compileMarshaler(p, _OP_marshal_text, vt, encodingTextMarshalerType)
return
}
@ -820,3 +820,23 @@ func (self *_Compiler) compileInterface(p *_Program, vt reflect.Type) {
p.add(_OP_null)
p.pin(e)
}
func (self *_Compiler) compileMarshaler(p *_Program, op _Op, vt reflect.Type, mt reflect.Type) {
pc := p.pc()
vk := vt.Kind()
/* direct receiver */
if vk != reflect.Ptr || !vt.Elem().Implements(mt) {
p.rtt(op, vt)
return
}
/* value receiver with a pointer type, check for nil before calling the marshaler */
p.add(_OP_is_nil)
p.rtt(op, vt)
i := p.pc()
p.add(_OP_goto)
p.pin(pc)
p.add(_OP_null)
p.pin(i)
}

41
issue58_test.go Normal file
View file

@ -0,0 +1,41 @@
/*
* 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 sonic
import (
`testing`
`github.com/stretchr/testify/require`
)
type (
Issue58ValueReceiver struct {}
Issue58PointerReceiver struct {}
)
func (_ Issue58ValueReceiver) MarshalJSON() ([]byte, error) { return []byte(`"value"`), nil }
func (_ *Issue58PointerReceiver) MarshalJSON() ([]byte, error) { return []byte(`"pointer"`), nil }
func TestIssue58_NilPointerOnValueMethod(t *testing.T) {
v := struct {
X *Issue58ValueReceiver
Y *Issue58PointerReceiver
}{}
buf, err := Marshal(v)
require.NoError(t, err)
require.Equal(t, []byte(`{"X":null,"Y":"pointer"}`), buf)
}