mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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.
This commit is contained in:
parent
5219b4ddb4
commit
2c7d3b3a72
Notes:
git
2021-04-26 22:47:18 +09:00
4 changed files with 16 additions and 1 deletions
7
gc.c
7
gc.c
|
@ -2435,6 +2435,13 @@ rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
|
||||||
return newobj_of(v0, flags, v1, v2, v3, TRUE);
|
return newobj_of(v0, flags, v1, v2, v3, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rb_ast_t *
|
||||||
|
rb_imemo_ast_new(VALUE node_buffer)
|
||||||
|
{
|
||||||
|
VALUE flags = T_IMEMO | (imemo_ast << FL_USHIFT);
|
||||||
|
return (rb_ast_t *)newobj_of(node_buffer, flags, 0, 0, 0, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_imemo_tmpbuf_new(VALUE v1, VALUE v2, VALUE v3, VALUE v0)
|
rb_imemo_tmpbuf_new(VALUE v1, VALUE v2, VALUE v3, VALUE v0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -130,6 +130,7 @@ struct MEMO {
|
||||||
|
|
||||||
typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t;
|
typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t;
|
||||||
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0);
|
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0);
|
||||||
|
struct rb_ast_struct *rb_imemo_ast_new(VALUE node_buffer);
|
||||||
rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt);
|
rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt);
|
||||||
struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
|
struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
|
||||||
void rb_strterm_mark(VALUE obj);
|
void rb_strterm_mark(VALUE obj);
|
||||||
|
|
2
node.c
2
node.c
|
@ -1299,7 +1299,7 @@ rb_ast_t *
|
||||||
rb_ast_new(void)
|
rb_ast_new(void)
|
||||||
{
|
{
|
||||||
node_buffer_t *nb = rb_node_buffer_new();
|
node_buffer_t *nb = rb_node_buffer_new();
|
||||||
rb_ast_t *ast = (rb_ast_t *)rb_imemo_new(imemo_ast, 0, 0, 0, (VALUE)nb);
|
rb_ast_t *ast = rb_imemo_ast_new((VALUE)nb);
|
||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -494,4 +494,11 @@ class TestGc < Test::Unit::TestCase
|
||||||
b = 1000.times.map { Object.new.object_id }
|
b = 1000.times.map { Object.new.object_id }
|
||||||
assert_empty(a & b)
|
assert_empty(a & b)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_ast_node_buffer
|
||||||
|
# https://github.com/ruby/ruby/pull/4416
|
||||||
|
Module.new.class_eval do
|
||||||
|
eval((["# shareable_constant_value: literal"] + (0..100000).map {|i| "M#{ i } = {}" }).join("\n"))
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue