From 83c7d9df2b0fce04c9f06911d0ed21153ba29fa2 Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 8 Feb 2012 13:30:04 +0000 Subject: [PATCH] * string.c (rb_str_modify_expand): fix memory leak. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34492 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 4 ++++ ext/-test-/string/modify.c | 8 ++++++++ include/ruby/intern.h | 1 + string.c | 16 ++++++++++++---- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 52ca0b5277..ac0341c9f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Wed Feb 8 22:29:59 2012 Nobuyoshi Nakada + + * string.c (rb_str_modify_expand): fix memory leak. + Wed Feb 8 14:06:59 2012 Hiroshi Nakamura * ext/openssl/ossl_ssl.c: Add SSL constants and allow to unset SSL diff --git a/ext/-test-/string/modify.c b/ext/-test-/string/modify.c index a6930051b6..ddd2efd8f0 100644 --- a/ext/-test-/string/modify.c +++ b/ext/-test-/string/modify.c @@ -7,8 +7,16 @@ bug_str_modify(VALUE str) return str; } +VALUE +bug_str_modify_expand(VALUE str, VALUE expand) +{ + rb_str_modify_expand(str, NUM2LONG(expand)); + return str; +} + void Init_modify(VALUE klass) { rb_define_method(klass, "modify!", bug_str_modify, 0); + rb_define_method(klass, "modify_expand!", bug_str_modify_expand, 1); } diff --git a/include/ruby/intern.h b/include/ruby/intern.h index e71db91717..e0c4710132 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -712,6 +712,7 @@ long rb_str_sublen(VALUE, long); VALUE rb_str_substr(VALUE, long, long); VALUE rb_str_subseq(VALUE, long, long); void rb_str_modify(VALUE); +void rb_str_modify_expand(VALUE, long); VALUE rb_str_freeze(VALUE); void rb_str_set_len(VALUE, long); VALUE rb_str_resize(VALUE, long); diff --git a/string.c b/string.c index 9fd2480fd3..2ce6504fe1 100644 --- a/string.c +++ b/string.c @@ -1328,12 +1328,20 @@ rb_str_modify_expand(VALUE str, long expand) if (expand < 0) { rb_raise(rb_eArgError, "negative expanding string size"); } - if (!str_independent(str) || - (expand > 0 && - (!STR_EMBED_P(str) || - RSTRING_LEN(str) + expand > RSTRING_EMBED_LEN_MAX))) { + if (!str_independent(str)) { str_make_independent_expand(str, expand); } + else if (expand > 0) { + long len = RSTRING_LEN(str); + long capa = len + expand; + if (!STR_EMBED_P(str)) { + REALLOC_N(RSTRING(str)->as.heap.ptr, char, capa+1); + RSTRING(str)->as.heap.aux.capa = capa; + } + else if (capa > RSTRING_EMBED_LEN_MAX) { + str_make_independent_expand(str, expand); + } + } ENC_CODERANGE_CLEAR(str); }