Skip to content

Commit fb18bb1

Browse files
committed
[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.
1 parent 827a19e commit fb18bb1

File tree

3 files changed

+29
-6
lines changed

3 files changed

+29
-6
lines changed

internal/parse.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ void rb_parser_string_free(rb_parser_t *p, rb_parser_string_t *str);
7878

7979
int rb_parser_dvar_defined_ref(struct parser_params*, ID, ID**);
8080
ID rb_parser_internal_id(struct parser_params*);
81-
int rb_parser_reg_fragment_check(struct parser_params*, rb_parser_string_t*, int);
81+
typedef void (*rb_parser_reg_fragment_error_func)(struct parser_params *, VALUE);
82+
int rb_parser_reg_fragment_check(struct parser_params*, rb_parser_string_t*, int, rb_parser_reg_fragment_error_func);
8283
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);
8384
int rb_parser_local_defined(struct parser_params *p, ID id, const struct rb_iseq_struct *iseq);
8485
NODE *rb_parser_assignable(struct parser_params *p, ID id, NODE *val, const YYLTYPE *loc);

parse.y

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,8 +1480,9 @@ static rb_ast_id_table_t *local_tbl(struct parser_params*);
14801480

14811481
static VALUE reg_compile(struct parser_params*, rb_parser_string_t*, int);
14821482
static void reg_fragment_setenc(struct parser_params*, rb_parser_string_t*, int);
1483-
#define reg_fragment_check rb_parser_reg_fragment_check
1484-
int reg_fragment_check(struct parser_params*, rb_parser_string_t*, int);
1483+
int rb_parser_reg_fragment_check(struct parser_params*, rb_parser_string_t*, int, rb_parser_reg_fragment_error_func);
1484+
static void reg_fragment_error(struct parser_params *, VALUE);
1485+
#define reg_fragment_check(p, str, option) rb_parser_reg_fragment_check(p, str, option, reg_fragment_error)
14851486

14861487
static int literal_concat0(struct parser_params *p, rb_parser_string_t *head, rb_parser_string_t *tail);
14871488
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
1537815379
if (c) reg_fragment_enc_error(p, str, c);
1537915380
}
1538015381

15382+
static void
15383+
reg_fragment_error(struct parser_params* p, VALUE err)
15384+
{
15385+
compile_error(p, "%"PRIsVALUE, err);
15386+
}
15387+
1538115388
#ifndef RIPPER
1538215389
int
15383-
reg_fragment_check(struct parser_params* p, rb_parser_string_t *str, int options)
15390+
rb_parser_reg_fragment_check(struct parser_params* p, rb_parser_string_t *str, int options, rb_parser_reg_fragment_error_func error)
1538415391
{
1538515392
VALUE err, str2;
1538615393
reg_fragment_setenc(p, str, options);
@@ -15389,7 +15396,7 @@ reg_fragment_check(struct parser_params* p, rb_parser_string_t *str, int options
1538915396
err = rb_reg_check_preprocess(str2);
1539015397
if (err != Qnil) {
1539115398
err = rb_obj_as_string(err);
15392-
compile_error(p, "%"PRIsVALUE, err);
15399+
error(p, err);
1539315400
return 0;
1539415401
}
1539515402
return 1;
@@ -15494,7 +15501,7 @@ reg_compile(struct parser_params* p, rb_parser_string_t *str, int options)
1549415501
if (NIL_P(re)) {
1549515502
VALUE m = rb_attr_get(rb_errinfo(), idMesg);
1549615503
rb_set_errinfo(err);
15497-
compile_error(p, "%"PRIsVALUE, m);
15504+
reg_fragment_error(p, m);
1549815505
return Qnil;
1549915506
}
1550015507
return re;

test/ripper/test_ripper.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,18 @@ def test_assignable_in_regexp
155155
end;
156156
end
157157

158+
def test_invalid_multibyte_character_in_regexp
159+
lex = Ripper.lex(%q[/#{"\xcd"}/])
160+
assert_equal([[1, 0], :on_regexp_beg, "/", state(:EXPR_BEG)], lex.shift)
161+
assert_equal([[1, 1], :on_embexpr_beg, "\#{", state(:EXPR_BEG)], lex.shift)
162+
assert_equal([[1, 3], :on_tstring_beg, "\"", state(:EXPR_BEG)], lex.shift)
163+
assert_equal([[1, 4], :on_tstring_content, "\\xcd", state(:EXPR_BEG)], lex.shift)
164+
assert_equal([[1, 8], :on_tstring_end, "\"", state(:EXPR_END)], lex.shift)
165+
assert_equal([[1, 9], :on_embexpr_end, "}", state(:EXPR_END)], lex.shift)
166+
assert_equal([[1, 10], :on_regexp_end, "/", state(:EXPR_BEG)], lex.shift)
167+
assert_empty(lex)
168+
end
169+
158170
def test_no_memory_leak
159171
assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
160172
2_000_000.times do
@@ -202,4 +214,7 @@ def test_invalid_gets
202214
end
203215
end
204216

217+
def state(name)
218+
Ripper::Lexer::State.new(Ripper.const_get(name))
219+
end
205220
end if ripper_test

0 commit comments

Comments
 (0)