diff options
author | Peter Zhu <[email protected]> | 2024-11-08 14:33:48 -0500 |
---|---|---|
committer | Peter Zhu <[email protected]> | 2024-11-08 15:43:41 -0500 |
commit | 51ffef281996727c60571771cd07c1459ba58cd2 (patch) | |
tree | a6b6706cb5ed5324fadf271d49ecd0a336d9a53b /prism_compile.c | |
parent | 72550d269ea89cd0bfcede7ad01a7c70ed01ba06 (diff) |
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
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/12036
Diffstat (limited to 'prism_compile.c')
-rw-r--r-- | prism_compile.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/prism_compile.c b/prism_compile.c index 53938ebb0c..f4a35fa429 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1268,11 +1268,17 @@ pm_new_child_iseq(rb_iseq_t *iseq, pm_scope_node_t *node, VALUE name, const rb_i { debugs("[new_child_iseq]> ---------------------------------------\n"); int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth; + int error_state; rb_iseq_t *ret_iseq = pm_iseq_new_with_opt(node, name, rb_iseq_path(iseq), rb_iseq_realpath(iseq), line_no, parent, isolated_depth ? isolated_depth + 1 : 0, - type, ISEQ_COMPILE_DATA(iseq)->option); + type, ISEQ_COMPILE_DATA(iseq)->option, &error_state); + + if (error_state) { + RUBY_ASSERT(ret_iseq == NULL); + rb_jump_tag(error_state); + } debugs("[new_child_iseq]< ---------------------------------------\n"); return ret_iseq; } @@ -3479,6 +3485,7 @@ pm_compile_builtin_mandatory_only_method(rb_iseq_t *iseq, pm_scope_node_t *scope pm_scope_node_t next_scope_node; pm_scope_node_init(&def.base, &next_scope_node, scope_node); + int error_state; ISEQ_BODY(iseq)->mandatory_only_iseq = pm_iseq_new_with_opt( &next_scope_node, rb_iseq_base_label(iseq), @@ -3488,9 +3495,15 @@ pm_compile_builtin_mandatory_only_method(rb_iseq_t *iseq, pm_scope_node_t *scope NULL, 0, ISEQ_TYPE_METHOD, - ISEQ_COMPILE_DATA(iseq)->option + ISEQ_COMPILE_DATA(iseq)->option, + &error_state ); + if (error_state) { + RUBY_ASSERT(ISEQ_BODY(iseq)->mandatory_only_iseq == NULL); + rb_jump_tag(error_state); + } + pm_scope_node_destroy(&next_scope_node); return COMPILE_OK; } |