Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions progressbar.go
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,10 @@ func (p *ProgressBar) Add64(num int64) error {
return errors.New("max must be greater than 0")
}

if !p.config.ignoreLength && p.state.currentNum+num > p.config.max {
return errors.New("current number exceeds max")
}

if p.state.currentNum < p.config.max {
if p.config.ignoreLength {
p.state.currentNum = (p.state.currentNum + num) % p.config.max
Expand Down Expand Up @@ -774,9 +778,6 @@ func (p *ProgressBar) Add64(num int64) error {
updateBar := p.state.currentPercent != p.state.lastPercent && p.state.currentPercent > 0

p.state.lastPercent = p.state.currentPercent
if p.state.currentNum > p.config.max {
return errors.New("current number exceeds max")
}

// always update if show bytes/second or its/second
if updateBar || p.config.showIterationsPerSecond || p.config.showIterationsCount {
Expand Down
28 changes: 28 additions & 0 deletions progressbar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,34 @@ func TestBar(t *testing.T) {
}
}

func TestAddExceedsMaxDoesNotCorruptState(t *testing.T) {
bar := NewOptions(100, OptionSetWriter(io.Discard))

if err := bar.Add(95); err != nil {
t.Fatalf("unexpected error: %v", err)
}

if err := bar.Add(10); err == nil {
t.Error("should have an error for adding past max")
}

// A rejected Add must leave state untouched, not partially applied.
if bar.state.currentNum != 95 {
t.Errorf("expected currentNum to stay at 95 after a rejected Add, got %d", bar.state.currentNum)
}
if bar.state.currentPercent != 95 {
t.Errorf("expected currentPercent to stay at 95 after a rejected Add, got %d", bar.state.currentPercent)
}

// The bar must still accept further, non-overshooting progress afterwards.
if err := bar.Add(5); err != nil {
t.Errorf("bar should still accept progress after a rejected Add, got error: %v", err)
}
if bar.state.currentNum != 100 {
t.Errorf("expected currentNum to reach 100, got %d", bar.state.currentNum)
}
}

func TestState(t *testing.T) {
bar := NewOptions(100, OptionSetWidth(10))
bar.Reset()
Expand Down