[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'; return '\0';
default: default:
if (!ISASCII(c)) {
tokskip_mbchar(p);
goto eof;
}
return c; 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 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 {

View file

@ -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

View file

@ -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