summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/parse.h3
-rw-r--r--parse.y17
-rw-r--r--test/ripper/test_ripper.rb15
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);
diff --git a/parse.y b/parse.y
index cbce831c5b..b238f8d651 100644
--- a/parse.y
+++ b/parse.y
@@ -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