From 90aa6aefc4e351d3840cfd58872c5f42a11f4c7a Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 15 Oct 2024 15:46:23 -0400 Subject: [PATCH] Fix memory leak in syntax error in prism If there is a syntax error, there could be an ast_node in the result. This could get leaked if there is a syntax error so parsing could not complete (parsed is not set to true). For example, the following script leaks memory: 10.times do 10_000.times do eval("def foo(...) super(...) {}; end") rescue SyntaxError end puts `ps -o rss= -p #{$$}` end Before: 31328 42768 53856 65120 76208 86768 97856 109120 120208 131296 After: 20944 20944 20944 20944 20944 20944 20944 20944 20944 20944 --- prism_compile.c | 4 +++- test/ruby/test_syntax.rb | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index aca358f871..04fc96e990 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -10118,9 +10118,11 @@ pm_iseq_compile_node(rb_iseq_t *iseq, pm_scope_node_t *node) void pm_parse_result_free(pm_parse_result_t *result) { - if (result->parsed) { + if (result->node.ast_node != NULL) { pm_node_destroy(&result->parser, result->node.ast_node); + } + if (result->parsed) { xfree(result->node.constants); pm_scope_node_destroy(&result->node); } diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index 7a6c66d782..edf5886a53 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -2204,6 +2204,20 @@ eom assert_syntax_error('def foo(...) super(1, ...) {}; end', /both block arg and actual block/) end + def test_argument_forwarding_with_super_memory_leak + assert_no_memory_leak([], "#{<<-'begin;'}", "#{<<-'end;'}", rss: true) + code = proc do + eval("def foo(...) super(...) {}; end") + raise "unreachable" + rescue SyntaxError + end + + 1_000.times(&code) + begin; + 100_000.times(&code) + end; + end + def test_class_module_Object_ancestors assert_separately([], <<-RUBY) m = Module.new