summaryrefslogtreecommitdiff
path: root/prism_compile.c
diff options
context:
space:
mode:
authorPeter Zhu <[email protected]>2024-11-08 14:33:48 -0500
committerPeter Zhu <[email protected]>2024-11-08 15:43:41 -0500
commit51ffef281996727c60571771cd07c1459ba58cd2 (patch)
treea6b6706cb5ed5324fadf271d49ecd0a336d9a53b /prism_compile.c
parent72550d269ea89cd0bfcede7ad01a7c70ed01ba06 (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.c17
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;
}