Skip to content

Commit 2c7d3b3

Browse files
committed
node.c (rb_ast_new): imemo_ast is WB-unprotected
Previously imemo_ast was handled as WB-protected which caused a segfault of the following code: # shareable_constant_value: literal M0 = {} M1 = {} ... M100000 = {} My analysis is here: `shareable_constant_value: literal` creates many Hash instances during parsing, and add them to node_buffer of imemo_ast. However, the contents are missed because imemo_ast is incorrectly WB-protected. This changeset makes imemo_ast as WB-unprotected.
1 parent 5219b4d commit 2c7d3b3

File tree

4 files changed

+16
-1
lines changed

4 files changed

+16
-1
lines changed

gc.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2435,6 +2435,13 @@ rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
24352435
return newobj_of(v0, flags, v1, v2, v3, TRUE);
24362436
}
24372437

2438+
rb_ast_t *
2439+
rb_imemo_ast_new(VALUE node_buffer)
2440+
{
2441+
VALUE flags = T_IMEMO | (imemo_ast << FL_USHIFT);
2442+
return (rb_ast_t *)newobj_of(node_buffer, flags, 0, 0, 0, FALSE);
2443+
}
2444+
24382445
static VALUE
24392446
rb_imemo_tmpbuf_new(VALUE v1, VALUE v2, VALUE v3, VALUE v0)
24402447
{

internal/imemo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ struct MEMO {
130130

131131
typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t;
132132
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0);
133+
struct rb_ast_struct *rb_imemo_ast_new(VALUE node_buffer);
133134
rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt);
134135
struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
135136
void rb_strterm_mark(VALUE obj);

node.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1299,7 +1299,7 @@ rb_ast_t *
12991299
rb_ast_new(void)
13001300
{
13011301
node_buffer_t *nb = rb_node_buffer_new();
1302-
rb_ast_t *ast = (rb_ast_t *)rb_imemo_new(imemo_ast, 0, 0, 0, (VALUE)nb);
1302+
rb_ast_t *ast = rb_imemo_ast_new((VALUE)nb);
13031303
return ast;
13041304
}
13051305

test/ruby/test_gc.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,4 +494,11 @@ def test_object_ids_never_repeat
494494
b = 1000.times.map { Object.new.object_id }
495495
assert_empty(a & b)
496496
end
497+
498+
def test_ast_node_buffer
499+
# https://github.com/ruby/ruby/pull/4416
500+
Module.new.class_eval do
501+
eval((["# shareable_constant_value: literal"] + (0..100000).map {|i| "M#{ i } = {}" }).join("\n"))
502+
end
503+
end
497504
end

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy