From 51ffef281996727c60571771cd07c1459ba58cd2 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 8 Nov 2024 14:33:48 -0500 Subject: Fix memory leak in prism when syntax error in iseq compilation If there's a syntax error during iseq compilation then prism would leak memory because it would not free the pm_parse_result_t. This commit changes pm_iseq_new_with_opt to have a rb_protect to catch when an error is raised, and return NULL and set error_state to a value that can be raised by calling rb_jump_tag after memory has been freed. For example: 10.times do 10_000.times do eval("/[/=~s") rescue SyntaxError end puts `ps -o rss= -p #{$$}` end Before: 39280 68736 99232 128864 158896 188208 217344 246304 275376 304592 After: 12192 13200 14256 14848 16000 16000 16000 16064 17232 17952 --- test/ruby/test_eval.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'test/ruby') diff --git a/test/ruby/test_eval.rb b/test/ruby/test_eval.rb index cf1c2bb2f6..2129272b00 100644 --- a/test/ruby/test_eval.rb +++ b/test/ruby/test_eval.rb @@ -612,4 +612,28 @@ class TestEval < Test::Unit::TestCase x = orphan_lambda assert_equal(:ok, x.call) end + + def test_syntax_error_no_memory_leak + assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", rss: true) + begin; + 100_000.times do + eval("/[/=~s") + rescue SyntaxError + else + raise "Expected SyntaxError to be raised" + end + end; + + assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", rss: true) + begin; + a = 1 + + 100_000.times do + eval("if a in [0, 0] | [0, a]; end") + rescue SyntaxError + else + raise "Expected SyntaxError to be raised" + end + end; + end end -- cgit v1.2.3