From 50ace992c75724aac6765b944f9017e21901e276 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Mon, 12 Feb 2024 13:16:25 -0500 Subject: [PATCH] [Bug #20234] Fix segv when parsing begin statement in method definition In a method definition, the `begin` may not have an `nd_body`. When that happens we get a null expr back from `last_expr_node` which causes a segv for the following examples: ```ruby def (begin;end).foo; end def (begin;else;end).foo; end def (begin;ensure;else;end).foo; end ``` In addition, I've added tests for other cases that weren't causing a segv but appeared untested.` Fixes https://bugs.ruby-lang.org/issues/20234 --- parse.y | 2 +- test/ruby/test_parse.rb | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/parse.y b/parse.y index 36803394fdde8f..bee79c9f6c51bf 100644 --- a/parse.y +++ b/parse.y @@ -1415,7 +1415,7 @@ last_expr_node(NODE *expr) if (nd_type_p(expr, NODE_BLOCK)) { expr = RNODE_BLOCK(RNODE_BLOCK(expr)->nd_end)->nd_head; } - else if (nd_type_p(expr, NODE_BEGIN)) { + else if (nd_type_p(expr, NODE_BEGIN) && RNODE_BEGIN(expr)->nd_body) { expr = RNODE_BEGIN(expr)->nd_body; } else { diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index e74406b84348cb..a8abccb1f937b3 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -1109,6 +1109,16 @@ def test_unused_variable assert_warning('') {o.instance_eval("def marg2((a)); nil; end")} end + def test_parsing_begin_statement_inside_method_definition + assert_equal :bug_20234, eval("def (begin;end).bug_20234; end") + assert_equal :bug_20234, eval("def (begin;rescue;end).bug_20234; end") + assert_equal :bug_20234, eval("def (begin;ensure;end).bug_20234; end") + assert_equal :bug_20234, eval("def (begin;rescue;else;end).bug_20234; end") + + assert_raise(SyntaxError) { eval("def (begin;else;end).bug_20234; end") } + assert_raise(SyntaxError) { eval("def (begin;ensure;else;end).bug_20234; end") } + end + def test_named_capture_conflict a = 1 assert_warning('') {eval("a = 1; /(?)/ =~ ''")}