mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-26 09:42:22 +00:00
Merge pull request #2904 from nspcc-dev/export-deserialization-context
vm: export deserialization context
This commit is contained in:
commit
1d6e48ee78
2 changed files with 43 additions and 2 deletions
|
@ -232,6 +232,27 @@ func Deserialize(data []byte) (Item, error) {
|
||||||
return item, nil
|
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
|
// DecodeBinary decodes the previously serialized Item from the given
|
||||||
// reader. It's similar to the io.Serializable's DecodeBinary() but implemented
|
// reader. It's similar to the io.Serializable's DecodeBinary() but implemented
|
||||||
// as a function because Item itself is an interface. Caveat: always check
|
// as a function because Item itself is an interface. Caveat: always check
|
||||||
|
@ -283,7 +304,7 @@ func (r *deserContext) decodeBinary() Item {
|
||||||
return NewBigInteger(num)
|
return NewBigInteger(num)
|
||||||
case ArrayT, StructT:
|
case ArrayT, StructT:
|
||||||
size := int(r.ReadVarUint())
|
size := int(r.ReadVarUint())
|
||||||
if size > MaxDeserialized {
|
if size > r.limit {
|
||||||
r.Err = errTooBigElements
|
r.Err = errTooBigElements
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -298,7 +319,7 @@ func (r *deserContext) decodeBinary() Item {
|
||||||
return NewStruct(arr)
|
return NewStruct(arr)
|
||||||
case MapT:
|
case MapT:
|
||||||
size := int(r.ReadVarUint())
|
size := int(r.ReadVarUint())
|
||||||
if size > MaxDeserialized {
|
if size > r.limit/2 {
|
||||||
r.Err = errTooBigElements
|
r.Err = errTooBigElements
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,6 +209,26 @@ func TestDeserializeTooManyElements(t *testing.T) {
|
||||||
require.True(t, errors.Is(err, ErrTooBig), err)
|
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) {
|
func BenchmarkEncodeBinary(b *testing.B) {
|
||||||
arr := getBigArray(15)
|
arr := getBigArray(15)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue