[Bug #20990] Reject escaped multibyte char with control/meta prefix

This commit is contained in:
Nobuyoshi Nakada 2024-12-28 18:40:37 +09:00
parent 0ccc7657f3
commit e4ec2128ae
No known key found for this signature in database
GPG key ID: 3582D74E1FEE4465
Notes: git 2024-12-28 14:34:53 +00:00
4 changed files with 51 additions and 1 deletions

View file

@ -8231,6 +8231,10 @@ read_escape(struct parser_params *p, int flags, const char *begin)
return '\0';
default:
if (!ISASCII(c)) {
tokskip_mbchar(p);
goto eof;
}
return c;
}
}

View file

@ -9657,7 +9657,8 @@ escape_read_warn(pm_parser_t *parser, uint8_t flags, uint8_t flag, const char *t
*/
static void
escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expression_buffer, uint8_t flags) {
switch (peek(parser)) {
uint8_t peeked = peek(parser);
switch (peeked) {
case '\\': {
parser->current.end++;
escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\\', flags));
@ -10054,6 +10055,11 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
}
/* fallthrough */
default: {
if ((flags & (PM_ESCAPE_FLAG_CONTROL | PM_ESCAPE_FLAG_META)) && !char_is_ascii_printable(peeked)) {
size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end);
pm_parser_err(parser, parser->current.start, parser->current.end + width, PM_ERR_ESCAPE_INVALID_META);
return;
}
if (parser->current.end < parser->end) {
escape_write_escape_encoded(parser, buffer, regular_expression_buffer, flags);
} else {

View file

@ -355,6 +355,15 @@ world"
]
assert_lexer(expected, code)
code = %["\\C-\\\u{3042}"]
expected = [
[[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
[[1, 1], :on_tstring_content, "\\C-\\\u{3042}", state(:EXPR_BEG)],
[[1, 8], :on_tstring_end, '"', state(:EXPR_END)],
]
assert_lexer(expected, code)
end
def test_invalid_escape_meta_mbchar
@ -366,6 +375,15 @@ world"
]
assert_lexer(expected, code)
code = %["\\M-\\\u{3042}"]
expected = [
[[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
[[1, 1], :on_tstring_content, "\\M-\\\u{3042}", state(:EXPR_BEG)],
[[1, 8], :on_tstring_end, '"', state(:EXPR_END)],
]
assert_lexer(expected, code)
end
def test_invalid_escape_meta_ctrl_mbchar
@ -377,6 +395,15 @@ world"
]
assert_lexer(expected, code)
code = %["\\M-\\C-\\\u{3042}"]
expected = [
[[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
[[1, 1], :on_tstring_content, "\\M-\\C-\\\u{3042}", state(:EXPR_BEG)],
[[1, 11], :on_tstring_end, '"', state(:EXPR_END)],
]
assert_lexer(expected, code)
end
def test_invalid_escape_ctrl_meta_mbchar
@ -388,6 +415,15 @@ world"
]
assert_lexer(expected, code)
code = %["\\C-\\M-\\\u{3042}"]
expected = [
[[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
[[1, 1], :on_tstring_content, "\\C-\\M-\\\u{3042}", state(:EXPR_BEG)],
[[1, 11], :on_tstring_end, '"', state(:EXPR_END)],
]
assert_lexer(expected, code)
end
def test_invalid_escape_string

View file

@ -97,6 +97,10 @@ class TestRubyLiteral < Test::Unit::TestCase
assert_equal "ab", eval("?a 'b'")
assert_equal "a\nb", eval("<<A 'b'\na\nA")
assert_raise(SyntaxError) {eval('"\C-' "\u3042" '"')}
assert_raise(SyntaxError) {eval('"\C-\\' "\u3042" '"')}
assert_raise(SyntaxError) {eval('"\M-' "\u3042" '"')}
assert_raise(SyntaxError) {eval('"\M-\\' "\u3042" '"')}
ensure
$VERBOSE = verbose_bak
end