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);
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)

View File

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

View File

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