parent
740488f7f3
commit
23b78b0be2
2 changed files with 100 additions and 11 deletions
|
@ -263,11 +263,22 @@ func (i *Struct) equalStruct(s *Struct, limit *int) bool {
|
||||||
} else if len(i.value) != len(s.value) {
|
} else if len(i.value) != len(s.value) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
var maxComparableSize = MaxByteArrayComparableSize
|
||||||
for j := range i.value {
|
for j := range i.value {
|
||||||
*limit--
|
*limit--
|
||||||
if *limit == 0 {
|
if *limit == 0 {
|
||||||
panic(errTooBigElements)
|
panic(errTooBigElements)
|
||||||
}
|
}
|
||||||
|
arr, ok := i.value[j].(*ByteArray)
|
||||||
|
if ok {
|
||||||
|
if !arr.equalsLimited(s.value[j], &maxComparableSize) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if maxComparableSize == 0 {
|
||||||
|
panic(errTooBigComparable)
|
||||||
|
}
|
||||||
|
maxComparableSize--
|
||||||
sa, oka := i.value[j].(*Struct)
|
sa, oka := i.value[j].(*Struct)
|
||||||
sb, okb := s.value[j].(*Struct)
|
sb, okb := s.value[j].(*Struct)
|
||||||
if oka && okb {
|
if oka && okb {
|
||||||
|
@ -278,6 +289,7 @@ func (i *Struct) equalStruct(s *Struct, limit *int) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,19 +606,39 @@ func (i ByteArray) TryInteger() (*big.Int, error) {
|
||||||
|
|
||||||
// Equals implements the Item interface.
|
// Equals implements the Item interface.
|
||||||
func (i *ByteArray) Equals(s Item) bool {
|
func (i *ByteArray) Equals(s Item) bool {
|
||||||
if len(*i) > MaxByteArrayComparableSize {
|
var limit = MaxByteArrayComparableSize
|
||||||
|
return i.equalsLimited(s, &limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// equalsLimited compares ByteArray with provided stackitem using the limit.
|
||||||
|
func (i *ByteArray) equalsLimited(s Item, limit *int) bool {
|
||||||
|
if i == nil {
|
||||||
|
return s == nil
|
||||||
|
}
|
||||||
|
lCurr := len(*i)
|
||||||
|
if lCurr > *limit || *limit == 0 {
|
||||||
panic(errTooBigComparable)
|
panic(errTooBigComparable)
|
||||||
}
|
}
|
||||||
if i == s {
|
|
||||||
return true
|
var comparedSize = 1
|
||||||
} else if s == nil {
|
defer func() { *limit -= comparedSize }()
|
||||||
|
|
||||||
|
if s == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
val, ok := s.(*ByteArray)
|
val, ok := s.(*ByteArray)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if len(*val) > MaxByteArrayComparableSize {
|
comparedSize = lCurr
|
||||||
|
lOther := len(*val)
|
||||||
|
if lOther > comparedSize {
|
||||||
|
comparedSize = lOther
|
||||||
|
}
|
||||||
|
if i == val {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if lOther > *limit {
|
||||||
panic(errTooBigComparable)
|
panic(errTooBigComparable)
|
||||||
}
|
}
|
||||||
return bytes.Equal(*i, *val)
|
return bytes.Equal(*i, *val)
|
||||||
|
|
|
@ -809,6 +809,63 @@ func TestEQUAL(t *testing.T) {
|
||||||
t.Run("Buffer", getTestFuncForVM(prog, false, stackitem.NewBuffer([]byte{42}), stackitem.NewBuffer([]byte{42})))
|
t.Run("Buffer", getTestFuncForVM(prog, false, stackitem.NewBuffer([]byte{42}), stackitem.NewBuffer([]byte{42})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEQUALByteArrayWithLimit(t *testing.T) {
|
||||||
|
prog := makeProgram(opcode.EQUAL)
|
||||||
|
t.Run("fits limit, equal", func(t *testing.T) {
|
||||||
|
args := make([]stackitem.Item, 2)
|
||||||
|
for i := range args {
|
||||||
|
args[i] = stackitem.NewStruct([]stackitem.Item{
|
||||||
|
stackitem.NewByteArray(make([]byte, stackitem.MaxByteArrayComparableSize/2)),
|
||||||
|
stackitem.NewByteArray(make([]byte, stackitem.MaxByteArrayComparableSize/2+1)), // MaxByteArrayComparableSize is even, thus use +1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
getTestFuncForVM(prog, true, args[0], args[1])(t)
|
||||||
|
})
|
||||||
|
t.Run("exceeds limit", func(t *testing.T) {
|
||||||
|
args := make([]stackitem.Item, 2)
|
||||||
|
for i := range args {
|
||||||
|
args[i] = stackitem.NewStruct([]stackitem.Item{
|
||||||
|
stackitem.NewByteArray(make([]byte, stackitem.MaxByteArrayComparableSize/2+2)),
|
||||||
|
stackitem.NewByteArray(make([]byte, stackitem.MaxByteArrayComparableSize/2)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
getTestFuncForVM(prog, nil, args[0], args[1])(t) // should FAULT due to comparable limit exceeding
|
||||||
|
})
|
||||||
|
t.Run("fits limit, second elements are not equal", func(t *testing.T) {
|
||||||
|
args := make([]stackitem.Item, 2)
|
||||||
|
for i := range args {
|
||||||
|
args[i] = stackitem.NewStruct([]stackitem.Item{
|
||||||
|
stackitem.NewByteArray(make([]byte, stackitem.MaxByteArrayComparableSize-1)),
|
||||||
|
stackitem.NewBuffer(make([]byte, 1)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
getTestFuncForVM(prog, false, args[0], args[1])(t) // no limit is exceeded, but the second struct item is a Buffer.
|
||||||
|
})
|
||||||
|
t.Run("fits limit, equal", func(t *testing.T) {
|
||||||
|
args := make([]stackitem.Item, 2)
|
||||||
|
buf := stackitem.NewBuffer(make([]byte, 100500)) // takes only 1 comparable unit despite its length
|
||||||
|
for i := range args {
|
||||||
|
args[i] = stackitem.NewStruct([]stackitem.Item{
|
||||||
|
stackitem.NewByteArray(make([]byte, stackitem.MaxByteArrayComparableSize-1)),
|
||||||
|
buf,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
getTestFuncForVM(prog, true, args[0], args[1])(t) // should HALT, because no limit exceeded
|
||||||
|
})
|
||||||
|
t.Run("exceeds limit, equal", func(t *testing.T) {
|
||||||
|
args := make([]stackitem.Item, 2)
|
||||||
|
buf := stackitem.NewBuffer(make([]byte, 100500)) // takes only 1 comparable unit despite its length
|
||||||
|
for i := range args {
|
||||||
|
args[i] = stackitem.NewStruct([]stackitem.Item{
|
||||||
|
stackitem.NewByteArray(make([]byte, stackitem.MaxByteArrayComparableSize-1)), // MaxByteArrayComparableSize-1 comparable units
|
||||||
|
buf, // 1 comparable unit
|
||||||
|
buf, // 1 comparable unit
|
||||||
|
})
|
||||||
|
}
|
||||||
|
getTestFuncForVM(prog, nil, args[0], args[1])(t) // should FAULT, because limit is exceeded:
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func runWithArgs(t *testing.T, prog []byte, result interface{}, args ...interface{}) {
|
func runWithArgs(t *testing.T, prog []byte, result interface{}, args ...interface{}) {
|
||||||
getTestFuncForVM(prog, result, args...)(t)
|
getTestFuncForVM(prog, result, args...)(t)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue