aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2015-06-26 13:39:09 +1000
committerRob Pike <r@golang.org>2015-06-26 23:33:39 +0000
commitaea348a3af088bc3bc05c5ee5cfc567215008f6f (patch)
tree71a4cea0edc2a71dae49e38a9f85da8f69289dfb /src
parent2b3b7dc1a96d4e23d687e1d4cc61dcb076ee3609 (diff)
downloadgo-aea348a3af088bc3bc05c5ee5cfc567215008f6f.tar.xz
cmd/asm: add tests for erroneous expressions
Also add a couple more errors, such as modulo with a zero divisor. Change-Id: If24c95477f7ae86cf4aef5b3460e9ec249ea5ae2 Reviewed-on: https://go-review.googlesource.com/11535 Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src')
-rw-r--r--src/cmd/asm/internal/asm/expr_test.go62
-rw-r--r--src/cmd/asm/internal/asm/parse.go24
2 files changed, 82 insertions, 4 deletions
diff --git a/src/cmd/asm/internal/asm/expr_test.go b/src/cmd/asm/internal/asm/expr_test.go
index 8543bab49d..eafbc5fee7 100644
--- a/src/cmd/asm/internal/asm/expr_test.go
+++ b/src/cmd/asm/internal/asm/expr_test.go
@@ -1,5 +1,3 @@
-// +build ignore
-
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -8,6 +6,7 @@ package asm
import (
"cmd/asm/internal/lex"
+ "strings"
"testing"
"text/scanner"
)
@@ -53,6 +52,8 @@ var exprTests = []exprTest{
{"3<<(2+4)", 3 << (2 + 4), true},
// Junk at EOF.
{"3 x", 3, false},
+ // Big number
+ {"4611686018427387904", 4611686018427387904, true},
}
func TestExpr(t *testing.T) {
@@ -71,3 +72,60 @@ func TestExpr(t *testing.T) {
}
}
}
+
+type badExprTest struct {
+ input string
+ error string // Empty means no error.
+}
+
+var badExprTests = []badExprTest{
+ {"0/0", "division by zero"},
+ {"3/0", "division by zero"},
+ {"(1<<63)/0", "divide of value with high bit set"},
+ {"3%0", "modulo by zero"},
+ {"(1<<63)%0", "modulo of value with high bit set"},
+ {"3<<-4", "negative left shift count"},
+ {"3<<(1<<63)", "negative left shift count"},
+ {"3>>-4", "negative right shift count"},
+ {"3>>(1<<63)", "negative right shift count"},
+ {"(1<<63)>>2", "right shift of value with high bit set"},
+ {"(1<<62)>>2", ""},
+ {`'\x80'`, "illegal UTF-8 encoding for character constant"},
+ {"(23*4", "missing closing paren"},
+ {")23*4", "unexpected ) evaluating expression"},
+ {"18446744073709551616", "value out of range"},
+}
+
+func TestBadExpr(t *testing.T) {
+ panicOnError = true
+ defer func() {
+ panicOnError = false
+ }()
+ for i, test := range badExprTests {
+ err := runBadTest(i, test, t)
+ if err == nil {
+ if test.error != "" {
+ t.Errorf("#%d: %q: expected error %q; got none", i, test.input, test.error)
+ }
+ continue
+ }
+ if !strings.Contains(err.Error(), test.error) {
+ t.Errorf("#%d: expected error %q; got %q", i, test.error, err)
+ continue
+ }
+ }
+}
+
+func runBadTest(i int, test badExprTest, t *testing.T) (err error) {
+ p := NewParser(nil, nil, nil) // Expression evaluation uses none of these fields of the parser.
+ p.start(lex.Tokenize(test.input))
+ defer func() {
+ e := recover()
+ var ok bool
+ if err, ok = e.(error); e != nil && !ok {
+ t.Fatal(e)
+ }
+ }()
+ p.expr()
+ return nil
+}
diff --git a/src/cmd/asm/internal/asm/parse.go b/src/cmd/asm/internal/asm/parse.go
index 2533256f88..1028c9208e 100644
--- a/src/cmd/asm/internal/asm/parse.go
+++ b/src/cmd/asm/internal/asm/parse.go
@@ -54,7 +54,14 @@ func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader) *Parser {
}
}
+// panicOnError is enable when testing to abort execution on the first error
+// and turn it into a recoverable panic.
+var panicOnError bool
+
func (p *Parser) errorf(format string, args ...interface{}) {
+ if panicOnError {
+ panic(fmt.Errorf(format, args...))
+ }
if p.histLineNum == p.errorLine {
// Only one error per line.
return
@@ -800,10 +807,23 @@ func (p *Parser) term() uint64 {
if int64(value) < 0 {
p.errorf("divide of value with high bit set")
}
- value /= p.factor()
+ divisor := p.factor()
+ if divisor == 0 {
+ p.errorf("division by zero")
+ } else {
+ value /= divisor
+ }
case '%':
p.next()
- value %= p.factor()
+ divisor := p.factor()
+ if int64(value) < 0 {
+ p.errorf("modulo of value with high bit set")
+ }
+ if divisor == 0 {
+ p.errorf("modulo by zero")
+ } else {
+ value %= divisor
+ }
case lex.LSH:
p.next()
shift := p.factor()