diff options
-rw-r--r-- | string.c | 3 | ||||
-rw-r--r-- | test/ruby/test_string.rb | 6 |
2 files changed, 8 insertions, 1 deletions
@@ -5098,7 +5098,7 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str) cr = cr2; } plen = end0 - beg0; - rp = RSTRING_PTR(repl); rlen = RSTRING_LEN(repl); + rlen = RSTRING_LEN(repl); len = RSTRING_LEN(str); if (rlen > plen) { RESIZE_CAPA(str, len + rlen - plen); @@ -5107,6 +5107,7 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str) if (rlen != plen) { memmove(p + beg0 + rlen, p + beg0 + plen, len - beg0 - plen); } + rp = RSTRING_PTR(repl); memmove(p + beg0, rp, rlen); len += rlen - plen; STR_SET_LEN(str, len); diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 7ae3bf272e..36d246f9e0 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -2010,6 +2010,12 @@ CODE r.taint a.sub!(/./, r) assert_predicate(a, :tainted?) + + bug16105 = '[Bug #16105] heap-use-after-free' + a = S("ABCDEFGHIJKLMNOPQRSTUVWXYZ012345678") + b = a.dup + c = a.slice(1, 100) + assert_equal("AABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", b.sub!(c, b), bug16105) end def test_succ |