Repository: jhump/protoreflect (go)

Issue:
protoparse: zero bytes in comments should be verboten
protoparse is out of sync with protoc in that it allows `0x00` bytes in comments. 

This is similar to #442 except it deals with comments.


Pull request description:
forbid 0x00 bytes in comments
fixes #448

This is similar to #447 except it deal with comments and the only character that `protoparse` handles differently from `protoc` in comments is `0x00`

Patch:
diff --git a/desc/protoparse/lexer.go b/desc/protoparse/lexer.go
index f2694be..155126c 100644
--- a/desc/protoparse/lexer.go
+++ b/desc/protoparse/lexer.go
@@ -335,7 +335,10 @@ func (l *protoLex) Lex(lval *protoSymType) int {
 			}
 			if cn == '/' {
 				l.adjustPos(cn)
-				hitNewline := l.skipToEndOfLineComment()
+				hitNewline, hasErr := l.skipToEndOfLineComment(lval)
+				if hasErr {
+					return _ERROR
+				}
 				comment := l.newComment()
 				comment.PosRange.End.Col++
 				if hitNewline {
@@ -349,12 +352,15 @@ func (l *protoLex) Lex(lval *protoSymType) int {
 			}
 			if cn == '*' {
 				l.adjustPos(cn)
-				if ok := l.skipToEndOfBlockComment(); !ok {
+				ok, hasErr := l.skipToEndOfBlockComment(lval)
+				if hasErr {
+					return _ERROR
+				}
+				if !ok {
 					l.setError(lval, errors.New("block comment never terminates, unexpected EOF"))
 					return _ERROR
-				} else {
-					l.comments = append(l.comments, l.newComment())
 				}
+				l.comments = append(l.comments, l.newComment())
 				continue
 			}
 			l.input.unreadRune(cn)
@@ -747,34 +753,42 @@ func (l *protoLex) readStringLiteral(quote rune) (string, error) {
 	return buf.String(), nil
 }
 
-func (l *protoLex) skipToEndOfLineComment() bool {
+func (l *protoLex) skipToEndOfLineComment(lval *protoSymType) (ok, hasErr bool) {
 	for {
 		c, _, err := l.input.readRune()
 		if err != nil {
-			return false
+			return false, false
 		}
-		if c == '\n' {
-			return true
+		switch c {
+		case '\n':
+			return true, false
+		case 0:
+			l.setError(lval, errors.New("invalid control character"))
+			return false, true
 		}
 		l.adjustPos(c)
 	}
 }
 
-func (l *protoLex) skipToEndOfBlockComment() bool {
+func (l *protoLex) skipToEndOfBlockComment(lval *protoSymType) (ok, hasErr bool) {
 	for {
 		c, _, err := l.input.readRune()
 		if err != nil {
-			return false
+			return false, false
+		}
+		if c == 0 {
+			l.setError(lval, errors.New("invalid control character"))
+			return false, true
 		}
 		l.adjustPos(c)
 		if c == '*' {
 			c, _, err := l.input.readRune()
 			if err != nil {
-				return false
+				return false, false
 			}
 			if c == '/' {
 				l.adjustPos(c)
-				return true
+				return true, false
 			}
 			l.input.unreadRune(c)
 		}


Test patch:
diff --git a/desc/protoparse/lexer_test.go b/desc/protoparse/lexer_test.go
index 0695170..fdf8538 100644
--- a/desc/protoparse/lexer_test.go
+++ b/desc/protoparse/lexer_test.go
@@ -259,6 +259,8 @@ func TestLexerErrors(t *testing.T) {
 		{str: "^", errMsg: "invalid character"},
 		{str: "\uAAAA", errMsg: "invalid character"},
 		{str: "\U0010FFFF", errMsg: "invalid character"},
+		{str: "// foo \x00", errMsg: "invalid control character"},
+		{str: "/* foo \x00", errMsg: "invalid control character"},
 	}
 	for i, tc := range testCases {
 		l := newTestLexer(strings.NewReader(tc.str))