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
5 changes: 4 additions & 1 deletion mrbgems/mruby-regexp/mrblib/string_regexp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,10 @@ def split(pattern = nil, *args)
# `ary[obj]` and `"s" * obj` all reject an object that only defines
# `to_int`; dispatching it here would leave this the one place in the tree
# that accepts one, as the same reasoning keeps `match` off `to_str`.
if limit_given && !limit.is_a?(Integer)
# `is_a?` is redefinable, so a limit claiming to be an Integer would skip
# that conversion and reach the arithmetic below as itself. `Module#===`
# reads the real type and cannot be redefined.
if limit_given && !(Integer === limit)
limit = limit.__to_int
end
# `nil?` and `is_a?` are redefinable, so an argument answering either one
Expand Down
38 changes: 38 additions & 0 deletions mrbgems/mruby-regexp/test/regexp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,44 @@ def limit.respond_to?(name, include_all = false); true; end
assert_raise(TypeError) { "a,b".split(/,/, limit) }
end

class StringSplitLimitIsALiar
def is_a?(klass)
true
end
end

class StringSplitLimitComparable
def is_a?(klass)
true
end

def ==(other)
false
end

def >(other)
true
end

def -(other)
1
end
end

assert("String#split limit cannot pose as an Integer") do
# `is_a?` is redefinable, so a limit claiming to be an Integer used to skip
# the conversion and reach the split loop as itself.
assert_raise(TypeError) { "a,b,c".split(/,/, StringSplitLimitIsALiar.new) }
# The String pattern delegates to __split, which converts the limit again in
# C, so this one held before the fix too. Asserted so that the two halves of
# the method stay pinned to the same answer.
assert_raise(TypeError) { "a,b,c".split(",", StringSplitLimitIsALiar.new) }

# Answering the operators the loop uses used to produce a wrong result
# instead of an error.
assert_raise(TypeError) { "a,b,c".split(/,/, StringSplitLimitComparable.new) }
end

assert("String#split with empty regexp") do
assert_equal ["a", "b", "c"], "abc".split(//)
assert_equal ["a", "bc"], "abc".split(//, 2)
Expand Down
Loading