Skip to content

Commit

Permalink
Merge pull request nspcc-dev#2904 from nspcc-dev/export-deserializati…
Browse files Browse the repository at this point in the history
…on-context

vm: export deserialization context
  • Loading branch information
roman-khimov committed Feb 8, 2023
2 parents bd26b9d + 25ed5fc commit 1d6e48e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 2 deletions.
25 changes: 23 additions & 2 deletions pkg/vm/stackitem/serialization.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,27 @@ func Deserialize(data []byte) (Item, error) {
return item, nil
}

// DeserializeLimited returns Item deserialized from the given byte slice. limit
// restricts the maximum number of items deserialized item can contain (including
// itself). The default limit of MaxDeserialized is used if non-positive limit is
// specified.
func DeserializeLimited(data []byte, limit int) (Item, error) {
r := io.NewBinReaderFromBuf(data)
dc := deserContext{
BinReader: r,
allowInvalid: false,
limit: MaxDeserialized,
}
if limit > 0 {
dc.limit = limit
}
item := dc.decodeBinary()
if r.Err != nil {
return nil, r.Err
}
return item, nil
}

// DecodeBinary decodes the previously serialized Item from the given
// reader. It's similar to the io.Serializable's DecodeBinary() but implemented
// as a function because Item itself is an interface. Caveat: always check
Expand Down Expand Up @@ -283,7 +304,7 @@ func (r *deserContext) decodeBinary() Item {
return NewBigInteger(num)
case ArrayT, StructT:
size := int(r.ReadVarUint())
if size > MaxDeserialized {
if size > r.limit {
r.Err = errTooBigElements
return nil
}
Expand All @@ -298,7 +319,7 @@ func (r *deserContext) decodeBinary() Item {
return NewStruct(arr)
case MapT:
size := int(r.ReadVarUint())
if size > MaxDeserialized {
if size > r.limit/2 {
r.Err = errTooBigElements
return nil
}
Expand Down
20 changes: 20 additions & 0 deletions pkg/vm/stackitem/serialization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,26 @@ func TestDeserializeTooManyElements(t *testing.T) {
require.True(t, errors.Is(err, ErrTooBig), err)
}

func TestDeserializeLimited(t *testing.T) {
customLimit := MaxDeserialized + 1
item := Make(0)
for i := 0; i < customLimit-1; i++ { // 1 for zero inner element.
item = Make([]Item{item})
}
data, err := Serialize(item)
require.NoError(t, err)
actual, err := DeserializeLimited(data, customLimit)
require.NoError(t, err)
require.Equal(t, item, actual)

item = Make([]Item{item})
data, err = Serialize(item)
require.NoError(t, err)
_, err = DeserializeLimited(data, customLimit)
require.Error(t, err)
require.True(t, errors.Is(err, ErrTooBig), err)
}

func BenchmarkEncodeBinary(b *testing.B) {
arr := getBigArray(15)

Expand Down

0 comments on commit 1d6e48e

Please sign in to comment.