From 2aa6072ac0b261af2a03cc25f5713db06cb10a9d Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 12 Jun 2014 04:09:26 +0000 Subject: [PATCH 1/4] string.c: shrink too big buffer * string.c (rb_str_resize): shrink the buffer even if new length is same but it is enough smaller than the capacity. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46408 b2dd03c8-39d4-4d8f-98ff-823fe69b080e Conflicts: string.c --- string.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/string.c b/string.c index 99b7e37f58797e..d007154a2b17b5 100644 --- a/string.c +++ b/string.c @@ -2034,9 +2034,11 @@ rb_str_resize(VALUE str, long len) independent = str_independent(str); ENC_CODERANGE_CLEAR(str); slen = RSTRING_LEN(str); - if (len != slen) { + + { const int termlen = TERM_LEN(str); if (STR_EMBED_P(str)) { + if (len == slen) return str; if (len + termlen <= RSTRING_EMBED_LEN_MAX + 1) { STR_SET_EMBED_LEN(str, len); TERM_FILL(RSTRING(str)->as.ary + len, termlen); @@ -2056,11 +2058,13 @@ rb_str_resize(VALUE str, long len) return str; } else if (!independent) { + if (len == slen) return str; str_make_independent_expand(str, len - slen); } else if (slen < len || slen - len > 1024) { REALLOC_N(RSTRING(str)->as.heap.ptr, char, len + termlen); } + else if (len == slen) return str; if (!STR_NOCAPA_P(str)) { RSTRING(str)->as.heap.aux.capa = len; } From abacb9485e0c73b500dc240024c408b28d281c93 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 12 Jun 2014 04:09:41 +0000 Subject: [PATCH 2/4] file.c: shrink expanded path * file.c (expand_path): shrink expanded path which no longer needs rooms to append. [ruby-core:63114] [Bug #9934] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46410 b2dd03c8-39d4-4d8f-98ff-823fe69b080e Conflicts: ChangeLog --- file.c | 17 ++++++++++++++--- test/ruby/test_file_exhaustive.rb | 7 +++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/file.c b/file.c index 77facacfcf202a..e9e2dd134030bf 100644 --- a/file.c +++ b/file.c @@ -3397,6 +3397,16 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na #define EXPAND_PATH_BUFFER() rb_usascii_str_new(0, MAXPATHLEN + 2) +static VALUE +str_shrink(VALUE str) +{ + rb_str_resize(str, RSTRING_LEN(str)); + return str; +} + +#define expand_path(fname, dname, abs_mode, long_name, result) \ + str_shrink(rb_file_expand_path_internal(fname, dname, abs_mode, long_name, result)) + #define check_expand_path_args(fname, dname) \ (((fname) = rb_get_path(fname)), \ (void)(NIL_P(dname) ? (dname) : ((dname) = rb_get_path(dname)))) @@ -3411,13 +3421,13 @@ VALUE rb_file_expand_path(VALUE fname, VALUE dname) { check_expand_path_args(fname, dname); - return rb_file_expand_path_internal(fname, dname, 0, 1, EXPAND_PATH_BUFFER()); + return expand_path(fname, dname, 0, 1, EXPAND_PATH_BUFFER()); } VALUE rb_file_expand_path_fast(VALUE fname, VALUE dname) { - return rb_file_expand_path_internal(fname, dname, 0, 0, EXPAND_PATH_BUFFER()); + return expand_path(fname, dname, 0, 0, EXPAND_PATH_BUFFER()); } /* @@ -3465,7 +3475,7 @@ VALUE rb_file_absolute_path(VALUE fname, VALUE dname) { check_expand_path_args(fname, dname); - return rb_file_expand_path_internal(fname, dname, 1, 1, EXPAND_PATH_BUFFER()); + return expand_path(fname, dname, 1, 1, EXPAND_PATH_BUFFER()); } /* @@ -5408,6 +5418,7 @@ is_explicit_relative(const char *path) static VALUE copy_path_class(VALUE path, VALUE orig) { + str_shrink(path); RBASIC_SET_CLASS(path, rb_obj_class(orig)); OBJ_FREEZE(path); return path; diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb index 2c945eac626f19..aa9bcc9fb768a7 100644 --- a/test/ruby/test_file_exhaustive.rb +++ b/test/ruby/test_file_exhaustive.rb @@ -458,6 +458,13 @@ def test_expand_path end end + def test_expand_path_memsize + bug9934 = '[ruby-core:63114] [Bug #9934]' + require "objspace" + path = File.expand_path("/foo") + assert_operator(ObjectSpace.memsize_of(path), :<=, path.bytesize, bug9934) + end + def test_expand_path_encoding drive = (DRIVE ? 'C:' : '') if Encoding.find("filesystem") == Encoding::CP1251 From b74a7d311ad78255f3d2eb0a0edd6ba9f9b3b928 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 12 Jun 2014 11:33:12 +0000 Subject: [PATCH 3/4] string.c: consider capacity * string.c (rb_str_resize): should consider the capacity instead of the old length, as pointed out by nagachika. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46413 b2dd03c8-39d4-4d8f-98ff-823fe69b080e Conflicts: ChangeLog --- string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/string.c b/string.c index d007154a2b17b5..bd1e3bcfdd5cec 100644 --- a/string.c +++ b/string.c @@ -2061,7 +2061,7 @@ rb_str_resize(VALUE str, long len) if (len == slen) return str; str_make_independent_expand(str, len - slen); } - else if (slen < len || slen - len > 1024) { + else if (slen < len || (RSTRING(str)->as.heap.aux.capa - len) > (len < 1024 ? len : 1024)) { REALLOC_N(RSTRING(str)->as.heap.ptr, char, len + termlen); } else if (len == slen) return str; From 97c12cc312387ab9fc695bb80162a2366e3de143 Mon Sep 17 00:00:00 2001 From: tmm1 Date: Fri, 13 Jun 2014 00:00:03 +0000 Subject: [PATCH 4/4] add more test coverage for [ruby-core:63136] [Bug #9934] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46414 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/ruby/test_file_exhaustive.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb index aa9bcc9fb768a7..a64a956afd73d8 100644 --- a/test/ruby/test_file_exhaustive.rb +++ b/test/ruby/test_file_exhaustive.rb @@ -463,6 +463,8 @@ def test_expand_path_memsize require "objspace" path = File.expand_path("/foo") assert_operator(ObjectSpace.memsize_of(path), :<=, path.bytesize, bug9934) + path = File.expand_path("/a"*25) + assert_equal(51, ObjectSpace.memsize_of(path), bug9934) end def test_expand_path_encoding