diff options
author | Peter Zhu <peter@peterzhu.ca> | 2023-08-09 12:18:28 -0400 |
---|---|---|
committer | Peter Zhu <peter@peterzhu.ca> | 2023-08-09 14:06:58 -0400 |
commit | 0b8f15575a440f85ac686f5b0eae8f8b7c2b72e7 (patch) | |
tree | f0435bad733992270e673308cd59a04d0373e895 /parse.y | |
parent | 5bc8fceca8d47ed1ef9c603c6531a408de36b60c (diff) |
Fix memory leak for incomplete lambdas
[Bug #19836]
The parser does not free the chain of `struct vtable`, which causes
memory leaks.
The following script reproduces this issue:
```
10.times do
100_000.times do
Ripper.parse("-> {")
end
puts `ps -o rss= -p #{$$}`
end
```
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/8192
Diffstat (limited to 'parse.y')
-rw-r--r-- | parse.y | 24 |
1 files changed, 14 insertions, 10 deletions
@@ -13229,22 +13229,26 @@ local_push(struct parser_params *p, int toplevel_scope) } static void -local_free(struct parser_params *p, struct local_vars *local) +vtable_chain_free(struct parser_params *p, struct vtable *table) { - if (local->used) { - vtable_free(local->used); + while (!DVARS_TERMINAL_P(table)) { + struct vtable *cur_table = table; + table = cur_table->prev; + vtable_free(cur_table); } +} + +static void +local_free(struct parser_params *p, struct local_vars *local) +{ + vtable_chain_free(p, local->used); # if WARN_PAST_SCOPE - while (local->past) { - struct vtable *past = local->past; - local->past = past->prev; - vtable_free(past); - } + vtable_chain_free(p, local->past); # endif - vtable_free(local->args); - vtable_free(local->vars); + vtable_chain_free(p, local->args); + vtable_chain_free(p, local->vars); ruby_sized_xfree(local, sizeof(struct local_vars)); } |