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
|
||||
in variables and returning the result.
|
||||
* 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)
|
||||
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.
|
||||
// It is set to be the maximum uint16 value.
|
||||
MaxByteArrayComparableSize = math.MaxUint16
|
||||
// MaxKeySize is the maximum size of map key.
|
||||
MaxKeySize = 64
|
||||
)
|
||||
|
||||
// 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.
|
||||
func (i *Map) Add(key, value Item) {
|
||||
if !IsValidMapKey(key) {
|
||||
panic("wrong key type")
|
||||
if err := IsValidMapKey(key); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
index := i.Index(key)
|
||||
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
|
||||
// key.
|
||||
func IsValidMapKey(key Item) bool {
|
||||
func IsValidMapKey(key Item) error {
|
||||
switch key.(type) {
|
||||
case *Bool, *BigInteger, *ByteArray:
|
||||
return true
|
||||
case *Bool, *BigInteger:
|
||||
return nil
|
||||
case *ByteArray:
|
||||
size := len(key.Value().([]byte))
|
||||
if size > MaxKeySize {
|
||||
return fmt.Errorf("invalid map key size: %d", size)
|
||||
}
|
||||
return nil
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !IsValidMapKey(key) {
|
||||
return nil, fmt.Errorf("invalid map key of type %s", key.Type())
|
||||
} else if err = IsValidMapKey(key); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
value, err := FromJSONWithTypes(arr[i].Value)
|
||||
if err != nil {
|
||||
|
|
|
@ -88,7 +88,7 @@ func TestFromToJSON(t *testing.T) {
|
|||
t.Run("BigNestedArray", getTestDecodeFunc(`[[[[[[[[[[[]]]]]]]]]]]`, nil))
|
||||
t.Run("EncodeRecursive", func(t *testing.T) {
|
||||
// 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) {
|
||||
arr := NewArray([]Item{item})
|
||||
arr.Append(arr)
|
||||
|
|
|
@ -1668,8 +1668,8 @@ func validateMapKey(key *Element) {
|
|||
if key == nil {
|
||||
panic("no key found")
|
||||
}
|
||||
if !stackitem.IsValidMapKey(key.Item()) {
|
||||
panic("key can't be a collection")
|
||||
if err := stackitem.IsValidMapKey(key.Item()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue