diff --git a/vlib/v/checker/tests/string_escape_u_err_a.out b/vlib/v/checker/tests/string_escape_u_err_a.out new file mode 100644 index 0000000000..607c240e5f --- /dev/null +++ b/vlib/v/checker/tests/string_escape_u_err_a.out @@ -0,0 +1,5 @@ +vlib/v/checker/tests/string_escape_u_err_a.vv:2:15: error: `\u` incomplete unicode character value + 1 | fn main() { + 2 | println('\u') + | ^ + 3 | } diff --git a/vlib/v/checker/tests/string_escape_u_err_a.vv b/vlib/v/checker/tests/string_escape_u_err_a.vv new file mode 100644 index 0000000000..ad7aee7e51 --- /dev/null +++ b/vlib/v/checker/tests/string_escape_u_err_a.vv @@ -0,0 +1,3 @@ +fn main() { + println('\u') +} diff --git a/vlib/v/checker/tests/string_escape_u_err_b.out b/vlib/v/checker/tests/string_escape_u_err_b.out new file mode 100644 index 0000000000..d81d688d14 --- /dev/null +++ b/vlib/v/checker/tests/string_escape_u_err_b.out @@ -0,0 +1,5 @@ +vlib/v/checker/tests/string_escape_u_err_b.vv:2:15: error: `\u` incomplete unicode character value + 1 | fn main() { + 2 | println('\u345') + | ^ + 3 | } diff --git a/vlib/v/checker/tests/string_escape_u_err_b.vv b/vlib/v/checker/tests/string_escape_u_err_b.vv new file mode 100644 index 0000000000..650f8d6d92 --- /dev/null +++ b/vlib/v/checker/tests/string_escape_u_err_b.vv @@ -0,0 +1,3 @@ +fn main() { + println('\u345') +} diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index 85ae34c96b..6b3bd15f9c 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -1039,11 +1039,19 @@ fn (mut s Scanner) ident_string() string { s.error(r'cannot use `\x00` (NULL character) in the string literal') } } - // Escape `\x` - if prevc == slash && - c == `x` && s.count_symbol_before(s.pos - 2, slash) % 2 == 0 && !is_raw && !is_cstr && - (s.text[s.pos + 1] == s.quote || !s.text[s.pos + 1].is_hex_digit()) { - s.error(r'`\x` used with no following hex digits') + // Escape `\x` `\u` + if prevc == slash && !is_raw && !is_cstr && s.count_symbol_before(s.pos - 2, slash) % 2 == 0 { + // Escape `\x` + if c == `x` && (s.text[s.pos + 1] == s.quote || !s.text[s.pos + 1].is_hex_digit()) { + s.error(r'`\x` used with no following hex digits') + } + // Escape `\u` + if c == `u` && (s.text[s.pos + 1] == s.quote || + s.text[s.pos + 2] == s.quote || s.text[s.pos + 3] == s.quote || s.text[s.pos + 4] == s.quote || + !s.text[s.pos + 1].is_hex_digit() || !s.text[s.pos + 2].is_hex_digit() || !s.text[s.pos + 3].is_hex_digit() || + !s.text[s.pos + 4].is_hex_digit()) { + s.error(r'`\u` incomplete unicode character value') + } } // ${var} (ignore in vfmt mode) (skip \$) if prevc == `$` && c == `{` && !is_raw && s.count_symbol_before(s.pos - 2, slash) % 2 == 0 {