From: "jeremyevans0 (Jeremy Evans)" Date: 2021-09-13T18:35:13+00:00 Subject: [ruby-core:105229] [Ruby master Bug#18164] Segfault after spawn when using modified ENV Issue #18164 has been updated by jeremyevans0 (Jeremy Evans). Fryguy (Jason Frey) wrote in #note-3: > Speculation ahead, but I'm at the point where I don't understand the Ruby C code anymore...but I think what's happening is, roughly: > > https://github.com/ruby/ruby/blob/ebad1e829316de48f212cd57f88639fa5ac55ee4/process.c#L2980-L2984 > > ```ruby > else { > envtbl = rb_const_get(rb_cObject, id_ENV); > envtbl = rb_to_hash_type(envtbl); > } > hide_obj(envtbl); > ``` I agree, that is a bug. It should not be looking for `Object::ENV`, it should be accessing the internal `envtbl` static variable. I'm guessing the reason it doesn't is that `envtbl` is static in `hash.c`. We probably need to add a non-static function in `hash.c` to return `envtbl` as a hash (e.g. `rb_env_to_hash`), and have the `process.c` code call that. ---------------------------------------- Bug #18164: Segfault after spawn when using modified ENV https://bugs.ruby-lang.org/issues/18164#change-93635 * Author: Fryguy (Jason Frey) * Status: Open * Priority: Normal * ruby -v: ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-darwin20] * Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN ---------------------------------------- The attached segfault.rb causes a segfault on Ruby 3.0.2 (also on 2.7.2+). This is the smallest reproducer we could get. ```ruby ENV = {} spawn({}, "true") ENV.replace({}) ``` You can also change the last line to `ENV.to_s` and it also segfaults. Note that while this script is the smallest reproducer we could get to, it's unlikely that someone might replace the ENV in this way directly. A more realistic usage scenario (which is how I found this) is using RSpec, having a spec that spawns a subprocess, using `stub_const` to have an alternate ENV, and using `Bundler.with_unbundled_env` to ensure that bundler env vars are not passed to the child process. This is demonstrated in the attached segfault_spec.rb. Here, `stub_const` effectively does the `ENV = {}` portion, and `Bundler.with_unbundled_env` does the `ENV.replace({})` portion (https://github.com/rubygems/rubygems/blob/b737e1c930aaca15618c702f10553992087e2bc4/bundler/lib/bundler.rb#L693) ---Files-------------------------------- segfault.rb (43 Bytes) segfault_spec.rb (255 Bytes) -- https://bugs.ruby-lang.org/ Unsubscribe: