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.
This commit is contained in:
Aaron Patterson 2021-05-24 14:23:45 -07:00 коммит произвёл Aaron Patterson
Родитель af43198738
Коммит 8fdb15fdd3
1 изменённых файлов: 36 добавлений и 7 удалений

43
gc.c
Просмотреть файл

@ -1794,6 +1794,8 @@ heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj
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)
{
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