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:
Peter Zhu 2023-08-09 12:18:28 -04:00
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
View file

@ -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));
} }

View file

@ -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