summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--hash.c20
-rw-r--r--test/ruby/test_env.rb16
-rw-r--r--version.h2
4 files changed, 32 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 376e29ec62..9dd1981323 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Mon Aug 4 01:26:46 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]
+
Mon Aug 4 01:24:09 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* hash.c (ruby_setenv): fix memory leak on Windows, free
diff --git a/hash.c b/hash.c
index 723b460701..aae90f0fec 100644
--- a/hash.c
+++ b/hash.c
@@ -3139,23 +3139,21 @@ static VALUE
env_select(VALUE ehash)
{
VALUE result;
- char **env;
+ VALUE keys;
+ long i;
RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
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_AREF(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;
}
diff --git a/test/ruby/test_env.rb b/test/ruby/test_env.rb
index 5eb6717405..2b286de04e 100644
--- a/test/ruby/test_env.rb
+++ b/test/ruby/test_env.rb
@@ -418,4 +418,20 @@ class TestEnv < Test::Unit::TestCase
v = (ENV[k] = 'bar'*5000 rescue 'bar'*1500)
end;
end
+
+ def test_memory_leak_select
+ bug9978 = '[ruby-dev:48325] [Bug #9978]'
+ assert_no_memory_leak([], <<-'end;', "5_000.times {ENV.select {break}}", bug9978)
+ ENV.clear
+ k = 'FOO'
+ (ENV[k] = 'bar'*5000 rescue 'bar'*1500)
+ end;
+ end
+
+ def test_memory_crash_select
+ assert_normal_exit(<<-'end;')
+ 1000.times {ENV["FOO#{i}"] = 'bar'}
+ ENV.select {ENV.clear}
+ end;
+ end
end
diff --git a/version.h b/version.h
index e314010659..9285ccc1e8 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
#define RUBY_VERSION "2.1.2"
#define RUBY_RELEASE_DATE "2014-08-04"
-#define RUBY_PATCHLEVEL 192
+#define RUBY_PATCHLEVEL 193
#define RUBY_RELEASE_YEAR 2014
#define RUBY_RELEASE_MONTH 8