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
parent
f013f9aa2f
commit
e8b1a06dad
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
/* If the error handler is set, we rewind any C stack frames and
|
/* Reset local roots before allocating anything */
|
||||||
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;
|
|
||||||
|
|
||||||
/* Reset local roots */
|
|
||||||
data_roots.clear();
|
data_roots.clear();
|
||||||
bignum_roots.clear();
|
bignum_roots.clear();
|
||||||
code_roots.clear();
|
code_roots.clear();
|
||||||
|
|
||||||
/* If we had an underflow or overflow, data or retain stack
|
/* If we had an underflow or overflow, data or retain stack
|
||||||
pointers might be out of bounds */
|
pointers might be out of bounds, so fix them before allocating
|
||||||
|
anything */
|
||||||
ctx->fix_stacks();
|
ctx->fix_stacks();
|
||||||
|
|
||||||
ctx->push(error);
|
/* 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]))
|
||||||
|
{
|
||||||
|
#ifdef FACTOR_DEBUG
|
||||||
|
/* Doing a GC here triggers all kinds of funny errors */
|
||||||
|
primitive_compact_gc();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Now its safe to allocate and GC */
|
||||||
|
cell error_object = allot_array_4(special_objects[OBJ_ERROR],
|
||||||
|
tag_fixnum(error),arg1,arg2);
|
||||||
|
|
||||||
|
ctx->push(error_object);
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue