summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-03-11 10:22:34 +0900
committerGitHub <[email protected]>2017-03-11 10:22:34 +0900
commitf9ed15d899edaa2393ea4d07c7862746cdfa06fc (patch)
tree53e250597a3adcce9a38edb49e6e15d5c4652020
parent431f474ba34a485281692ab08df16d4f7daa8750 (diff)
parent7590482d4873474f7a435f2533831358bca80a97 (diff)
downloadmruby-f9ed15d899edaa2393ea4d07c7862746cdfa06fc.tar.gz
mruby-f9ed15d899edaa2393ea4d07c7862746cdfa06fc.zip
Merge pull request #3496 from ksss/string-gsub
Avoid infinity loop when empty string pattern
-rw-r--r--mrblib/string.rb25
-rw-r--r--test/t/string.rb1
2 files changed, 16 insertions, 10 deletions
diff --git a/mrblib/string.rb b/mrblib/string.rb
index 6f698e321..7add360a8 100644
--- a/mrblib/string.rb
+++ b/mrblib/string.rb
@@ -54,17 +54,22 @@ class String
# ISO 15.2.10.5.18
def gsub(*args, &block)
if args.size == 2
- s = ""
- i = 0
- while j = index(args[0], i)
- seplen = args[0].length
- k = j + seplen
- pre = self[0, j]
- post = self[k, length-k]
- s += self[i, j-i] + args[1].__sub_replace(pre, args[0], post)
- i = k
+ pattern, replace = *args
+ plen = pattern.length
+ replace = replace.to_str
+ offset = 0
+ result = []
+ while found = index(pattern, offset)
+ result << self[offset, found - offset]
+ offset = found + plen
+ result << replace.__sub_replace(self[0, found], pattern, self[offset..-1] || "")
+ if plen == 0
+ result << self[offset, 1]
+ offset += 1
+ end
end
- s + self[i, length-i]
+ result << self[offset..-1] if offset < length
+ result.join
elsif args.size == 1 && block
split(args[0], -1).join(block.call(args[0]))
else
diff --git a/test/t/string.rb b/test/t/string.rb
index ace6638cf..25c599ad4 100644
--- a/test/t/string.rb
+++ b/test/t/string.rb
@@ -366,6 +366,7 @@ assert('String#gsub', '15.2.10.5.18') do
assert_equal('A', 'a'.gsub('a', 'A'))
assert_equal('A', 'a'.gsub('a'){|w| w.capitalize })
assert_equal("<a><><>", 'a'.gsub('a', '<\0><\1><\2>'))
+ assert_equal(".h.e.l.l.o.", "hello".gsub("", "."))
end
assert('String#gsub with backslash') do