Browse Source

Check for int overflow in clist (#2289)

* explicitly panic if max capacity is reached

* address review comments

* comments and a test
pull/2270/merge
Ismail Khoffi 6 years ago
committed by Ethan Buchman
parent
commit
1de32fba17
3 changed files with 36 additions and 1 deletions
  1. +1
    -0
      CHANGELOG_PENDING.md
  2. +22
    -1
      libs/clist/clist.go
  3. +13
    -0
      libs/clist/clist_test.go

+ 1
- 0
CHANGELOG_PENDING.md View File

@ -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))


+ 22
- 1
libs/clist/clist.go View File

@ -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


+ 13
- 0
libs/clist/clist_test.go View File

@ -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…
Cancel
Save