[ruby-core:75388] [Ruby trunk Bug#12355] exec, system, and spawn fail when Array#to_hash is defined and its first argument is an Array

From: dennis@...
Date: 2016-05-06 18:33:21 UTC
List: ruby-core #75388
Issue #12355 has been reported by Dennis Taylor.

----------------------------------------
Bug #12355: exec, system, and spawn fail when Array#to_hash is defined and its first argument is an Array
https://bugs.ruby-lang.org/issues/12355

* Author: Dennis Taylor
* Status: Open
* Priority: Normal
* Assignee: 
* ruby -v: 2.3.0
* Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN
----------------------------------------
When any gem which adds a to_hash method to Array is loaded (extlib, dropbox, others), Kernel.exec, Kernel.system, and Kernel.spawn will fail when you specify the program name with an array. Behold:

~~~
irb(main):001:0> ex = "/usr/local/bin/cowsay"; Kernel.exec([ex, ex], "-t", "Hello world")
Errno::ENOENT: No such file or directory - -t
        from (irb):1:in `exec'
~~~

You can duplicate it yourself in irb without loading any gems by just defining an Array#to_hash method of your own:

~~~
irb(main):001:0> class Array; def to_hash; raise "HONK"; end; end; ex = "/usr/local/bin/cowsay"; Kernel.exec([ex, ex], "-t", "Hello world")
RuntimeError: HONK
        from (irb):1:in `to_hash'
        from (irb):1:in `exec'
~~~

(Let's leave aside the issue of whether it's a good idea or not to add a to_hash method to Array in the first place; the basic language functionality should still be robust in the presence of people doing silly things.)

The problem is that, because it thinks that the first parameter is something hash-like, it assumes that it's the "env" parameter, and goes on to use the first argument to the program ("-t") as the program name. I've attached a one-line patch to process.c to fix the argument parsing; it'll ensure that the first argument is not an array before trying to convert it to a hash.

Output with the patch:

~~~
irb(main):001:0> class Array; def to_hash; raise "HONK"; end; end; ex = "/usr/local/bin/cowsay"; Kernel.exec([ex, ex], "-t", "Hello world")
 _____________ 
< Hello world >
 ------------- 
        \   ^__^
         \  (--)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
~~~

---Files--------------------------------
process-to-hash.patch (414 Bytes)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread

Prev Next