@@ -779,6 +779,16 @@ func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
779
779
e .WriteString ("null" )
780
780
return
781
781
}
782
+ if e .ptrLevel ++ ; e .ptrLevel > startDetectingCyclesAfter {
783
+ // We're a large number of nested ptrEncoder.encode calls deep;
784
+ // start checking if we've run into a pointer cycle.
785
+ ptr := v .Pointer ()
786
+ if _ , ok := e .ptrSeen [ptr ]; ok {
787
+ e .error (& UnsupportedValueError {v , fmt .Sprintf ("encountered a cycle via %s" , v .Type ())})
788
+ }
789
+ e .ptrSeen [ptr ] = struct {}{}
790
+ defer delete (e .ptrSeen , ptr )
791
+ }
782
792
e .WriteByte ('{' )
783
793
784
794
// Extract and sort the keys.
@@ -801,6 +811,7 @@ func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
801
811
me .elemEnc (e , v .MapIndex (kv .v ), opts )
802
812
}
803
813
e .WriteByte ('}' )
814
+ e .ptrLevel --
804
815
}
805
816
806
817
func newMapEncoder (t reflect.Type ) encoderFunc {
@@ -857,7 +868,23 @@ func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
857
868
e .WriteString ("null" )
858
869
return
859
870
}
871
+ if e .ptrLevel ++ ; e .ptrLevel > startDetectingCyclesAfter {
872
+ // We're a large number of nested ptrEncoder.encode calls deep;
873
+ // start checking if we've run into a pointer cycle.
874
+ // Here we use a struct to memorize the pointer to the first element of the slice
875
+ // and its length.
876
+ ptr := struct {
877
+ ptr uintptr
878
+ len int
879
+ }{v .Pointer (), v .Len ()}
880
+ if _ , ok := e .ptrSeen [ptr ]; ok {
881
+ e .error (& UnsupportedValueError {v , fmt .Sprintf ("encountered a cycle via %s" , v .Type ())})
882
+ }
883
+ e .ptrSeen [ptr ] = struct {}{}
884
+ defer delete (e .ptrSeen , ptr )
885
+ }
860
886
se .arrayEnc (e , v , opts )
887
+ e .ptrLevel --
861
888
}
862
889
863
890
func newSliceEncoder (t reflect.Type ) encoderFunc {
0 commit comments