summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2021-09-13 11:59:04 -0700
committerJeremy Evans <code@jeremyevans.net>2021-09-14 05:55:14 -0900
commit57d315c937e79199af2b77f21f5eecaca85ffac8 (patch)
tree2cb1f5530720afa596debc33a3d4c4ac10ca422c
parent616d6717589abb30a5c67c79cbf874693c3dadbd (diff)
Handle overwriting Object::ENV in spawn
Instead of looking for Object::ENV (which can be overwritten), directly look for the envtbl variable. As that is static in hash.c, and the lookup code is in process.c, add a couple non-static functions that will return envtbl (or envtbl#to_hash). Fixes [Bug #18164]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4834
-rw-r--r--hash.c12
-rw-r--r--process.c11
-rw-r--r--test/ruby/test_process.rb12
3 files changed, 30 insertions, 5 deletions
diff --git a/hash.c b/hash.c
index f75e39430c5..fd21a99be08 100644
--- a/hash.c
+++ b/hash.c
@@ -6182,6 +6182,18 @@ env_to_hash(void)
return hash;
}
+VALUE
+rb_envtbl(void)
+{
+ return envtbl;
+}
+
+VALUE
+rb_env_to_hash(void)
+{
+ return env_to_hash();
+}
+
/*
* call-seq:
* ENV.to_hash -> hash of name/value pairs
diff --git a/process.c b/process.c
index 8c0f11259be..2e4040061b4 100644
--- a/process.c
+++ b/process.c
@@ -177,6 +177,9 @@ static void check_uid_switch(void);
static void check_gid_switch(void);
static int exec_async_signal_safe(const struct rb_execarg *, char *, size_t);
+VALUE rb_envtbl(void);
+VALUE rb_env_to_hash(void);
+
#if 1
#define p_uid_from_name p_uid_from_name
#define p_gid_from_name p_gid_from_name
@@ -315,7 +318,7 @@ static ID id_pgroup;
#ifdef _WIN32
static ID id_new_pgroup;
#endif
-static ID id_unsetenv_others, id_chdir, id_umask, id_close_others, id_ENV;
+static ID id_unsetenv_others, id_chdir, id_umask, id_close_others;
static ID id_nanosecond, id_microsecond, id_millisecond, id_second;
static ID id_float_microsecond, id_float_millisecond, id_float_second;
static ID id_GETTIMEOFDAY_BASED_CLOCK_REALTIME, id_TIME_BASED_CLOCK_REALTIME;
@@ -2978,8 +2981,7 @@ rb_execarg_parent_start1(VALUE execarg_obj)
envtbl = rb_hash_new();
}
else {
- envtbl = rb_const_get(rb_cObject, id_ENV);
- envtbl = rb_to_hash_type(envtbl);
+ envtbl = rb_env_to_hash();
}
hide_obj(envtbl);
if (envopts != Qfalse) {
@@ -3591,7 +3593,7 @@ save_env(struct rb_execarg *sargp)
if (!sargp)
return;
if (sargp->env_modification == Qfalse) {
- VALUE env = rb_const_get(rb_cObject, id_ENV);
+ VALUE env = rb_envtbl();
if (RTEST(env)) {
VALUE ary = hide_obj(rb_ary_new());
rb_block_call(env, idEach, 0, 0, save_env_i,
@@ -9061,7 +9063,6 @@ Init_process(void)
id_chdir = rb_intern_const("chdir");
id_umask = rb_intern_const("umask");
id_close_others = rb_intern_const("close_others");
- id_ENV = rb_intern_const("ENV");
id_nanosecond = rb_intern_const("nanosecond");
id_microsecond = rb_intern_const("microsecond");
id_millisecond = rb_intern_const("millisecond");
diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb
index 80d2eefca9b..07aa58418b7 100644
--- a/test/ruby/test_process.rb
+++ b/test/ruby/test_process.rb
@@ -261,6 +261,18 @@ class TestProcess < Test::Unit::TestCase
}
end
+ def test_overwrite_ENV
+ assert_separately([],"#{<<~"begin;"}\n#{<<~"end;"}")
+ BUG = "[ruby-core:105223] [Bug #18164]"
+ begin;
+ $VERBOSE = nil
+ ENV = {}
+ pid = spawn({}, *#{TRUECOMMAND.inspect})
+ ENV.replace({})
+ assert_kind_of(Integer, pid, BUG)
+ end;
+ end
+
MANDATORY_ENVS = %w[RUBYLIB MJIT_SEARCH_BUILD_DIR]
case RbConfig::CONFIG['target_os']
when /linux/