From d22dfce1cc5e5425e062dc7883b522ef85fe06db Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 1 May 2024 15:36:36 +0900 Subject: [PATCH] Fix memory leak of `rb_ast_t` in parser Do not allocate `rb_ast_t` in `ast_alloc` to avoid memory leak. For example: 10.times do 100_000.times do eval("") end puts `ps -o rss= -p #{$$}` end Before: 17568 20960 24096 27808 31008 34160 37312 40464 43568 46816 After: 14432 14448 14496 14576 14592 15072 15072 15072 15072 15088 --- ruby_parser.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/ruby_parser.c b/ruby_parser.c index 17b98a37d7..4c981df29d 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -784,13 +784,7 @@ static const rb_data_type_t ast_data_type = { static VALUE ast_alloc(void) { - rb_ast_t *ast; - VALUE vast = TypedData_Make_Struct(0, rb_ast_t, &ast_data_type, ast); -#ifdef UNIVERSAL_PARSER - ast = (rb_ast_t *)DATA_PTR(vast); - ast->config = &rb_global_parser_config; -#endif - return vast; + return TypedData_Wrap_Struct(0, &ast_data_type, NULL); } VALUE @@ -1142,8 +1136,11 @@ parser_aset_script_lines_for(VALUE path, rb_parser_ary_t *lines) VALUE rb_ruby_ast_new(const NODE *const root) { - VALUE vast = ast_alloc(); - rb_ast_t *ast = DATA_PTR(vast); + rb_ast_t *ast; + VALUE vast = TypedData_Make_Struct(0, rb_ast_t, &ast_data_type, ast); +#ifdef UNIVERSAL_PARSER + ast->config = &rb_global_parser_config; +#endif ast->body = (rb_ast_body_t){ .root = root, .frozen_string_literal = -1,