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
This commit is contained in:
Peter Zhu 2024-11-08 14:33:48 -05:00
parent 72550d269e
commit 51ffef2819
Notes: git 2024-11-08 20:43:59 +00:00
8 changed files with 130 additions and 25 deletions

9
ruby.c
View file

@ -2609,8 +2609,15 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
if (!result.ast) {
pm_parse_result_t *pm = &result.prism;
iseq = pm_iseq_new_main(&pm->node, opt->script_name, path, parent, optimize);
int error_state;
iseq = pm_iseq_new_main(&pm->node, opt->script_name, path, parent, optimize, &error_state);
pm_parse_result_free(pm);
if (error_state) {
RUBY_ASSERT(iseq == NULL);
rb_jump_tag(error_state);
}
}
else {
rb_ast_t *ast = result.ast;