Check for int overflow in clist (#2289)
* explicitly panic if max capacity is reached * address review comments * comments and a test
This commit is contained in:
parent
7b88172f41
commit
1de32fba17
|
@ -22,6 +22,7 @@ BREAKING CHANGES:
|
|||
- Update field names and types in BeginBlock
|
||||
- [state] Implement BFT time
|
||||
- [p2p] update secret connection to use a little endian encoded nonce
|
||||
- [libs/clist] Panics if list extends beyond MaxLength
|
||||
|
||||
FEATURES:
|
||||
- [types] allow genesis file to have 0 validators ([#2015](https://github.com/tendermint/tendermint/issues/2015))
|
||||
|
|
|
@ -12,9 +12,15 @@ to ensure garbage collection of removed elements.
|
|||
*/
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// MaxLength is the max allowed number of elements a linked list is
|
||||
// allowed to contain.
|
||||
// If more elements are pushed to the list it will panic.
|
||||
const MaxLength = int(^uint(0) >> 1)
|
||||
|
||||
/*
|
||||
|
||||
CElement is an element of a linked-list
|
||||
|
@ -210,6 +216,7 @@ func (e *CElement) SetRemoved() {
|
|||
// CList represents a linked list.
|
||||
// The zero value for CList is an empty list ready to use.
|
||||
// Operations are goroutine-safe.
|
||||
// Panics if length grows beyond the max.
|
||||
type CList struct {
|
||||
mtx sync.RWMutex
|
||||
wg *sync.WaitGroup
|
||||
|
@ -217,6 +224,7 @@ type CList struct {
|
|||
head *CElement // first element
|
||||
tail *CElement // last element
|
||||
len int // list length
|
||||
maxLen int // max list length
|
||||
}
|
||||
|
||||
func (l *CList) Init() *CList {
|
||||
|
@ -231,7 +239,16 @@ func (l *CList) Init() *CList {
|
|||
return l
|
||||
}
|
||||
|
||||
func New() *CList { return new(CList).Init() }
|
||||
// Return CList with MaxLength. CList will panic if it goes beyond MaxLength.
|
||||
func New() *CList { return newWithMax(MaxLength) }
|
||||
|
||||
// Return CList with given maxLength.
|
||||
// Will panic if list exceeds given maxLength.
|
||||
func newWithMax(maxLength int) *CList {
|
||||
l := new(CList)
|
||||
l.maxLen = maxLength
|
||||
return l.Init()
|
||||
}
|
||||
|
||||
func (l *CList) Len() int {
|
||||
l.mtx.RLock()
|
||||
|
@ -295,6 +312,7 @@ func (l *CList) WaitChan() <-chan struct{} {
|
|||
return l.waitCh
|
||||
}
|
||||
|
||||
// Panics if list grows beyond its max length.
|
||||
func (l *CList) PushBack(v interface{}) *CElement {
|
||||
l.mtx.Lock()
|
||||
|
||||
|
@ -315,6 +333,9 @@ func (l *CList) PushBack(v interface{}) *CElement {
|
|||
l.wg.Done()
|
||||
close(l.waitCh)
|
||||
}
|
||||
if l.len >= l.maxLen {
|
||||
panic(fmt.Sprintf("clist: maximum length list reached %d", l.maxLen))
|
||||
}
|
||||
l.len++
|
||||
|
||||
// Modify the tail
|
||||
|
|
|
@ -7,9 +7,22 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
)
|
||||
|
||||
func TestPanicOnMaxLength(t *testing.T) {
|
||||
maxLength := 1000
|
||||
|
||||
l := newWithMax(maxLength)
|
||||
for i := 0; i < maxLength; i++ {
|
||||
l.PushBack(1)
|
||||
}
|
||||
assert.Panics(t, func() {
|
||||
l.PushBack(1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSmall(t *testing.T) {
|
||||
l := New()
|
||||
el1 := l.PushBack(1)
|
||||
|
|
Loading…
Reference in New Issue