From: Rob Pike Date: Fri, 26 Jun 2015 03:39:09 +0000 (+1000) Subject: cmd/asm: add tests for erroneous expressions X-Git-Tag: go1.5beta1~85 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=aea348a3af088bc3bc05c5ee5cfc567215008f6f;p=gostls13.git 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 --- 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()