diff --git a/internal/cmd/generator/vm.go.tmpl b/internal/cmd/generator/vm.go.tmpl index 17374ba..78da5e4 100644 --- a/internal/cmd/generator/vm.go.tmpl +++ b/internal/cmd/generator/vm.go.tmpl @@ -177,9 +177,11 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b code = code.Next break } - for _, seen := range ctx.SeenPtr { - if p == seen { - return nil, errUnsupportedValue(code, p) + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } } } ctx.SeenPtr = append(ctx.SeenPtr, p) @@ -226,9 +228,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c + recursiveLevel++ case encoder.OpInterfaceEnd: - offset := load(ctxptr, code.Idx) + recursiveLevel-- + // restore ctxptr + offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] diff --git a/internal/encoder/vm/vm.go b/internal/encoder/vm/vm.go index 17374ba..78da5e4 100644 --- a/internal/encoder/vm/vm.go +++ b/internal/encoder/vm/vm.go @@ -177,9 +177,11 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b code = code.Next break } - for _, seen := range ctx.SeenPtr { - if p == seen { - return nil, errUnsupportedValue(code, p) + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } } } ctx.SeenPtr = append(ctx.SeenPtr, p) @@ -226,9 +228,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c + recursiveLevel++ case encoder.OpInterfaceEnd: - offset := load(ctxptr, code.Idx) + recursiveLevel-- + // restore ctxptr + offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] diff --git a/internal/encoder/vm_color/vm.go b/internal/encoder/vm_color/vm.go index 33bea71..0d4c472 100644 --- a/internal/encoder/vm_color/vm.go +++ b/internal/encoder/vm_color/vm.go @@ -177,9 +177,11 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b code = code.Next break } - for _, seen := range ctx.SeenPtr { - if p == seen { - return nil, errUnsupportedValue(code, p) + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } } } ctx.SeenPtr = append(ctx.SeenPtr, p) @@ -226,9 +228,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c + recursiveLevel++ case encoder.OpInterfaceEnd: - offset := load(ctxptr, code.Idx) + recursiveLevel-- + // restore ctxptr + offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] diff --git a/internal/encoder/vm_color_indent/vm.go b/internal/encoder/vm_color_indent/vm.go index 523cb45..de8b858 100644 --- a/internal/encoder/vm_color_indent/vm.go +++ b/internal/encoder/vm_color_indent/vm.go @@ -177,9 +177,11 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b code = code.Next break } - for _, seen := range ctx.SeenPtr { - if p == seen { - return nil, errUnsupportedValue(code, p) + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } } } ctx.SeenPtr = append(ctx.SeenPtr, p) @@ -226,9 +228,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c + recursiveLevel++ case encoder.OpInterfaceEnd: - offset := load(ctxptr, code.Idx) + recursiveLevel-- + // restore ctxptr + offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1] diff --git a/internal/encoder/vm_indent/vm.go b/internal/encoder/vm_indent/vm.go index 2d2dcb5..d10ce75 100644 --- a/internal/encoder/vm_indent/vm.go +++ b/internal/encoder/vm_indent/vm.go @@ -177,9 +177,11 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b code = code.Next break } - for _, seen := range ctx.SeenPtr { - if p == seen { - return nil, errUnsupportedValue(code, p) + if recursiveLevel > encoder.StartDetectingCyclesAfter { + for _, seen := range ctx.SeenPtr { + if p == seen { + return nil, errUnsupportedValue(code, p) + } } } ctx.SeenPtr = append(ctx.SeenPtr, p) @@ -226,9 +228,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next))) storeIndent(ctxptr, end, uintptr(oldBaseIndent)) code = c + recursiveLevel++ case encoder.OpInterfaceEnd: - offset := load(ctxptr, code.Idx) + recursiveLevel-- + // restore ctxptr + offset := load(ctxptr, code.Idx) restoreIndent(ctx, code, ctxptr) ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1]