From 2ea7ab6e2481d5cb91a8ec72855db3e28345d0ce Mon Sep 17 00:00:00 2001 From: Nao Yonashiro Date: Wed, 4 May 2022 23:40:12 +0900 Subject: [PATCH 01/11] fix: wrong the detection method of nilable fix #339 --- encode_test.go | 18 ++++++++++++++++++ internal/encoder/compiler.go | 3 +++ 2 files changed, 21 insertions(+) diff --git a/encode_test.go b/encode_test.go index 92f4304..59bb08f 100644 --- a/encode_test.go +++ b/encode_test.go @@ -9,6 +9,7 @@ import ( "fmt" "log" "math" + "math/big" "reflect" "regexp" "strconv" @@ -2388,3 +2389,20 @@ func TestIssue324(t *testing.T) { t.Fatalf("failed to encode. expected %q but got %q", expected, got) } } + +func TestIssue339(t *testing.T) { + type T1 struct { + *big.Int + } + type T2 struct { + T1 T1 `json:"T1"` + } + v := T2{T1{Int: big.NewInt(10000)}} + b, err := json.Marshal(&v) + assertErr(t, err) + got := string(b) + expected := `{"T1":10000}` + if got != expected { + t.Errorf("unexpected result: %v != %v", got, expected) + } +} diff --git a/internal/encoder/compiler.go b/internal/encoder/compiler.go index 1be01aa..de7323c 100644 --- a/internal/encoder/compiler.go +++ b/internal/encoder/compiler.go @@ -853,6 +853,9 @@ func (c *Compiler) implementsMarshalText(typ *runtime.Type) bool { } func (c *Compiler) isNilableType(typ *runtime.Type) bool { + if !runtime.IfaceIndir(typ) { + return true + } switch typ.Kind() { case reflect.Ptr: return true From 27bd0f2aab2965c8940fd78d1f0c7ca5b91f4d85 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Thu, 30 Jun 2022 02:38:52 +0900 Subject: [PATCH 02/11] Update CHANGELOG --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c4a94f..6e4b93f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +# v0.9.8 - 2022/06/30 + +### Fix bugs + +* Fix decoding of surrogate-pair ( #365 ) +* Fix handling of embedded primitive type ( #366 ) +* Add validation of escape sequence for decoder ( #367 ) +* Fix stream tokenizing respecting UseNumber ( #369 ) +* Fix encoding when struct pointer type that implements Marshal JSON is embedded ( #375 ) + +### Improve performance + +* Improve performance of linkRecursiveCode ( #368 ) + # v0.9.7 - 2022/04/22 ### Fix bugs From c8d6da88dd5e417e57d7125bb805874f78496fcd Mon Sep 17 00:00:00 2001 From: Nao Yonashiro Date: Sun, 3 Jul 2022 06:05:26 +0900 Subject: [PATCH 03/11] fix: confusing nil in direct interface with typed nil fix #376 --- encode_test.go | 18 ++++++++++++++++++ internal/cmd/generator/vm.go.tmpl | 4 +++- internal/encoder/vm/vm.go | 4 +++- internal/encoder/vm_color/vm.go | 4 +++- internal/encoder/vm_color_indent/vm.go | 4 +++- internal/encoder/vm_indent/vm.go | 4 +++- 6 files changed, 33 insertions(+), 5 deletions(-) diff --git a/encode_test.go b/encode_test.go index 59bb08f..1c0de3c 100644 --- a/encode_test.go +++ b/encode_test.go @@ -2406,3 +2406,21 @@ func TestIssue339(t *testing.T) { t.Errorf("unexpected result: %v != %v", got, expected) } } + +func TestIssue376(t *testing.T) { + type Container struct { + V interface{} `json:"value"` + } + type MapOnly struct { + Map map[string]int64 `json:"map"` + } + b, err := json.Marshal(Container{MapOnly{}}) + if err != nil { + t.Fatal(err) + } + got := string(b) + expected := `{"value":{"map":null}}` + if got != expected { + t.Errorf("unexpected result: %v != %v", got, expected) + } +} diff --git a/internal/cmd/generator/vm.go.tmpl b/internal/cmd/generator/vm.go.tmpl index 91b11e1..cb4db57 100644 --- a/internal/cmd/generator/vm.go.tmpl +++ b/internal/cmd/generator/vm.go.tmpl @@ -3,6 +3,7 @@ package vm import ( "math" + "reflect" "sort" "unsafe" @@ -193,7 +194,8 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if ifacePtr == nil && !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break diff --git a/internal/encoder/vm/vm.go b/internal/encoder/vm/vm.go index 91b11e1..cb4db57 100644 --- a/internal/encoder/vm/vm.go +++ b/internal/encoder/vm/vm.go @@ -3,6 +3,7 @@ package vm import ( "math" + "reflect" "sort" "unsafe" @@ -193,7 +194,8 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if ifacePtr == nil && !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break diff --git a/internal/encoder/vm_color/vm.go b/internal/encoder/vm_color/vm.go index 5c6c52c..e8a5597 100644 --- a/internal/encoder/vm_color/vm.go +++ b/internal/encoder/vm_color/vm.go @@ -3,6 +3,7 @@ package vm_color import ( "math" + "reflect" "sort" "unsafe" @@ -193,7 +194,8 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if ifacePtr == nil && !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break diff --git a/internal/encoder/vm_color_indent/vm.go b/internal/encoder/vm_color_indent/vm.go index 42dc11c..79cfdd8 100644 --- a/internal/encoder/vm_color_indent/vm.go +++ b/internal/encoder/vm_color_indent/vm.go @@ -3,6 +3,7 @@ package vm_color_indent import ( "math" + "reflect" "sort" "unsafe" @@ -193,7 +194,8 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if ifacePtr == nil && !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break diff --git a/internal/encoder/vm_indent/vm.go b/internal/encoder/vm_indent/vm.go index dfe0cc6..5451484 100644 --- a/internal/encoder/vm_indent/vm.go +++ b/internal/encoder/vm_indent/vm.go @@ -3,6 +3,7 @@ package vm_indent import ( "math" + "reflect" "sort" "unsafe" @@ -193,7 +194,8 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if ifacePtr == nil && !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break From 884b8dbf9ac90370b4df41d1b3cba565dc602078 Mon Sep 17 00:00:00 2001 From: Nao Yonashiro Date: Sun, 3 Jul 2022 22:39:31 +0900 Subject: [PATCH 04/11] refactor: to check for IsDirectedNil only if ifacePtr == nil --- internal/cmd/generator/vm.go.tmpl | 12 +++++++----- internal/encoder/vm/vm.go | 12 +++++++----- internal/encoder/vm_color/vm.go | 12 +++++++----- internal/encoder/vm_color_indent/vm.go | 12 +++++++----- internal/encoder/vm_indent/vm.go | 12 +++++++----- 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/internal/cmd/generator/vm.go.tmpl b/internal/cmd/generator/vm.go.tmpl index cb4db57..645d20f 100644 --- a/internal/cmd/generator/vm.go.tmpl +++ b/internal/cmd/generator/vm.go.tmpl @@ -194,11 +194,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) - if ifacePtr == nil && !isDirectedNil { - b = appendNullComma(ctx, b) - code = code.Next - break + if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) diff --git a/internal/encoder/vm/vm.go b/internal/encoder/vm/vm.go index cb4db57..645d20f 100644 --- a/internal/encoder/vm/vm.go +++ b/internal/encoder/vm/vm.go @@ -194,11 +194,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) - if ifacePtr == nil && !isDirectedNil { - b = appendNullComma(ctx, b) - code = code.Next - break + if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) diff --git a/internal/encoder/vm_color/vm.go b/internal/encoder/vm_color/vm.go index e8a5597..a63e83e 100644 --- a/internal/encoder/vm_color/vm.go +++ b/internal/encoder/vm_color/vm.go @@ -194,11 +194,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) - if ifacePtr == nil && !isDirectedNil { - b = appendNullComma(ctx, b) - code = code.Next - break + if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) diff --git a/internal/encoder/vm_color_indent/vm.go b/internal/encoder/vm_color_indent/vm.go index 79cfdd8..3b4e22e 100644 --- a/internal/encoder/vm_color_indent/vm.go +++ b/internal/encoder/vm_color_indent/vm.go @@ -194,11 +194,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) - if ifacePtr == nil && !isDirectedNil { - b = appendNullComma(ctx, b) - code = code.Next - break + if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) diff --git a/internal/encoder/vm_indent/vm.go b/internal/encoder/vm_indent/vm.go index 5451484..836c5c8 100644 --- a/internal/encoder/vm_indent/vm.go +++ b/internal/encoder/vm_indent/vm.go @@ -194,11 +194,13 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) - if ifacePtr == nil && !isDirectedNil { - b = appendNullComma(ctx, b) - code = code.Next - break + if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) From f0e6a549f2f868b6ecbb5e05aa80b52d9baf9aee Mon Sep 17 00:00:00 2001 From: Nao Yonashiro Date: Mon, 4 Jul 2022 14:46:17 +0900 Subject: [PATCH 05/11] fix: support for embedding alias of primitive types fix #372 --- decode_test.go | 17 +++++++++++++++++ internal/decoder/compile.go | 9 +++++++++ 2 files changed, 26 insertions(+) diff --git a/decode_test.go b/decode_test.go index f5e2563..c276a32 100644 --- a/decode_test.go +++ b/decode_test.go @@ -3968,3 +3968,20 @@ func TestIssue335(t *testing.T) { t.Errorf("unexpected success") } } + +func TestIssue372(t *testing.T) { + type A int + type T struct { + _ int + *A + } + var v T + err := json.Unmarshal([]byte(`{"A":7}`), &v) + assertErr(t, err) + + got := *v.A + expected := A(7) + if got != expected { + t.Errorf("unexpected result: %v != %v", got, expected) + } +} diff --git a/internal/decoder/compile.go b/internal/decoder/compile.go index f13b43b..48b0217 100644 --- a/internal/decoder/compile.go +++ b/internal/decoder/compile.go @@ -393,6 +393,15 @@ func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeTo } allFields = append(allFields, fieldSet) } + } else { + fieldSet := &structFieldSet{ + dec: pdec, + offset: field.Offset, + isTaggedKey: tag.IsTaggedKey, + key: field.Name, + keyLen: int64(len(field.Name)), + } + allFields = append(allFields, fieldSet) } } else { fieldSet := &structFieldSet{ From 565e07e45c3fff959ae82cfeff814309fe185928 Mon Sep 17 00:00:00 2001 From: Nao Yonashiro Date: Tue, 5 Jul 2022 01:15:08 +0900 Subject: [PATCH 06/11] fix: change isPtr to true on listElemCode fix #370 --- encode_test.go | 29 +++++++++++++++++++++++++++++ internal/encoder/compiler.go | 3 ++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/encode_test.go b/encode_test.go index 1c0de3c..480ec78 100644 --- a/encode_test.go +++ b/encode_test.go @@ -2424,3 +2424,32 @@ func TestIssue376(t *testing.T) { t.Errorf("unexpected result: %v != %v", got, expected) } } + +type Issue370 struct { + String string + Valid bool +} + +func (i *Issue370) MarshalJSON() ([]byte, error) { + if !i.Valid { + return json.Marshal(nil) + } + return json.Marshal(i.String) +} + +func TestIssue370(t *testing.T) { + v := []struct { + V Issue370 + }{ + {V: Issue370{String: "test", Valid: true}}, + } + b, err := json.Marshal(v) + if err != nil { + t.Fatal(err) + } + got := string(b) + expected := `[{"V":"test"}]` + if got != expected { + t.Errorf("unexpected result: %v != %v", got, expected) + } +} diff --git a/internal/encoder/compiler.go b/internal/encoder/compiler.go index de7323c..83eab57 100644 --- a/internal/encoder/compiler.go +++ b/internal/encoder/compiler.go @@ -487,7 +487,8 @@ func (c *Compiler) listElemCode(typ *runtime.Type) (Code, error) { case typ.Kind() == reflect.Map: return c.ptrCode(runtime.PtrTo(typ)) default: - code, err := c.typeToCodeWithPtr(typ, false) + // Strictly not isPtr == true, but reflect.ValueOf().Index() is canAddr, so set isPtr == true. + code, err := c.typeToCodeWithPtr(typ, true) if err != nil { return nil, err } From 8f5055b06ad27a023d7bcac7fc0f6ef03f2e8306 Mon Sep 17 00:00:00 2001 From: Nao Yonashiro Date: Wed, 6 Jul 2022 16:56:11 +0900 Subject: [PATCH 07/11] fix: In decodeUnicode, the case that the expected buffer's state is not satisfied after reading. fix #374 --- encode_test.go | 15 +++++++++++++++ internal/decoder/string.go | 24 +++++++++++++++--------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/encode_test.go b/encode_test.go index 1c0de3c..f828dda 100644 --- a/encode_test.go +++ b/encode_test.go @@ -7,12 +7,14 @@ import ( stdjson "encoding/json" "errors" "fmt" + "io" "log" "math" "math/big" "reflect" "regexp" "strconv" + "strings" "testing" "time" @@ -2424,3 +2426,16 @@ func TestIssue376(t *testing.T) { t.Errorf("unexpected result: %v != %v", got, expected) } } + +func TestIssue374(t *testing.T) { + r := io.MultiReader(strings.NewReader(strings.Repeat(" ", 505)+`"\u`), strings.NewReader(`0000"`)) + var v interface{} + if err := json.NewDecoder(r).Decode(&v); err != nil { + t.Fatal(err) + } + got := v.(string) + expected := "\u0000" + if got != expected { + t.Errorf("unexpected result: %q != %q", got, expected) + } +} diff --git a/internal/decoder/string.go b/internal/decoder/string.go index cef6688..871ab3d 100644 --- a/internal/decoder/string.go +++ b/internal/decoder/string.go @@ -95,24 +95,30 @@ func unicodeToRune(code []byte) rune { return r } +func readAtLeast(s *Stream, n int64, p *unsafe.Pointer) bool { + for s.cursor+n >= s.length { + if !s.read() { + return false + } + *p = s.bufptr() + } + return true +} + func decodeUnicodeRune(s *Stream, p unsafe.Pointer) (rune, int64, unsafe.Pointer, error) { const defaultOffset = 5 const surrogateOffset = 11 - if s.cursor+defaultOffset >= s.length { - if !s.read() { - return rune(0), 0, nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset()) - } - p = s.bufptr() + if !readAtLeast(s, defaultOffset, &p) { + return rune(0), 0, nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset()) } r := unicodeToRune(s.buf[s.cursor+1 : s.cursor+defaultOffset]) if utf16.IsSurrogate(r) { - if s.cursor+surrogateOffset >= s.length { - s.read() - p = s.bufptr() + if !readAtLeast(s, surrogateOffset, &p) { + return unicode.ReplacementChar, defaultOffset, p, nil } - if s.cursor+surrogateOffset >= s.length || s.buf[s.cursor+defaultOffset] != '\\' || s.buf[s.cursor+defaultOffset+1] != 'u' { + if s.buf[s.cursor+defaultOffset] != '\\' || s.buf[s.cursor+defaultOffset+1] != 'u' { return unicode.ReplacementChar, defaultOffset, p, nil } r2 := unicodeToRune(s.buf[s.cursor+defaultOffset+2 : s.cursor+surrogateOffset]) From 88aa13e3006fb5de4fa8c800778b4c671853e399 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Thu, 7 Jul 2022 14:52:28 +0900 Subject: [PATCH 08/11] Fix comment for #379 --- internal/encoder/compiler.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/encoder/compiler.go b/internal/encoder/compiler.go index 83eab57..64533f4 100644 --- a/internal/encoder/compiler.go +++ b/internal/encoder/compiler.go @@ -487,7 +487,9 @@ func (c *Compiler) listElemCode(typ *runtime.Type) (Code, error) { case typ.Kind() == reflect.Map: return c.ptrCode(runtime.PtrTo(typ)) default: - // Strictly not isPtr == true, but reflect.ValueOf().Index() is canAddr, so set isPtr == true. + // isPtr was originally used to indicate whether the type of top level is pointer. + // However, since the slice/array element is a specification that can get the pointer address, explicitly set isPtr to true. + // See here for related issues: https://github.com/goccy/go-json/issues/370 code, err := c.typeToCodeWithPtr(typ, true) if err != nil { return nil, err From 9a9f9adb055ce1cd8cf8251105633938f9f36875 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Sun, 10 Jul 2022 09:15:33 +0800 Subject: [PATCH 09/11] fix encoder and decoder cache slice edge case --- encode_test.go | 123 +++++++++++++++++++++++++++++++++++ internal/decoder/compile.go | 2 +- internal/encoder/compiler.go | 2 +- 3 files changed, 125 insertions(+), 2 deletions(-) diff --git a/encode_test.go b/encode_test.go index 4989866..5b10d75 100644 --- a/encode_test.go +++ b/encode_test.go @@ -2468,3 +2468,126 @@ func TestIssue374(t *testing.T) { t.Errorf("unexpected result: %q != %q", got, expected) } } + +func TestIssue381(t *testing.T) { + var v struct { + Field0 bool + Field1 bool + Field2 bool + Field3 bool + Field4 bool + Field5 bool + Field6 bool + Field7 bool + Field8 bool + Field9 bool + Field10 bool + Field11 bool + Field12 bool + Field13 bool + Field14 bool + Field15 bool + Field16 bool + Field17 bool + Field18 bool + Field19 bool + Field20 bool + Field21 bool + Field22 bool + Field23 bool + Field24 bool + Field25 bool + Field26 bool + Field27 bool + Field28 bool + Field29 bool + Field30 bool + Field31 bool + Field32 bool + Field33 bool + Field34 bool + Field35 bool + Field36 bool + Field37 bool + Field38 bool + Field39 bool + Field40 bool + Field41 bool + Field42 bool + Field43 bool + Field44 bool + Field45 bool + Field46 bool + Field47 bool + Field48 bool + Field49 bool + Field50 bool + Field51 bool + Field52 bool + Field53 bool + Field54 bool + Field55 bool + Field56 bool + Field57 bool + Field58 bool + Field59 bool + Field60 bool + Field61 bool + Field62 bool + Field63 bool + Field64 bool + Field65 bool + Field66 bool + Field67 bool + Field68 bool + Field69 bool + Field70 bool + Field71 bool + Field72 bool + Field73 bool + Field74 bool + Field75 bool + Field76 bool + Field77 bool + Field78 bool + Field79 bool + Field80 bool + Field81 bool + Field82 bool + Field83 bool + Field84 bool + Field85 bool + Field86 bool + Field87 bool + Field88 bool + Field89 bool + Field90 bool + Field91 bool + Field92 bool + Field93 bool + Field94 bool + Field95 bool + Field96 bool + Field97 bool + Field98 bool + Field99 bool + } + + // test encoder cache issue, not related to encoder + b, err := json.Marshal(v) + if err != nil { + t.Errorf("failed to marshal %s", err.Error()) + t.FailNow() + } + + std, err := stdjson.Marshal(v) + if err != nil { + t.Errorf("failed to marshal with encoding/json %s", err.Error()) + t.FailNow() + } + + if !bytes.Equal(std, b) { + t.Errorf("encoding result not equal to encoding/json") + t.FailNow() + } +} diff --git a/internal/decoder/compile.go b/internal/decoder/compile.go index 48b0217..fab6437 100644 --- a/internal/decoder/compile.go +++ b/internal/decoder/compile.go @@ -24,7 +24,7 @@ func init() { if typeAddr == nil { typeAddr = &runtime.TypeAddr{} } - cachedDecoder = make([]Decoder, typeAddr.AddrRange>>typeAddr.AddrShift) + cachedDecoder = make([]Decoder, typeAddr.AddrRange>>typeAddr.AddrShift+1) } func loadDecoderMap() map[uintptr]Decoder { diff --git a/internal/encoder/compiler.go b/internal/encoder/compiler.go index 64533f4..bf5e0f9 100644 --- a/internal/encoder/compiler.go +++ b/internal/encoder/compiler.go @@ -31,7 +31,7 @@ func init() { if typeAddr == nil { typeAddr = &runtime.TypeAddr{} } - cachedOpcodeSets = make([]*OpcodeSet, typeAddr.AddrRange>>typeAddr.AddrShift) + cachedOpcodeSets = make([]*OpcodeSet, typeAddr.AddrRange>>typeAddr.AddrShift+1) } func loadOpcodeMap() map[uintptr]*OpcodeSet { From 190c2e30bda23da7b7cf121ddd2809de8e3e687d Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 15 Jul 2022 16:59:13 +0900 Subject: [PATCH 10/11] Update CHANGELOG --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e4b93f..e4b1d26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# v0.9.9 - 2022/07/15 + +### Fix bugs + +* Fix encoding of directed interface with typed nil ( #377 ) +* Fix embedded primitive type encoding using alias ( #378 ) +* Fix slice/array type encoding with types implementing MarshalJSON ( #379 ) +* Fix unicode decoding when the expected buffer state is not met after reading ( #380 ) + # v0.9.8 - 2022/06/30 ### Fix bugs From 3eafdb612986f7fdf5dedbb537521def4341e3be Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 15 Jul 2022 19:12:47 +0900 Subject: [PATCH 11/11] Update CHANGELOG --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4b1d26..20d13e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v0.9.10 - 2022/07/15 + +### Fix bugs + +* Fix boundary exception of type caching ( #382 ) + # v0.9.9 - 2022/07/15 ### Fix bugs