Fix Ripper memory allocation size when enabled Universal Parser
authorS-H-GAMELINKS <[email protected]>
Tue, 19 Mar 2024 15:26:54 +0000 (20 00:26 +0900)
committerYuichiro Kaneko <[email protected]>
Thu, 21 Mar 2024 09:10:02 +0000 (21 18:10 +0900)
The size of `struct parser_params` is 8 bytes difference in `ripper_s_allocate` and `rb_ruby_parser_allocate` when the universal parser is
enabled.
This causes a situation where `*r->p` is not fully initialized in `ripper_s_allocate` as shown below.

```console
(gdb) p *r->p
$2 = {heap = 0x0, lval = 0x0, yylloc = 0x0, lex = {strterm = 0x0, gets = 0x0, input = 0, string_buffer = {head = 0x0, last = 0x0}, lastlin
e = 0x0,
    nextline = 0x0, pbeg = 0x0, pcur = 0x0, pend = 0x0, ptok = 0x0, gets_ = {ptr = 0, call = 0x0}, state = EXPR_NONE, paren_nest = 0, lpar
_seen = 0,
    debug = 0, has_shebang = 0, token_seen = 0, token_info_enabled = 0, error_p = 0, cr_seen = 0, value = 0, result = 0, parsing_thread = 0, s_value = 0,
    s_lvalue = 0, s_value_stack = 2097}
````

This seems to cause `double free or corruption (!prev)` and SEGV.
So, fixing this by introduce `rb_ripper_parser_params_allocate` and `rb_ruby_parser_config` functions for Ripper, and `struct parser_params` same size is returned.

ext/ripper/ripper_init.c.tmpl
internal/parse.h
internal/ruby_parser.h
parse.y
ruby_parser.c

index 2386f54..894cbc0 100644 (file)
@@ -94,7 +94,8 @@ ripper_s_allocate(VALUE klass)
                                        &parser_data_type, r);
 
 #ifdef UNIVERSAL_PARSER
-    r->p = rb_parser_params_allocate();
+    const rb_parser_config_t *config = rb_ruby_parser_config();
+    r->p = rb_ripper_parser_params_allocate(config);
 #else
     r->p = rb_ruby_ripper_parser_allocate();
 #endif
index e05b2bc..fc78836 100644 (file)
@@ -105,6 +105,9 @@ long rb_ruby_ripper_column(rb_parser_t *p);
 long rb_ruby_ripper_token_len(rb_parser_t *p);
 rb_parser_string_t *rb_ruby_ripper_lex_lastline(rb_parser_t *p);
 VALUE rb_ruby_ripper_lex_state_name(struct parser_params *p, int state);
+#ifdef UNIVERSAL_PARSER
+rb_parser_t *rb_ripper_parser_params_allocate(const rb_parser_config_t *config);
+#endif
 struct parser_params *rb_ruby_ripper_parser_allocate(void);
 #endif