Skip to content
This repository has been archived by the owner on Mar 19, 2021. It is now read-only.

Commit

Permalink
Fix crasher on history underflow.
Browse files Browse the repository at this point in the history
From fuzz testing: getHistory() wasn't being bounds-checked, and so
would crash if an @-token referenced before the first evaluation.
Reproducing this requires either serialized testing or clearing the
history, so the ClearHistory() needs to be called first to reproduce it
reliably.
  • Loading branch information
Devin Carraway committed Aug 8, 2018
1 parent 0bc48ea commit 7547b3e
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 3 deletions.
13 changes: 10 additions & 3 deletions compute/compute.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ ScanLoop:
_, tok, lit := s.Scan()

if lit != "@" && back > -1 && len(resHistory) > 0 {
floats.Push(getHistory(back))
if hval, err := getHistory(back); err != nil {
return 0, err
} else {
floats.Push(hval)
}
if prev == token.RPAREN || constants.IsConstant(prev.String()) {
evalUnprecedenced("*", ops, floats)
}
Expand Down Expand Up @@ -189,8 +193,11 @@ func parseOperator(lit string) *operators.Operator {
return operators.FindOperatorFromString(lit)
}

func getHistory(back int) float64 {
return resHistory[back]
func getHistory(back int) (float64, error) {
if back >= len(resHistory) {
return 0, errors.New("History underflow")
}
return resHistory[back], nil
}

func pushHistory(res float64) {
Expand Down
28 changes: 28 additions & 0 deletions compute/compute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,34 @@ func TestEvaluate(t *testing.T) {
}
}

func TestEvaluateInvalid(t *testing.T) {
tests := [][]string{
{"/"},
{"1/"},
{"1("},
{")("},
{"(()"},
{"@"},
{"@@"},
{"0", "@@"},
{"0", "@@@"},
{"@@\xa6"},
}
for i, series := range tests {
ClearHistory()
var fail error
for _, expr := range series {
if _, err := Evaluate(expr); err != nil {
fail = err
break
}
}
if fail == nil {
t.Errorf("case %d: expected error, finished successfully", i)
}
}
}

func BenchmarkEvaluate(b *testing.B) {
tests := []string{
"π",
Expand Down

0 comments on commit 7547b3e

Please sign in to comment.