From 190b017fc6c21ff7b61c2b5ece0294785e4a4ca2 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 21 Nov 2025 17:26:08 -0500 Subject: [PATCH 1/3] Don't use non blocking pipes for RUBY_CRASH_REPORT [Bug #21703] RUBY_CRASH_REPORT does not work in some cases when shelling out on Linux. For example, given the following shell script dump.sh: #!/usr/bin/env bash cat > /tmp/crash And we see it fails like this: $ RUBY_CRASH_REPORT="|dump.sh" ruby -rfiddle -e "Fiddle::Pointer.new(1, 10)[0]" cat: -: Resource temporarily unavailable --- io.c | 7 ++++++- test/ruby/test_rubyoptions.rb | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/io.c b/io.c index 2605207f2bb49a..fdd6256ff854dd 100644 --- a/io.c +++ b/io.c @@ -8079,7 +8079,12 @@ ruby_popen_writer(char *const *argv, rb_pid_t *pid) int write_pair[2]; # endif - int result = rb_cloexec_pipe(write_pair); +#ifdef HAVE_PIPE2 + int result = pipe2(write_pair, O_CLOEXEC); +#else + int result = pipe(write_pair); +#endif + *pid = -1; if (result == 0) { # ifdef HAVE_WORKING_FORK diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index 527208cee5219d..a057e64a4a3596 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -954,6 +954,27 @@ def test_crash_report_pipe end end + def test_crash_report_pipe_script + omit "only runs on Linux" unless RUBY_PLATFORM.include?("linux") + + Tempfile.create(["script", ".sh"]) do |script| + Tempfile.create("crash_report") do |crash_report| + script.write(<<~BASH) + #!/usr/bin/env bash + + cat > #{crash_report.path} + BASH + script.close + + FileUtils.chmod("+x", script) + + assert_crash_report("| #{script.path}") do + assert_include(File.read(crash_report.path), "[BUG] Segmentation fault at") + end + end + end + end + def test_DATA Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) {|t| t.puts "puts DATA.read.inspect" From 2870b7d7df30bc227f40a4c04c97050b90f1f25b Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Tue, 18 Nov 2025 09:33:55 +0100 Subject: [PATCH 2/3] [ruby/prism] Reject `p(p a, &block => value)` and similar They were being parsed as `p((p a, &block) => value)`. When we get to this point, we must not just have parsed a command call, always consuming the `=>` is not correct. Closes [Bug #21622] https://github.com/ruby/prism/commit/796ab0edf4 --- prism/prism.c | 21 ++++++++++- test/prism/errors/command_calls_35.txt | 41 +++++++++++++++++++++ test/prism/fixtures/command_method_call.txt | 6 +++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 test/prism/errors/command_calls_35.txt diff --git a/prism/prism.c b/prism/prism.c index 45817cdd8c05b2..38f3a9c6ef0f41 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -14232,6 +14232,25 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod return contains_keyword_splat; } +static inline bool +argument_allowed_for_bare_hash(pm_parser_t *parser, pm_node_t *argument) { + if (pm_symbol_node_label_p(argument)) { + return true; + } + + switch (PM_NODE_TYPE(argument)) { + case PM_CALL_NODE: { + pm_call_node_t *cast = (pm_call_node_t *) argument; + if (cast->opening_loc.start == NULL && cast->arguments != NULL) { + return false; + } + break; + } + default: break; + } + return accept1(parser, PM_TOKEN_EQUAL_GREATER); +} + /** * Append an argument to a list of arguments. */ @@ -14389,7 +14408,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for bool contains_keywords = false; bool contains_keyword_splat = false; - if (pm_symbol_node_label_p(argument) || accept1(parser, PM_TOKEN_EQUAL_GREATER)) { + if (argument_allowed_for_bare_hash(parser, argument)){ if (parsed_bare_hash) { pm_parser_err_previous(parser, PM_ERR_ARGUMENT_BARE_HASH); } diff --git a/test/prism/errors/command_calls_35.txt b/test/prism/errors/command_calls_35.txt new file mode 100644 index 00000000000000..9eb011cd86ca61 --- /dev/null +++ b/test/prism/errors/command_calls_35.txt @@ -0,0 +1,41 @@ +p(p a, x: b => value) + ^~ unexpected '=>'; expected a `)` to close the arguments + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + +p(p a, x: => value) + ^~ unexpected '=>'; expected a `)` to close the arguments + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + +p(p a, &block => value) + ^~ unexpected '=>'; expected a `)` to close the arguments + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + +p(p a, *args => value) + ^~ unexpected '=>'; expected a `)` to close the arguments + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + +p(p a, **kwargs => value) + ^~ unexpected '=>'; expected a `)` to close the arguments + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + +p p 1, &block => 2, &block + ^~ unexpected '=>', expecting end-of-input + ^~ unexpected '=>', ignoring it + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ unexpected '&', ignoring it + +p p p 1 => 2 => 3 => 4 + ^~ unexpected '=>', expecting end-of-input + ^~ unexpected '=>', ignoring it + +p[p a, x: b => value] + ^ expected a matching `]` + ^ unexpected ']', expecting end-of-input + ^ unexpected ']', ignoring it + diff --git a/test/prism/fixtures/command_method_call.txt b/test/prism/fixtures/command_method_call.txt index 182b87948b52d5..3f510efa6935d6 100644 --- a/test/prism/fixtures/command_method_call.txt +++ b/test/prism/fixtures/command_method_call.txt @@ -39,3 +39,9 @@ def foo = bar 1 !foo 1 or !bar 2 not !foo 1 + +foo(bar baz, key => value) + +foo(bar baz, KEY => value) + +foo(bar baz, :key => value) From 026140b3a209ee2608241a91bb7728a429285685 Mon Sep 17 00:00:00 2001 From: Steven Johnstone Date: Thu, 20 Nov 2025 11:31:06 +0000 Subject: [PATCH 3/3] [ruby/prism] Avoid reading out-of-bounds in pm_strnstr Fixes https://github.com/ruby/prism/pull/3738. https://github.com/ruby/prism/commit/37bb46ff5f --- prism/prism.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index 38f3a9c6ef0f41..a5475b17530907 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -22639,7 +22639,7 @@ static const char * pm_strnstr(const char *big, const char *little, size_t big_length) { size_t little_length = strlen(little); - for (const char *big_end = big + big_length; big < big_end; big++) { + for (const char *max = big + big_length - little_length; big <= max; big++) { if (*big == *little && memcmp(big, little, little_length) == 0) return big; }