浏览代码

Fix crash in character literal lexing (#6805)

When lexing a hash-prefixed character literal, the lexer assumed that
the hash level of escape sequences inside the literal was zero, which
allowed unclosed escape sequences inside the literal which crashed the
compiler.

Closes #6799
Ilya 1 月之前
父节点
当前提交
6304df1db9
共有 2 个文件被更改,包括 46 次插入5 次删除
  1. 2 1
      toolchain/lex/string_literal.cpp
  2. 44 4
      toolchain/lex/testdata/char_literals.carbon

+ 2 - 1
toolchain/lex/string_literal.cpp

@@ -503,7 +503,8 @@ auto StringLiteral::ComputeCharLiteralValue(
   buffer.resize_for_overwrite(content_.size());
 
   auto result = ExpandEscapeSequencesAndRemoveIndent(
-      emitter, content_, 0, /*indent=*/llvm::StringRef(), buffer.data());
+      emitter, content_, hash_level_, /*indent=*/llvm::StringRef(),
+      buffer.data());
   CARBON_CHECK(result.size() <= content_.size(),
                "Content grew from {0} to {1}: `{2}`", content_.size(),
                result.size(), content_);

+ 44 - 4
toolchain/lex/testdata/char_literals.carbon

@@ -82,26 +82,66 @@
 #'a'#
 // CHECK:STDOUT:   - { index:  7, kind: "CharLiteral", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "#'a'#", has_leading_space: true }
 
+// CHECK:STDERR: fail_invalid.carbon:[[@LINE+4]]:1: error: unexpected `#` before character literal [CharLiteralRaw]
+// CHECK:STDERR: #'\'#
+// CHECK:STDERR: ^
+// CHECK:STDERR:
+#'\'#
+// CHECK:STDOUT:   - { index:  8, kind: "CharLiteral", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "#'\\'#", has_leading_space: true }
+
+// CHECK:STDERR: fail_invalid.carbon:[[@LINE+8]]:1: error: unexpected `#` before character literal [CharLiteralRaw]
+// CHECK:STDERR: ##''##
+// CHECK:STDERR: ^
+// CHECK:STDERR:
+// CHECK:STDERR: fail_invalid.carbon:[[@LINE+4]]:1: error: empty character literal [CharLiteralEmpty]
+// CHECK:STDERR: ##''##
+// CHECK:STDERR: ^
+// CHECK:STDERR:
+##''##
+// CHECK:STDOUT:   - { index:  9, kind:       "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "##''##", has_leading_space: true }
+
+// CHECK:STDERR: fail_invalid.carbon:[[@LINE+8]]:1: error: unexpected `#` before character literal [CharLiteralRaw]
+// CHECK:STDERR: #'foo\'#
+// CHECK:STDERR: ^
+// CHECK:STDERR:
+// CHECK:STDERR: fail_invalid.carbon:[[@LINE+4]]:1: error: too many characters [CharLiteralOverflow]
+// CHECK:STDERR: #'foo\'#
+// CHECK:STDERR: ^
+// CHECK:STDERR:
+#'foo\'#
+// CHECK:STDOUT:   - { index: 10, kind:       "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "#'foo\\'#", has_leading_space: true }
+
+// CHECK:STDERR: fail_invalid.carbon:[[@LINE+8]]:1: error: unexpected `#` before character literal [CharLiteralRaw]
+// CHECK:STDERR: ##'#\'##
+// CHECK:STDERR: ^
+// CHECK:STDERR:
+// CHECK:STDERR: fail_invalid.carbon:[[@LINE+4]]:1: error: too many characters [CharLiteralOverflow]
+// CHECK:STDERR: ##'#\'##
+// CHECK:STDERR: ^
+// CHECK:STDERR:
+##'#\'##
+// CHECK:STDOUT:   - { index: 11, kind:       "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "##'#\\'##", has_leading_space: true }
+
 // CHECK:STDERR: fail_invalid.carbon:[[@LINE+4]]:1: error: character literal is missing a terminator [UnterminatedString]
 // CHECK:STDERR: '
 // CHECK:STDERR: ^
 // CHECK:STDERR:
 '
-// CHECK:STDOUT:   - { index:  8, kind:       "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "'", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 12, kind:       "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "'", has_leading_space: true }
 
 // CHECK:STDERR: fail_invalid.carbon:[[@LINE+4]]:1: error: character literal is missing a terminator [UnterminatedString]
 // CHECK:STDERR: '\'
 // CHECK:STDERR: ^
 // CHECK:STDERR:
 '\'
-// CHECK:STDOUT:   - { index:  9, kind:       "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "'\\'", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 13, kind:       "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "'\\'", has_leading_space: true }
 
 // CHECK:STDERR: fail_invalid.carbon:[[@LINE+4]]:1: error: character literal is missing a terminator [UnterminatedString]
 // CHECK:STDERR: '\
 // CHECK:STDERR: ^
 // CHECK:STDERR:
 '\
-// CHECK:STDOUT:   - { index: 10, kind:       "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "'\\", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 14, kind:       "Error", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "'\\", has_leading_space: true }
 
 // This literal contains a raw tab character.
 // CHECK:STDERR: fail_invalid.carbon:[[@LINE+4]]:2: error: whitespace other than plain space must be expressed with an escape sequence in a string literal [InvalidHorizontalWhitespaceInString]
@@ -109,4 +149,4 @@
 // CHECK:STDERR:  ^~~~
 // CHECK:STDERR:
 '	'
-// CHECK:STDOUT:   - { index: 11, kind: "CharLiteral", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "'\t'", has_leading_space: true }
+// CHECK:STDOUT:   - { index: 15, kind: "CharLiteral", line: {{ *}}[[@LINE-1]], column:   1, indent: 1, spelling: "'\t'", has_leading_space: true }