diff options
author | Nobuyoshi Nakada <[email protected]> | 2024-12-28 11:25:57 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <[email protected]> | 2024-12-28 11:25:57 +0900 |
commit | fb18bb183c24ca82b8f114ed090d62bd69b5df84 (patch) | |
tree | c1a34231fbb8d16e8537af5ca9805d7cc72ab0ab | |
parent | 827a19e7781ea2308787f3bb14bfe57b4fcc07f6 (diff) |
[Bug #20989] Ripper: Pass `compile_error`
For the universal parser, `rb_parser_reg_fragment_check` function is
shared between the parser and ripper. However `parser_params` struct
is partially different, and `compile_error` function depends on that
part indirectly.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/12482
-rw-r--r-- | internal/parse.h | 3 | ||||
-rw-r--r-- | parse.y | 17 | ||||
-rw-r--r-- | test/ripper/test_ripper.rb | 15 |
3 files changed, 29 insertions, 6 deletions
diff --git a/internal/parse.h b/internal/parse.h index c4df4b9377..8e04664ae8 100644 --- a/internal/parse.h +++ b/internal/parse.h @@ -78,7 +78,8 @@ void rb_parser_string_free(rb_parser_t *p, rb_parser_string_t *str); int rb_parser_dvar_defined_ref(struct parser_params*, ID, ID**); ID rb_parser_internal_id(struct parser_params*); -int rb_parser_reg_fragment_check(struct parser_params*, rb_parser_string_t*, int); +typedef void (*rb_parser_reg_fragment_error_func)(struct parser_params *, VALUE); +int rb_parser_reg_fragment_check(struct parser_params*, rb_parser_string_t*, int, rb_parser_reg_fragment_error_func); int rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len, rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc, rb_parser_assignable_func assignable); int rb_parser_local_defined(struct parser_params *p, ID id, const struct rb_iseq_struct *iseq); NODE *rb_parser_assignable(struct parser_params *p, ID id, NODE *val, const YYLTYPE *loc); @@ -1480,8 +1480,9 @@ static rb_ast_id_table_t *local_tbl(struct parser_params*); static VALUE reg_compile(struct parser_params*, rb_parser_string_t*, int); static void reg_fragment_setenc(struct parser_params*, rb_parser_string_t*, int); -#define reg_fragment_check rb_parser_reg_fragment_check -int reg_fragment_check(struct parser_params*, rb_parser_string_t*, int); +int rb_parser_reg_fragment_check(struct parser_params*, rb_parser_string_t*, int, rb_parser_reg_fragment_error_func); +static void reg_fragment_error(struct parser_params *, VALUE); +#define reg_fragment_check(p, str, option) rb_parser_reg_fragment_check(p, str, option, reg_fragment_error) static int literal_concat0(struct parser_params *p, rb_parser_string_t *head, rb_parser_string_t *tail); static NODE *heredoc_dedent(struct parser_params*,NODE*); @@ -15378,9 +15379,15 @@ reg_fragment_setenc(struct parser_params* p, rb_parser_string_t *str, int option if (c) reg_fragment_enc_error(p, str, c); } +static void +reg_fragment_error(struct parser_params* p, VALUE err) +{ + compile_error(p, "%"PRIsVALUE, err); +} + #ifndef RIPPER int -reg_fragment_check(struct parser_params* p, rb_parser_string_t *str, int options) +rb_parser_reg_fragment_check(struct parser_params* p, rb_parser_string_t *str, int options, rb_parser_reg_fragment_error_func error) { VALUE err, str2; reg_fragment_setenc(p, str, options); @@ -15389,7 +15396,7 @@ reg_fragment_check(struct parser_params* p, rb_parser_string_t *str, int options err = rb_reg_check_preprocess(str2); if (err != Qnil) { err = rb_obj_as_string(err); - compile_error(p, "%"PRIsVALUE, err); + error(p, err); return 0; } return 1; @@ -15494,7 +15501,7 @@ reg_compile(struct parser_params* p, rb_parser_string_t *str, int options) if (NIL_P(re)) { VALUE m = rb_attr_get(rb_errinfo(), idMesg); rb_set_errinfo(err); - compile_error(p, "%"PRIsVALUE, m); + reg_fragment_error(p, m); return Qnil; } return re; diff --git a/test/ripper/test_ripper.rb b/test/ripper/test_ripper.rb index 0d3e33dde6..414ce83b7d 100644 --- a/test/ripper/test_ripper.rb +++ b/test/ripper/test_ripper.rb @@ -155,6 +155,18 @@ end end; end + def test_invalid_multibyte_character_in_regexp + lex = Ripper.lex(%q[/#{"\xcd"}/]) + assert_equal([[1, 0], :on_regexp_beg, "/", state(:EXPR_BEG)], lex.shift) + assert_equal([[1, 1], :on_embexpr_beg, "\#{", state(:EXPR_BEG)], lex.shift) + assert_equal([[1, 3], :on_tstring_beg, "\"", state(:EXPR_BEG)], lex.shift) + assert_equal([[1, 4], :on_tstring_content, "\\xcd", state(:EXPR_BEG)], lex.shift) + assert_equal([[1, 8], :on_tstring_end, "\"", state(:EXPR_END)], lex.shift) + assert_equal([[1, 9], :on_embexpr_end, "}", state(:EXPR_END)], lex.shift) + assert_equal([[1, 10], :on_regexp_end, "/", state(:EXPR_BEG)], lex.shift) + assert_empty(lex) + end + def test_no_memory_leak assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true) 2_000_000.times do @@ -202,4 +214,7 @@ end end end + def state(name) + Ripper::Lexer::State.new(Ripper.const_get(name)) + end end if ripper_test |