summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Zhu <[email protected]>2024-05-01 10:01:02 -0400
committerPeter Zhu <[email protected]>2024-05-01 11:09:54 -0400
commit7ef8bb129ff16750429a7ede4397d0622954ca35 (patch)
treeca28b571c649a0750db0bab47b67464e19466cb7
parente9e41ad6b0b94e69e375cb2cef84e7a241d7ef56 (diff)
Fix memory leak in Ripper.sexp
rb_ast_dispose does not free the rb_ast_t causing it to be leaked. This commit changes it to use rb_ast_free instead. For example: require "ripper" 10.times do 100_000.times do Ripper.sexp("") end puts `ps -o rss= -p #{$$}` end Before: 27648 32512 37376 42240 47232 52224 57344 62208 67072 71936 After: 22784 22784 22784 22784 22912 22912 22912 22912 22912 22912
-rw-r--r--parse.y2
-rw-r--r--test/ripper/test_ripper.rb8
2 files changed, 9 insertions, 1 deletions
diff --git a/parse.y b/parse.y
index 521d24787b..f406bb43b7 100644
--- a/parse.y
+++ b/parse.y
@@ -16076,7 +16076,7 @@ rb_ruby_ripper_parse0(rb_parser_t *p)
parser_prepare(p);
p->ast = rb_ast_new();
ripper_yyparse((void*)p);
- rb_ast_dispose(p->ast);
+ rb_ast_free(p->ast);
p->ast = 0;
p->eval_tree = 0;
p->eval_tree_begin = 0;
diff --git a/test/ripper/test_ripper.rb b/test/ripper/test_ripper.rb
index 6061496d9c..f129a41be9 100644
--- a/test/ripper/test_ripper.rb
+++ b/test/ripper/test_ripper.rb
@@ -170,6 +170,14 @@ end
end;
end
+ def test_sexp_no_memory_leak
+ assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
+ 1_000_000.times do
+ Ripper.sexp("")
+ end
+ end;
+ end
+
class TestInput < self
Input = Struct.new(:lines) do
def gets