From e34fa2e915dc17bab23eba85ee12d8f1674009a0 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 6 Jul 2021 17:33:16 +0300 Subject: [PATCH] stackitem: limit JSONization nesting level We can have very deep reference types and attempt to JSONize them can easily lead to OOM (even though there are no recursive references inside). Therefore we have to limit them. While regular ToJSON() is buffer size limited to MaxSize, ToJSONWithTypes is not and limiting it to MaxSize output will require substantial rewriting effort while not really providing fair result, MaxSize is more about stack item size while its JSON representation can be much bigger because of various overheads. Initial thought was to limit it by element count based on MaxIteratorResultItems, but the problem here is that we don't always have this limit in contexts using ToJSONWithTypes (like notification event marshaling). Thus we need some generic limit which would be fine for all users. We at the same time have maxJSONDepth used when deserializing from JSON, so it can be used for marshaling as well, it's not often that we have deeper structures in real results. Inspired by neo-project/neo#2521. --- pkg/vm/stackitem/json.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/vm/stackitem/json.go b/pkg/vm/stackitem/json.go index 292b6936a..3d6abe9ed 100644 --- a/pkg/vm/stackitem/json.go +++ b/pkg/vm/stackitem/json.go @@ -221,6 +221,9 @@ func ToJSONWithTypes(item Item) ([]byte, error) { } func toJSONWithTypes(item Item, seen map[Item]bool) (interface{}, error) { + if len(seen) > maxJSONDepth { + return "", errors.New("too deep structure") + } typ := item.Type() result := map[string]interface{}{ "type": typ.String(),