mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-05 08:10:05 +00:00
detect stack overflows
This commit is contained in:
parent
84f7895684
commit
509823e1bc
@ -4,6 +4,7 @@
|
|||||||
#include "cchunk.h"
|
#include "cchunk.h"
|
||||||
#include "cdebug.h"
|
#include "cdebug.h"
|
||||||
#include "cmem.h"
|
#include "cmem.h"
|
||||||
|
#include "cvm.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
31
src/cstate.h
31
src/cstate.h
@ -33,6 +33,9 @@ typedef struct ArrayCObj {
|
|||||||
typedef struct CState {
|
typedef struct CState {
|
||||||
bool panic;
|
bool panic;
|
||||||
int freezeGC; // when > 0, GC events will be ignored (for internal use)
|
int freezeGC; // when > 0, GC events will be ignored (for internal use)
|
||||||
|
int frameCount;
|
||||||
|
|
||||||
|
CObjObject *protoObj; // start met obj for all objects (NULL by default)
|
||||||
CObj *objects; // tracks all of our allocated objects
|
CObj *objects; // tracks all of our allocated objects
|
||||||
CObj *userRoots; // user definable roots, this holds CObjs that should be considered "roots", lets the VM know you are holding a reference to a CObj in your code
|
CObj *userRoots; // user definable roots, this holds CObjs that should be considered "roots", lets the VM know you are holding a reference to a CObj in your code
|
||||||
ArrayCObj grayStack; // keeps track of which objects *haven't yet* been traversed in our GC, but *have been* found
|
ArrayCObj grayStack; // keeps track of which objects *haven't yet* been traversed in our GC, but *have been* found
|
||||||
@ -44,12 +47,9 @@ typedef struct CState {
|
|||||||
CTable globals;
|
CTable globals;
|
||||||
|
|
||||||
CValue *top; // top of the stack
|
CValue *top; // top of the stack
|
||||||
CValue stack[STACK_MAX]; // stack
|
|
||||||
CCallFrame callFrame[FRAME_MAX]; // call frames
|
|
||||||
int frameCount;
|
|
||||||
|
|
||||||
CObjString *iStrings[ISTRING_MAX]; // strings used internally by the VM, eg. __init, __index & friends
|
CObjString *iStrings[ISTRING_MAX]; // strings used internally by the VM, eg. __init, __index & friends
|
||||||
CObjObject *protoObj; // start met obj for all objects (NULL by default)
|
CCallFrame callFrame[FRAME_MAX]; // call frames
|
||||||
|
CValue stack[STACK_MAX]; // stack
|
||||||
} CState;
|
} CState;
|
||||||
|
|
||||||
COSMO_API CState *cosmoV_newState();
|
COSMO_API CState *cosmoV_newState();
|
||||||
@ -58,25 +58,4 @@ COSMO_API void cosmoV_register(CState *state, int pairs);
|
|||||||
COSMO_API void cosmoV_freeState(CState *state);
|
COSMO_API void cosmoV_freeState(CState *state);
|
||||||
COSMO_API void cosmoV_printStack(CState *state);
|
COSMO_API void cosmoV_printStack(CState *state);
|
||||||
|
|
||||||
// pushes value to the stack
|
|
||||||
static inline void cosmoV_pushValue(CState *state, CValue val) {
|
|
||||||
*(state->top++) = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sets stack->top to stack->top - indx
|
|
||||||
static inline StkPtr cosmoV_setTop(CState *state, int indx) {
|
|
||||||
state->top -= indx;
|
|
||||||
return state->top;
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns stack->top - indx - 1
|
|
||||||
static inline StkPtr cosmoV_getTop(CState *state, int indx) {
|
|
||||||
return &state->top[-(indx + 1)];
|
|
||||||
}
|
|
||||||
|
|
||||||
// pops 1 value off the stack
|
|
||||||
static inline StkPtr cosmoV_pop(CState *state) {
|
|
||||||
return cosmoV_setTop(state, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -18,6 +18,7 @@ COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...) {
|
|||||||
void cosmoV_error(CState *state, const char *format, ...) {
|
void cosmoV_error(CState *state, const char *format, ...) {
|
||||||
if (state->panic)
|
if (state->panic)
|
||||||
return;
|
return;
|
||||||
|
state->panic = true;
|
||||||
|
|
||||||
// print stack trace
|
// print stack trace
|
||||||
for (int i = 0; i < state->frameCount; i++) {
|
for (int i = 0; i < state->frameCount; i++) {
|
||||||
@ -50,8 +51,7 @@ void cosmoV_error(CState *state, const char *format, ...) {
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
printf("%.*s\n", errString->length, errString->str);
|
printf("%.*s\n", errString->length, errString->str);
|
||||||
cosmoV_printStack(state);
|
//cosmoV_printStack(state);
|
||||||
state->panic = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CObjUpval *captureUpvalue(CState *state, CValue *local) {
|
CObjUpval *captureUpvalue(CState *state, CValue *local) {
|
||||||
@ -90,6 +90,11 @@ void closeUpvalues(CState *state, CValue *local) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pushCallFrame(CState *state, CObjClosure *closure, int args) {
|
void pushCallFrame(CState *state, CObjClosure *closure, int args) {
|
||||||
|
if (state->frameCount >= FRAME_MAX) {
|
||||||
|
cosmoV_error(state, "Callframe overflow!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CCallFrame *frame = &state->callFrame[state->frameCount++];
|
CCallFrame *frame = &state->callFrame[state->frameCount++];
|
||||||
frame->base = state->top - args - 1; // - 1 for the function
|
frame->base = state->top - args - 1; // - 1 for the function
|
||||||
frame->pc = closure->function->chunk.buf;
|
frame->pc = closure->function->chunk.buf;
|
||||||
|
36
src/cvm.h
36
src/cvm.h
@ -23,6 +23,42 @@ COSMO_API void cosmoV_error(CState *state, const char *format, ...);
|
|||||||
|
|
||||||
// nice to have wrappers
|
// nice to have wrappers
|
||||||
|
|
||||||
|
// pushes value to the stack
|
||||||
|
static inline void cosmoV_pushValue(CState *state, CValue val) {
|
||||||
|
ptrdiff_t stackSize = state->top - state->stack;
|
||||||
|
|
||||||
|
// we reserve 8 slots for the error string and whatever c api we might be in
|
||||||
|
if (stackSize >= STACK_MAX - 8) {
|
||||||
|
if (state->panic) { // we're in a panic state, let the 8 reserved slots be filled
|
||||||
|
if (stackSize < STACK_MAX)
|
||||||
|
*(state->top++) = val;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cosmoV_error(state, "Stack overflow!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(state->top++) = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets stack->top to stack->top - indx
|
||||||
|
static inline StkPtr cosmoV_setTop(CState *state, int indx) {
|
||||||
|
state->top -= indx;
|
||||||
|
return state->top;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns stack->top - indx - 1
|
||||||
|
static inline StkPtr cosmoV_getTop(CState *state, int indx) {
|
||||||
|
return &state->top[-(indx + 1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// pops 1 value off the stack
|
||||||
|
static inline StkPtr cosmoV_pop(CState *state) {
|
||||||
|
return cosmoV_setTop(state, 1);
|
||||||
|
}
|
||||||
|
|
||||||
// pushes a cosmo_Number to the stack
|
// pushes a cosmo_Number to the stack
|
||||||
static inline void cosmoV_pushNumber(CState *state, cosmo_Number num) {
|
static inline void cosmoV_pushNumber(CState *state, cosmo_Number num) {
|
||||||
cosmoV_pushValue(state, cosmoV_newNumber(num));
|
cosmoV_pushValue(state, cosmoV_newNumber(num));
|
||||||
|
Loading…
Reference in New Issue
Block a user