mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
[Bug #20990] Reject escaped multibyte char with control/meta prefix
This commit is contained in:
parent
0ccc7657f3
commit
e4ec2128ae
Notes:
git
2024-12-28 14:34:53 +00:00
4 changed files with 51 additions and 1 deletions
4
parse.y
4
parse.y
|
@ -8231,6 +8231,10 @@ read_escape(struct parser_params *p, int flags, const char *begin)
|
||||||
return '\0';
|
return '\0';
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if (!ISASCII(c)) {
|
||||||
|
tokskip_mbchar(p);
|
||||||
|
goto eof;
|
||||||
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9657,7 +9657,8 @@ escape_read_warn(pm_parser_t *parser, uint8_t flags, uint8_t flag, const char *t
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expression_buffer, uint8_t flags) {
|
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 '\\': {
|
case '\\': {
|
||||||
parser->current.end++;
|
parser->current.end++;
|
||||||
escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\\', flags));
|
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 */
|
/* fallthrough */
|
||||||
default: {
|
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) {
|
if (parser->current.end < parser->end) {
|
||||||
escape_write_escape_encoded(parser, buffer, regular_expression_buffer, flags);
|
escape_write_escape_encoded(parser, buffer, regular_expression_buffer, flags);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -355,6 +355,15 @@ world"
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_lexer(expected, code)
|
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
|
end
|
||||||
|
|
||||||
def test_invalid_escape_meta_mbchar
|
def test_invalid_escape_meta_mbchar
|
||||||
|
@ -366,6 +375,15 @@ world"
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_lexer(expected, code)
|
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
|
end
|
||||||
|
|
||||||
def test_invalid_escape_meta_ctrl_mbchar
|
def test_invalid_escape_meta_ctrl_mbchar
|
||||||
|
@ -377,6 +395,15 @@ world"
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_lexer(expected, code)
|
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
|
end
|
||||||
|
|
||||||
def test_invalid_escape_ctrl_meta_mbchar
|
def test_invalid_escape_ctrl_meta_mbchar
|
||||||
|
@ -388,6 +415,15 @@ world"
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_lexer(expected, code)
|
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
|
end
|
||||||
|
|
||||||
def test_invalid_escape_string
|
def test_invalid_escape_string
|
||||||
|
|
|
@ -97,6 +97,10 @@ class TestRubyLiteral < Test::Unit::TestCase
|
||||||
assert_equal "ab", eval("?a 'b'")
|
assert_equal "ab", eval("?a 'b'")
|
||||||
assert_equal "a\nb", eval("<<A 'b'\na\nA")
|
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
|
ensure
|
||||||
$VERBOSE = verbose_bak
|
$VERBOSE = verbose_bak
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue