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
This commit is contained in:
Peter Zhu 2024-10-15 15:46:23 -04:00
parent 4621c9b815
commit 90aa6aefc4
Notes: git 2024-10-16 18:53:06 +00:00
2 changed files with 17 additions and 1 deletions

View File

@ -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);
}

View File

@ -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