mirror of
https://github.com/ruby/ruby.git
synced 2025-09-15 16:44:01 +02:00
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 ```
This commit is contained in:
parent
5bc8fceca8
commit
0b8f15575a
Notes:
git
2023-08-09 18:07:18 +00:00
2 changed files with 21 additions and 10 deletions
24
parse.y
24
parse.y
|
@ -13228,23 +13228,27 @@ local_push(struct parser_params *p, int toplevel_scope)
|
||||||
p->lvtbl = local;
|
p->lvtbl = local;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vtable_chain_free(struct parser_params *p, struct vtable *table)
|
||||||
|
{
|
||||||
|
while (!DVARS_TERMINAL_P(table)) {
|
||||||
|
struct vtable *cur_table = table;
|
||||||
|
table = cur_table->prev;
|
||||||
|
vtable_free(cur_table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
local_free(struct parser_params *p, struct local_vars *local)
|
local_free(struct parser_params *p, struct local_vars *local)
|
||||||
{
|
{
|
||||||
if (local->used) {
|
vtable_chain_free(p, local->used);
|
||||||
vtable_free(local->used);
|
|
||||||
}
|
|
||||||
|
|
||||||
# if WARN_PAST_SCOPE
|
# if WARN_PAST_SCOPE
|
||||||
while (local->past) {
|
vtable_chain_free(p, local->past);
|
||||||
struct vtable *past = local->past;
|
|
||||||
local->past = past->prev;
|
|
||||||
vtable_free(past);
|
|
||||||
}
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
vtable_free(local->args);
|
vtable_chain_free(p, local->args);
|
||||||
vtable_free(local->vars);
|
vtable_chain_free(p, local->vars);
|
||||||
|
|
||||||
ruby_sized_xfree(local, sizeof(struct local_vars));
|
ruby_sized_xfree(local, sizeof(struct local_vars));
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,6 +161,13 @@ end
|
||||||
Ripper.parse("class Foo")
|
Ripper.parse("class Foo")
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
# [Bug #19836]
|
||||||
|
assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
|
||||||
|
1_000_000.times do
|
||||||
|
Ripper.parse("-> {")
|
||||||
|
end
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
|
|
||||||
class TestInput < self
|
class TestInput < self
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue