Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions mrbgems/mruby-regexp/src/regexp.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,17 @@ regexp_s_byte_search(mrb_state *mrb, mrb_value klass)

mrb_get_args(mrb, "oS|ibb", &re, &str, &pos, &checked, &publish);
check_regexp_arg(mrb, re);
/* Every mrblib loop enters at zero or at an offset a match answered with,
so a position before the subject reaches here only from a direct call.
A backstop, as check_regexp_arg() above is: the answer is the miss a
position past the end already gives, rather than the read behind
RSTRING_PTR(str) that the engine would make of it. Asked before the
encoding is, as `__search` asks a position it cannot place, since a
subject the position names nothing in is not read either way. */
if (pos < 0) {
if (publish) clear_match_globals(mrb);
return mrb_nil_value();
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
if (!checked) re_check_encoding(mrb, str);
return exec_match(mrb, re, str, pos, publish);
}
Expand Down
36 changes: 36 additions & 0 deletions mrbgems/mruby-regexp/test/regexp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,42 @@
assert_false(/a/ === nil)
end

assert("Regexp.__byte_search answers a position before the subject with a miss") do
# The mrblib loops enter this at zero or at an offset a match answered with,
# so a negative one arrives only from a direct call. Left to the engine it
# would read behind the subject; the answer instead is the miss a position
# past the end already gives, and it clears the match globals the same way.
$~ = /b/.match("abc")
assert_nil Regexp.__byte_search(/b/, "abc", -1)
assert_nil $~

$~ = /b/.match("abc")
assert_nil Regexp.__byte_search(/b/, "abc", -1000000)
assert_nil $~

$~ = /b/.match("abc")
assert_nil Regexp.__byte_search(/b/, "abc", 1000000)
assert_nil $~

# and a search that publishes nothing clears nothing either, at both ends
$~ = /b/.match("abc")
assert_nil Regexp.__byte_search(/b/, "abc", -1, false, false)
assert_equal "b", $~[0]
assert_nil Regexp.__byte_search(/b/, "abc", 1000000, false, false)
assert_equal "b", $~[0]

# and it is answered before the subject is read, the way `__search` answers a
# position it cannot place: a subject the position names nothing in is not
# read either way
bad = "\xFF"
assert_nil Regexp.__byte_search(/b/, bad, -1)
if __ENCODING__ == "UTF-8"
assert_raise(ArgumentError) { Regexp.__byte_search(/b/, bad, 0) }
else
assert_nil Regexp.__byte_search(/b/, bad, 0)
end
end

assert("Regexp.escape") do
assert_equal "a\\.b\\*c", Regexp.escape("a.b*c")

Expand Down
Loading