ruby-changes:66333
From: Aaron <ko1@a...>
Date: Thu, 27 May 2021 06:22:07 +0900 (JST)
Subject: [ruby-changes:66333] 8fdb15fdd3 (master): Fill out switch statement in push_mark_stack
https://git.ruby-lang.org/ruby.git/commit/?id=8fdb15fdd3 From 8fdb15fdd3ed2636d28d60153a7520256d72594e Mon Sep 17 00:00:00 2001 From: Aaron Patterson <tenderlove@r...> Date: Mon, 24 May 2021 14:23:45 -0700 Subject: Fill out switch statement in push_mark_stack When objects are popped from the mark stack, we check that the object is the right type (otherwise an rb_bug happens). The problem is that when we pop a bad object from the stack, we have no idea what pushed the bad object on the stack. This change makes an error happen when a bad object is pushed on the mark stack, that way we can track down the source of the bug. --- gc.c | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/gc.c b/gc.c index 64b16c9..3844333 100644 --- a/gc.c +++ b/gc.c @@ -1794,6 +1794,8 @@ heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj https://github.com/ruby/ruby/blob/trunk/gc.c#L1794 RVALUE *p = (RVALUE *)obj; + asan_unpoison_object(obj, false); + asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false); p->as.free.flags = 0; @@ -5863,24 +5865,51 @@ push_mark_stack(mark_stack_t *stack, VALUE data) https://github.com/ruby/ruby/blob/trunk/gc.c#L5865 { VALUE obj = data; switch (BUILTIN_TYPE(obj)) { + case T_OBJECT: + case T_CLASS: + case T_MODULE: + case T_FLOAT: + case T_STRING: + case T_REGEXP: + case T_ARRAY: + case T_HASH: + case T_STRUCT: + case T_BIGNUM: + case T_FILE: + case T_DATA: + case T_MATCH: + case T_COMPLEX: + case T_RATIONAL: + case T_TRUE: + case T_FALSE: + case T_SYMBOL: + case T_PAYLOAD: + case T_IMEMO: + case T_ICLASS: + if (stack->index == stack->limit) { + push_mark_stack_chunk(stack); + } + stack->chunk->data[stack->index++] = data; + return; + + case T_NONE: case T_NIL: case T_FIXNUM: case T_MOVED: + case T_ZOMBIE: + case T_UNDEF: + case T_MASK: rb_bug("push_mark_stack() called for broken object"); break; case T_NODE: UNEXPECTED_NODE(push_mark_stack); break; - - default: - break; } - if (stack->index == stack->limit) { - push_mark_stack_chunk(stack); - } - stack->chunk->data[stack->index++] = data; + rb_bug("rb_gc_mark(): unknown data type 0x%x(%p) %s", + BUILTIN_TYPE(obj), (void *)data, + is_pointer_to_heap(&rb_objspace, (void *)data) ? "corrupted object" : "non object"); } static int -- cgit v1.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/