Skip to content

Commit 7b1806d

Browse files
fxamackerturbolent
authored andcommitted
Check array element count before inserting new element
This commit checks if the array element count reached the max limit (currently math.MaxUint32) before inserting a new element to the array. If the array already has the max number of elements allowed (4.29+ billion) then the insert function returns a user error. NOTE: Even before adding this check, a single transaction cannot by itself insert 4.29+ billion elements due to various transaction limits enforced by client software (onflow/cadence and onflow/flow-go).
1 parent e354664 commit 7b1806d

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

array.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,19 @@ package atree
2020

2121
import (
2222
"fmt"
23+
"math"
2324
"strings"
2425
)
2526

27+
const (
28+
// maxArrayElementCount is the max number of elements that can be stored in an array.
29+
// Currently, this limit is set to math.MaxUint32 (4,294,967,295 elements per array).
30+
// ArraySlabHeader.Count (uint32) is used to track element count in array slabs.
31+
// NOTE: MaxArrayElementCount is uint64 since we may want to increase the limit to be
32+
// greater than MaxUint32 in the future.
33+
maxArrayElementCount uint64 = math.MaxUint32
34+
)
35+
2636
// Array is a heterogeneous variable-size array, storing any type of values
2737
// into a smaller ordered list of values and provides efficient functionality
2838
// to lookup, insert and remove elements anywhere in the array.
@@ -444,6 +454,11 @@ func (a *Array) Append(value Value) error {
444454
}
445455

446456
func (a *Array) Insert(index uint64, value Value) error {
457+
if a.Count() == maxArrayElementCount {
458+
// Don't insert new element if array already has max number of elements.
459+
return NewArrayElementCannotExceedMaxElementCountError(maxArrayElementCount)
460+
}
461+
447462
err := a.root.Insert(a.Storage, a.Address(), index, value)
448463
if err != nil {
449464
// Don't need to wrap error as external error because err is already categorized by ArraySlab.Insert().

errors.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,25 @@ func (e *FatalError) Unwrap() error {
7676
return e.err
7777
}
7878

79+
// ArrayElementCannotExceedMaxElementCountError is returned when new element can't be inserted into an array
80+
// because the array already has the max number of elements allowed.
81+
type ArrayElementCannotExceedMaxElementCountError struct {
82+
maxCount uint64
83+
}
84+
85+
// NewArrayElementCannotExceedMaxElementCountError returns ArrayElementCannotExceedMaxElementCountError.
86+
func NewArrayElementCannotExceedMaxElementCountError(maxCount uint64) error {
87+
return NewUserError(
88+
&ArrayElementCannotExceedMaxElementCountError{
89+
maxCount: maxCount,
90+
},
91+
)
92+
}
93+
94+
func (e *ArrayElementCannotExceedMaxElementCountError) Error() string {
95+
return fmt.Sprintf("new element cann't be inserted into an array: array already has max number of elements %d", e.maxCount)
96+
}
97+
7998
// SliceOutOfBoundsError is returned when index for array slice is out of bounds.
8099
type SliceOutOfBoundsError struct {
81100
startIndex uint64

0 commit comments

Comments
 (0)