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
|
- Update field names and types in BeginBlock
|
||||||
- [state] Implement BFT time
|
- [state] Implement BFT time
|
||||||
- [p2p] update secret connection to use a little endian encoded nonce
|
- [p2p] update secret connection to use a little endian encoded nonce
|
||||||
|
- [libs/clist] Panics if list extends beyond MaxLength
|
||||||
|
|
||||||
FEATURES:
|
FEATURES:
|
||||||
- [types] allow genesis file to have 0 validators ([#2015](https://github.com/tendermint/tendermint/issues/2015))
|
- [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 (
|
import (
|
||||||
|
"fmt"
|
||||||
"sync"
|
"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
|
CElement is an element of a linked-list
|
||||||
|
@ -210,6 +216,7 @@ func (e *CElement) SetRemoved() {
|
||||||
// CList represents a linked list.
|
// CList represents a linked list.
|
||||||
// The zero value for CList is an empty list ready to use.
|
// The zero value for CList is an empty list ready to use.
|
||||||
// Operations are goroutine-safe.
|
// Operations are goroutine-safe.
|
||||||
|
// Panics if length grows beyond the max.
|
||||||
type CList struct {
|
type CList struct {
|
||||||
mtx sync.RWMutex
|
mtx sync.RWMutex
|
||||||
wg *sync.WaitGroup
|
wg *sync.WaitGroup
|
||||||
|
@ -217,6 +224,7 @@ type CList struct {
|
||||||
head *CElement // first element
|
head *CElement // first element
|
||||||
tail *CElement // last element
|
tail *CElement // last element
|
||||||
len int // list length
|
len int // list length
|
||||||
|
maxLen int // max list length
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *CList) Init() *CList {
|
func (l *CList) Init() *CList {
|
||||||
|
@ -231,7 +239,16 @@ func (l *CList) Init() *CList {
|
||||||
return l
|
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 {
|
func (l *CList) Len() int {
|
||||||
l.mtx.RLock()
|
l.mtx.RLock()
|
||||||
|
@ -295,6 +312,7 @@ func (l *CList) WaitChan() <-chan struct{} {
|
||||||
return l.waitCh
|
return l.waitCh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Panics if list grows beyond its max length.
|
||||||
func (l *CList) PushBack(v interface{}) *CElement {
|
func (l *CList) PushBack(v interface{}) *CElement {
|
||||||
l.mtx.Lock()
|
l.mtx.Lock()
|
||||||
|
|
||||||
|
@ -315,6 +333,9 @@ func (l *CList) PushBack(v interface{}) *CElement {
|
||||||
l.wg.Done()
|
l.wg.Done()
|
||||||
close(l.waitCh)
|
close(l.waitCh)
|
||||||
}
|
}
|
||||||
|
if l.len >= l.maxLen {
|
||||||
|
panic(fmt.Sprintf("clist: maximum length list reached %d", l.maxLen))
|
||||||
|
}
|
||||||
l.len++
|
l.len++
|
||||||
|
|
||||||
// Modify the tail
|
// Modify the tail
|
||||||
|
|
|
@ -7,9 +7,22 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
cmn "github.com/tendermint/tendermint/libs/common"
|
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) {
|
func TestSmall(t *testing.T) {
|
||||||
l := New()
|
l := New()
|
||||||
el1 := l.PushBack(1)
|
el1 := l.PushBack(1)
|
||||||
|
|
Loading…
Reference in New Issue