summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-03 03:43:19 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-03 03:43:19 +0000
commit6ed3a3524a05dbd22cab4440dd81f7c76ea67afd (patch)
tree4aade8c63f72316022143d313bd9a0ee95c5f7b0
parentd910ce1f908a70afad5261d91fd6dec0a3708240 (diff)
merge revision(s) 46550,46557,46565,46570,46585,46595,46822: [Backport #9977] [Backport #9978] [Backport #9983]
* hash.c (ruby_setenv): fix memory leak on Windows, free environment strings block after check for the size. [ruby-dev:48323] [Bug #9977] * hash.c (env_select): fix memory leak and crash on Windows, make keys array first instead of iterating on envrion directly. [ruby-dev:48325] [Bug #9978] keys array first instead of iterating on environ directly. * hash.c (env_shift): fix memory leak on Windows, free environment strings block always. [ruby-dev:48332] [Bug #9983] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@47365 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog17
-rw-r--r--hash.c32
-rw-r--r--test/ruby/test_env.rb43
-rw-r--r--version.h2
4 files changed, 78 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 32da1f7e49..4e83f6ed0e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+Wed Sep 3 12:41:35 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (env_shift): fix memory leak on Windows, free environment
+ strings block always. [ruby-dev:48332] [Bug #9983]
+
+Wed Sep 3 12:41:35 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (env_select): fix memory leak and crash on Windows, make
+ keys array first instead of iterating on environ directly.
+ [ruby-dev:48325] [Bug #9978]
+
+Wed Sep 3 12:41:35 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (ruby_setenv): fix memory leak on Windows, free
+ environment strings block after check for the size.
+ [ruby-dev:48323] [Bug #9977]
+
Wed Sep 3 12:24:39 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* re.c (match_aref, rb_reg_regsub): consider encoding of captured
diff --git a/hash.c b/hash.c
index 30aa03101e..1ca87de1ec 100644
--- a/hash.c
+++ b/hash.c
@@ -2416,9 +2416,12 @@ ruby_setenv(const char *name, const char *value)
rb_sys_fail("ruby_setenv");
}
if (value) {
- const char* p = GetEnvironmentStringsA();
+ char* p = GetEnvironmentStringsA();
+ size_t n;
if (!p) goto fail; /* never happen */
- if (strlen(name) + 2 + strlen(value) + getenvsize(p) >= getenvblocksize()) {
+ n = strlen(name) + 2 + strlen(value) + getenvsize(p);
+ FreeEnvironmentStringsA(p);
+ if (n >= getenvblocksize()) {
goto fail; /* 2 for '=' & '\0' */
}
buf = rb_sprintf("%s=%s", name, value);
@@ -2806,24 +2809,22 @@ static VALUE
env_select(VALUE ehash)
{
VALUE result;
- char **env;
+ VALUE keys;
+ long i;
RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
rb_secure(4);
result = rb_hash_new();
- env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
- if (s) {
- VALUE k = env_str_new(*env, s-*env);
- VALUE v = env_str_new2(s+1);
- if (RTEST(rb_yield_values(2, k, v))) {
- rb_hash_aset(result, k, v);
+ keys = env_keys();
+ for (i = 0; i < RARRAY_LEN(keys); ++i) {
+ VALUE key = RARRAY_PTR(keys)[i];
+ VALUE val = rb_f_getenv(Qnil, key);
+ if (!NIL_P(val)) {
+ if (RTEST(rb_yield_values(2, key, val))) {
+ rb_hash_aset(result, key, val);
}
}
- env++;
}
- FREE_ENVIRON(environ);
return result;
}
@@ -3237,6 +3238,7 @@ static VALUE
env_shift(void)
{
char **env;
+ VALUE result = Qnil;
rb_secure(4);
env = GET_ENVIRON(environ);
@@ -3246,11 +3248,11 @@ env_shift(void)
VALUE key = env_str_new(*env, s-*env);
VALUE val = env_str_new2(getenv(RSTRING_PTR(key)));
env_delete(Qnil, key);
- return rb_assoc_new(key, val);
+ result = rb_assoc_new(key, val);
}
}
FREE_ENVIRON(environ);
- return Qnil;
+ return result;
}
/*
diff --git a/test/ruby/test_env.rb b/test/ruby/test_env.rb
index ced00c30cc..98357ba201 100644
--- a/test/ruby/test_env.rb
+++ b/test/ruby/test_env.rb
@@ -1,4 +1,5 @@
require 'test/unit'
+require_relative 'envutil'
class TestEnv < Test::Unit::TestCase
IGNORE_CASE = /bccwin|mswin|mingw/ =~ RUBY_PLATFORM
@@ -405,4 +406,46 @@ class TestEnv < Test::Unit::TestCase
}
end
end
+
+ if RUBY_PLATFORM =~ /bccwin|mswin|mingw/
+ def test_memory_leak_aset
+ bug9977 = '[ruby-dev:48323] [Bug #9977]'
+ assert_no_memory_leak([], <<-'end;', "5_000.times(&doit)", bug9977, limit: 2.0)
+ ENV.clear
+ k = 'FOO'
+ v = (ENV[k] = 'bar'*5000 rescue 'bar'*1500)
+ doit = proc {ENV[k] = v}
+ 500.times(&doit)
+ end;
+ end
+
+ def test_memory_leak_select
+ bug9978 = '[ruby-dev:48325] [Bug #9978]'
+ assert_no_memory_leak([], <<-'end;', "5_000.times(&doit)", bug9978, limit: 2.0)
+ ENV.clear
+ k = 'FOO'
+ (ENV[k] = 'bar'*5000 rescue 'bar'*1500)
+ doit = proc {ENV.select {break}}
+ 500.times(&doit)
+ end;
+ end
+
+ def test_memory_crash_select
+ assert_normal_exit(<<-'end;')
+ 1000.times {ENV["FOO#{i}"] = 'bar'}
+ ENV.select {ENV.clear}
+ end;
+ end
+
+ def test_memory_leak_shift
+ bug9983 = '[ruby-dev:48332] [Bug #9983]'
+ assert_no_memory_leak([], <<-'end;', "5_000.times(&doit)", bug9983, limit: 2.0)
+ ENV.clear
+ k = 'FOO'
+ v = (ENV[k] = 'bar'*5000 rescue 'bar'*1500)
+ doit = proc {ENV[k] = v; ENV.shift}
+ 500.times(&doit)
+ end;
+ end
+ end
end
diff --git a/version.h b/version.h
index 664db1c2b9..911cd53e4a 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
#define RUBY_VERSION "2.0.0"
#define RUBY_RELEASE_DATE "2014-09-03"
-#define RUBY_PATCHLEVEL 543
+#define RUBY_PATCHLEVEL 544
#define RUBY_RELEASE_YEAR 2014
#define RUBY_RELEASE_MONTH 9