summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--ext/-test-/string/modify.c8
-rw-r--r--include/ruby/intern.h1
-rw-r--r--string.c16
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 <nobu@ruby-lang.org>
+
+ * string.c (rb_str_modify_expand): fix memory leak.
+
Wed Feb 8 14:06:59 2012 Hiroshi Nakamura <nahi@ruby-lang.org>
* 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);
}