forked from TrueCloudLab/neoneo-go
vm: restrict map key size
This commit is contained in:
parent
1f9b92c295
commit
543fd58e93
5 changed files with 20 additions and 11 deletions
|
@ -24,6 +24,7 @@ a dialect of Go rather than a complete port of the language:
|
||||||
overhead for all contracts. This can easily be mitigated by first storing values
|
overhead for all contracts. This can easily be mitigated by first storing values
|
||||||
in variables and returning the result.
|
in variables and returning the result.
|
||||||
* lambdas are supported, but closures are not.
|
* lambdas are supported, but closures are not.
|
||||||
|
* maps are supported, but valid map keys are booleans, integers and strings with length <= 64
|
||||||
|
|
||||||
## VM API (interop layer)
|
## VM API (interop layer)
|
||||||
Compiler translates interop function calls into NEO VM syscalls or (for custom
|
Compiler translates interop function calls into NEO VM syscalls or (for custom
|
||||||
|
|
|
@ -27,6 +27,8 @@ const (
|
||||||
// MaxByteArrayComparableSize is the maximum allowed length of ByteArray for Equals method.
|
// MaxByteArrayComparableSize is the maximum allowed length of ByteArray for Equals method.
|
||||||
// It is set to be the maximum uint16 value.
|
// It is set to be the maximum uint16 value.
|
||||||
MaxByteArrayComparableSize = math.MaxUint16
|
MaxByteArrayComparableSize = math.MaxUint16
|
||||||
|
// MaxKeySize is the maximum size of map key.
|
||||||
|
MaxKeySize = 64
|
||||||
)
|
)
|
||||||
|
|
||||||
// Item represents the "real" value that is pushed on the stack.
|
// Item represents the "real" value that is pushed on the stack.
|
||||||
|
@ -773,8 +775,8 @@ func (i *Map) Convert(typ Type) (Item, error) {
|
||||||
|
|
||||||
// Add adds key-value pair to the map.
|
// Add adds key-value pair to the map.
|
||||||
func (i *Map) Add(key, value Item) {
|
func (i *Map) Add(key, value Item) {
|
||||||
if !IsValidMapKey(key) {
|
if err := IsValidMapKey(key); err != nil {
|
||||||
panic("wrong key type")
|
panic(err)
|
||||||
}
|
}
|
||||||
index := i.Index(key)
|
index := i.Index(key)
|
||||||
if index >= 0 {
|
if index >= 0 {
|
||||||
|
@ -792,12 +794,18 @@ func (i *Map) Drop(index int) {
|
||||||
|
|
||||||
// IsValidMapKey checks whether it's possible to use given Item as a Map
|
// IsValidMapKey checks whether it's possible to use given Item as a Map
|
||||||
// key.
|
// key.
|
||||||
func IsValidMapKey(key Item) bool {
|
func IsValidMapKey(key Item) error {
|
||||||
switch key.(type) {
|
switch key.(type) {
|
||||||
case *Bool, *BigInteger, *ByteArray:
|
case *Bool, *BigInteger:
|
||||||
return true
|
return nil
|
||||||
|
case *ByteArray:
|
||||||
|
size := len(key.Value().([]byte))
|
||||||
|
if size > MaxKeySize {
|
||||||
|
return fmt.Errorf("invalid map key size: %d", size)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
default:
|
default:
|
||||||
return false
|
return fmt.Errorf("invalid map key of type %s", key.Type())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -360,8 +360,8 @@ func FromJSONWithTypes(data []byte) (Item, error) {
|
||||||
key, err := FromJSONWithTypes(arr[i].Key)
|
key, err := FromJSONWithTypes(arr[i].Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !IsValidMapKey(key) {
|
} else if err = IsValidMapKey(key); err != nil {
|
||||||
return nil, fmt.Errorf("invalid map key of type %s", key.Type())
|
return nil, err
|
||||||
}
|
}
|
||||||
value, err := FromJSONWithTypes(arr[i].Value)
|
value, err := FromJSONWithTypes(arr[i].Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -88,7 +88,7 @@ func TestFromToJSON(t *testing.T) {
|
||||||
t.Run("BigNestedArray", getTestDecodeFunc(`[[[[[[[[[[[]]]]]]]]]]]`, nil))
|
t.Run("BigNestedArray", getTestDecodeFunc(`[[[[[[[[[[[]]]]]]]]]]]`, nil))
|
||||||
t.Run("EncodeRecursive", func(t *testing.T) {
|
t.Run("EncodeRecursive", func(t *testing.T) {
|
||||||
// add this item to speed up test a bit
|
// add this item to speed up test a bit
|
||||||
item := NewByteArray(make([]byte, MaxSize/100))
|
item := NewByteArray(make([]byte, MaxKeySize))
|
||||||
t.Run("Array", func(t *testing.T) {
|
t.Run("Array", func(t *testing.T) {
|
||||||
arr := NewArray([]Item{item})
|
arr := NewArray([]Item{item})
|
||||||
arr.Append(arr)
|
arr.Append(arr)
|
||||||
|
|
|
@ -1668,8 +1668,8 @@ func validateMapKey(key *Element) {
|
||||||
if key == nil {
|
if key == nil {
|
||||||
panic("no key found")
|
panic("no key found")
|
||||||
}
|
}
|
||||||
if !stackitem.IsValidMapKey(key.Item()) {
|
if err := stackitem.IsValidMapKey(key.Item()); err != nil {
|
||||||
panic("key can't be a collection")
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue