diff --git a/src/cmd/gofmt/test.sh b/src/cmd/gofmt/test.sh index f21f3609a98..bed46532b87 100755 --- a/src/cmd/gofmt/test.sh +++ b/src/cmd/gofmt/test.sh @@ -36,7 +36,7 @@ apply1() { # the following files are skipped because they are test cases # for syntax errors and thus won't parse in the first place: case `basename "$F"` in - func3.go | const2.go | \ + func3.go | const2.go | char_lit1.go | \ bug014.go | bug050.go | bug068.go | bug083.go | bug088.go | \ bug106.go | bug121.go | bug125.go | bug133.go | bug160.go | \ bug163.go | bug166.go | bug169.go | bug217.go | bug222.go | \ diff --git a/src/pkg/go/scanner/scanner.go b/src/pkg/go/scanner/scanner.go index 576b95a2896..e5ac9d7729c 100644 --- a/src/pkg/go/scanner/scanner.go +++ b/src/pkg/go/scanner/scanner.go @@ -345,34 +345,43 @@ exit: } -func (S *Scanner) scanDigits(base, length int) { - for length > 0 && digitVal(S.ch) < base { - S.next() - length-- - } - if length > 0 { - S.error(S.pos, "illegal char escape") - } -} - - func (S *Scanner) scanEscape(quote int) { pos := S.pos - ch := S.ch - S.next() - switch ch { + + var i, base, max uint32 + switch S.ch { case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote: - // nothing to do + S.next() + return case '0', '1', '2', '3', '4', '5', '6', '7': - S.scanDigits(8, 3-1) // 1 char read already + i, base, max = 3, 8, 255 case 'x': - S.scanDigits(16, 2) + S.next() + i, base, max = 2, 16, 255 case 'u': - S.scanDigits(16, 4) + S.next() + i, base, max = 4, 16, unicode.MaxRune case 'U': - S.scanDigits(16, 8) + S.next() + i, base, max = 8, 16, unicode.MaxRune default: - S.error(pos, "illegal char escape") + S.next() // always make progress + S.error(pos, "unknown escape sequence") + return + } + + var x uint32 + for ; i > 0; i-- { + d := uint32(digitVal(S.ch)) + if d > base { + S.error(S.pos, "illegal character in escape sequence") + return + } + x = x*base + d + S.next() + } + if x > max || 0xd800 <= x && x < 0xe000 { + S.error(pos, "escape sequence is invalid Unicode code point") } }