From a500eb9f8c487c9245d82f9b3c64cd3ddf44c836 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 27 Jun 2023 14:34:03 -0400 Subject: [PATCH] Fix memory leak in Ripper The following script leaks memory in Ripper: ```ruby require "ripper" 20.times do 100_000.times do Ripper.parse("") end puts `ps -o rss= -p #{$$}` end ``` --- ext/ripper/ripper_init.c.tmpl | 1 + test/ripper/test_ripper.rb | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/ext/ripper/ripper_init.c.tmpl b/ext/ripper/ripper_init.c.tmpl index db58d64fe69e6e..32b8aa439872ec 100644 --- a/ext/ripper/ripper_init.c.tmpl +++ b/ext/ripper/ripper_init.c.tmpl @@ -33,6 +33,7 @@ ripper_parser_free2(void *ptr) { struct ripper *r = (struct ripper*)ptr; ripper_parser_free(r->p); + xfree(r); } static size_t diff --git a/test/ripper/test_ripper.rb b/test/ripper/test_ripper.rb index 76276c54effff3..a3fa0509982456 100644 --- a/test/ripper/test_ripper.rb +++ b/test/ripper/test_ripper.rb @@ -141,6 +141,14 @@ def test_dedent_string assert_nothing_raised { Ripper.lex src } end + def test_no_memory_leak + assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true) + 10_000_000.times do + Ripper.parse("") + end + end; + end + class TestInput < self Input = Struct.new(:lines) do def gets