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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
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;
 | 
			
		||||
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);
 | 
			
		||||
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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								node.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								node.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1299,7 +1299,7 @@ rb_ast_t *
 | 
			
		|||
rb_ast_new(void)
 | 
			
		||||
{
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -494,4 +494,11 @@ class TestGc < Test::Unit::TestCase
 | 
			
		|||
    b = 1000.times.map { Object.new.object_id }
 | 
			
		||||
    assert_empty(a & b)
 | 
			
		||||
  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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue