Skip to content

Commit 339fad1

Browse files
committed
Merge pull request #18 from github/2.1-expandpath
Backport file_expand memory usage fix
2 parents 9574ced + 97c12cc commit 339fad1

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

file.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3397,6 +3397,16 @@ rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_na
33973397

33983398
#define EXPAND_PATH_BUFFER() rb_usascii_str_new(0, MAXPATHLEN + 2)
33993399

3400+
static VALUE
3401+
str_shrink(VALUE str)
3402+
{
3403+
rb_str_resize(str, RSTRING_LEN(str));
3404+
return str;
3405+
}
3406+
3407+
#define expand_path(fname, dname, abs_mode, long_name, result) \
3408+
str_shrink(rb_file_expand_path_internal(fname, dname, abs_mode, long_name, result))
3409+
34003410
#define check_expand_path_args(fname, dname) \
34013411
(((fname) = rb_get_path(fname)), \
34023412
(void)(NIL_P(dname) ? (dname) : ((dname) = rb_get_path(dname))))
@@ -3411,13 +3421,13 @@ VALUE
34113421
rb_file_expand_path(VALUE fname, VALUE dname)
34123422
{
34133423
check_expand_path_args(fname, dname);
3414-
return rb_file_expand_path_internal(fname, dname, 0, 1, EXPAND_PATH_BUFFER());
3424+
return expand_path(fname, dname, 0, 1, EXPAND_PATH_BUFFER());
34153425
}
34163426

34173427
VALUE
34183428
rb_file_expand_path_fast(VALUE fname, VALUE dname)
34193429
{
3420-
return rb_file_expand_path_internal(fname, dname, 0, 0, EXPAND_PATH_BUFFER());
3430+
return expand_path(fname, dname, 0, 0, EXPAND_PATH_BUFFER());
34213431
}
34223432

34233433
/*
@@ -3465,7 +3475,7 @@ VALUE
34653475
rb_file_absolute_path(VALUE fname, VALUE dname)
34663476
{
34673477
check_expand_path_args(fname, dname);
3468-
return rb_file_expand_path_internal(fname, dname, 1, 1, EXPAND_PATH_BUFFER());
3478+
return expand_path(fname, dname, 1, 1, EXPAND_PATH_BUFFER());
34693479
}
34703480

34713481
/*
@@ -5408,6 +5418,7 @@ is_explicit_relative(const char *path)
54085418
static VALUE
54095419
copy_path_class(VALUE path, VALUE orig)
54105420
{
5421+
str_shrink(path);
54115422
RBASIC_SET_CLASS(path, rb_obj_class(orig));
54125423
OBJ_FREEZE(path);
54135424
return path;

string.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,9 +2034,11 @@ rb_str_resize(VALUE str, long len)
20342034
independent = str_independent(str);
20352035
ENC_CODERANGE_CLEAR(str);
20362036
slen = RSTRING_LEN(str);
2037-
if (len != slen) {
2037+
2038+
{
20382039
const int termlen = TERM_LEN(str);
20392040
if (STR_EMBED_P(str)) {
2041+
if (len == slen) return str;
20402042
if (len + termlen <= RSTRING_EMBED_LEN_MAX + 1) {
20412043
STR_SET_EMBED_LEN(str, len);
20422044
TERM_FILL(RSTRING(str)->as.ary + len, termlen);
@@ -2056,11 +2058,13 @@ rb_str_resize(VALUE str, long len)
20562058
return str;
20572059
}
20582060
else if (!independent) {
2061+
if (len == slen) return str;
20592062
str_make_independent_expand(str, len - slen);
20602063
}
2061-
else if (slen < len || slen - len > 1024) {
2064+
else if (slen < len || (RSTRING(str)->as.heap.aux.capa - len) > (len < 1024 ? len : 1024)) {
20622065
REALLOC_N(RSTRING(str)->as.heap.ptr, char, len + termlen);
20632066
}
2067+
else if (len == slen) return str;
20642068
if (!STR_NOCAPA_P(str)) {
20652069
RSTRING(str)->as.heap.aux.capa = len;
20662070
}

test/ruby/test_file_exhaustive.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,15 @@ def test_expand_path
458458
end
459459
end
460460

461+
def test_expand_path_memsize
462+
bug9934 = '[ruby-core:63114] [Bug #9934]'
463+
require "objspace"
464+
path = File.expand_path("/foo")
465+
assert_operator(ObjectSpace.memsize_of(path), :<=, path.bytesize, bug9934)
466+
path = File.expand_path("/a"*25)
467+
assert_equal(51, ObjectSpace.memsize_of(path), bug9934)
468+
end
469+
461470
def test_expand_path_encoding
462471
drive = (DRIVE ? 'C:' : '')
463472
if Encoding.find("filesystem") == Encoding::CP1251

0 commit comments

Comments
 (0)