vm: a stack underflow inside a primitive could leave a data root in an uninitialized state; if allocating the thrown underflow error triggered a GC, the GC would visit a garbage pointer

release
Slava Pestov 2010-09-17 19:20:40 -07:00
parent f013f9aa2f
commit e8b1a06dad
3 changed files with 25 additions and 27 deletions

View File

@ -137,11 +137,6 @@ void factor_vm::scrub_return_address()
frame = frame_successor(frame); frame = frame_successor(frame);
set_frame_offset(frame,0); set_frame_offset(frame,0);
#ifdef FACTOR_DEBUG
/* Doing a GC here triggers all kinds of funny errors */
primitive_compact_gc();
#endif
} }
cell factor_vm::frame_scan(stack_frame *frame) cell factor_vm::frame_scan(stack_frame *frame)

View File

@ -27,25 +27,35 @@ void out_of_memory()
exit(1); exit(1);
} }
void factor_vm::throw_error(cell error) void factor_vm::general_error(vm_error_type error, cell arg1, cell arg2)
{ {
/* Reset local roots before allocating anything */
data_roots.clear();
bignum_roots.clear();
code_roots.clear();
/* If we had an underflow or overflow, data or retain stack
pointers might be out of bounds, so fix them before allocating
anything */
ctx->fix_stacks();
/* If error was thrown during heap scan, we re-enable the GC */
gc_off = false;
/* If the error handler is set, we rewind any C stack frames and /* If the error handler is set, we rewind any C stack frames and
pass the error to user-space. */ pass the error to user-space. */
if(!current_gc && to_boolean(special_objects[ERROR_HANDLER_QUOT])) if(!current_gc && to_boolean(special_objects[ERROR_HANDLER_QUOT]))
{ {
/* If error was thrown during heap scan, we re-enable the GC */ #ifdef FACTOR_DEBUG
gc_off = false; /* Doing a GC here triggers all kinds of funny errors */
primitive_compact_gc();
#endif
/* Reset local roots */ /* Now its safe to allocate and GC */
data_roots.clear(); cell error_object = allot_array_4(special_objects[OBJ_ERROR],
bignum_roots.clear(); tag_fixnum(error),arg1,arg2);
code_roots.clear();
/* If we had an underflow or overflow, data or retain stack ctx->push(error_object);
pointers might be out of bounds */
ctx->fix_stacks();
ctx->push(error);
unwind_native_frames(special_objects[ERROR_HANDLER_QUOT], unwind_native_frames(special_objects[ERROR_HANDLER_QUOT],
ctx->callstack_top); ctx->callstack_top);
@ -55,19 +65,13 @@ void factor_vm::throw_error(cell error)
else else
{ {
std::cout << "You have triggered a bug in Factor. Please report.\n"; std::cout << "You have triggered a bug in Factor. Please report.\n";
std::cout << "early_error: "; std::cout << "error: " << error << std::endl;
print_obj(error); std::cout << "arg 1: "; print_obj(arg1); std::cout << std::endl;
std::cout << std::endl; std::cout << "arg 2: "; print_obj(arg2); std::cout << std::endl;
factorbug(); factorbug();
} }
} }
void factor_vm::general_error(vm_error_type error, cell arg1, cell arg2)
{
throw_error(allot_array_4(special_objects[OBJ_ERROR],
tag_fixnum(error),arg1,arg2));
}
void factor_vm::type_error(cell type, cell tagged) void factor_vm::type_error(cell type, cell tagged)
{ {
general_error(ERROR_TYPE,tag_fixnum(type),tagged); general_error(ERROR_TYPE,tag_fixnum(type),tagged);

View File

@ -167,7 +167,6 @@ struct factor_vm
void primitive_profiling(); void primitive_profiling();
// errors // errors
void throw_error(cell error);
void general_error(vm_error_type error, cell arg1, cell arg2); void general_error(vm_error_type error, cell arg1, cell arg2);
void type_error(cell type, cell tagged); void type_error(cell type, cell tagged);
void not_implemented_error(); void not_implemented_error();