From d581e6816681899766d79b222be6d50a018ff4a6 Mon Sep 17 00:00:00 2001 From: CPunch Date: Sun, 28 May 2023 12:16:00 -0500 Subject: [PATCH] proper error handling for dump edgecases --- src/cdump.c | 109 ++++++++++++++++++++++++++++++-------------------- src/cundump.c | 9 +++-- 2 files changed, 71 insertions(+), 47 deletions(-) diff --git a/src/cdump.c b/src/cdump.c index 745dcf7..ebc2187 100644 --- a/src/cdump.c +++ b/src/cdump.c @@ -4,6 +4,7 @@ #include "cmem.h" #include "cobj.h" #include "cvalue.h" +#include "cvm.h" typedef struct { @@ -13,7 +14,12 @@ typedef struct int writerStatus; } DumpState; -static void writeCValue(DumpState *dstate, CValue val); +static bool writeCValue(DumpState *dstate, CValue val); + +#define check(e) \ + if (!e) { \ + return false; \ + } static void initDumpState(CState *state, DumpState *dstate, cosmo_Writer writer, const void *userData) @@ -24,82 +30,92 @@ static void initDumpState(CState *state, DumpState *dstate, cosmo_Writer writer, dstate->writerStatus = 0; } -static void writeBlock(DumpState *dstate, const void *data, size_t size) +static bool writeBlock(DumpState *dstate, const void *data, size_t size) { if (dstate->writerStatus == 0) { dstate->writerStatus = dstate->writer(dstate->state, data, size, dstate->userData); } + + return dstate->writerStatus == 0; } -static void writeu8(DumpState *dstate, uint8_t d) +static bool writeu8(DumpState *dstate, uint8_t d) { - writeBlock(dstate, &d, sizeof(uint8_t)); + return writeBlock(dstate, &d, sizeof(uint8_t)); } -static void writeu32(DumpState *dstate, uint32_t d) +static bool writeu32(DumpState *dstate, uint32_t d) { - writeBlock(dstate, &d, sizeof(uint32_t)); + return writeBlock(dstate, &d, sizeof(uint32_t)); } -static void writeSize(DumpState *dstate, size_t d) +static bool writeSize(DumpState *dstate, size_t d) { - writeBlock(dstate, &d, sizeof(size_t)); + return writeBlock(dstate, &d, sizeof(size_t)); } -static void writeVector(DumpState *dstate, const void *data, size_t size, size_t count) +static bool writeVector(DumpState *dstate, const void *data, size_t size, size_t count) { - writeSize(dstate, count); - writeBlock(dstate, data, size * count); + check(writeSize(dstate, count)); + check(writeBlock(dstate, data, size * count)); + + return true; } -static void writeHeader(DumpState *dstate) +static bool writeHeader(DumpState *dstate) { - writeBlock(dstate, COSMO_MAGIC, COSMO_MAGIC_LEN); + check(writeBlock(dstate, COSMO_MAGIC, COSMO_MAGIC_LEN)); /* after the magic, we write some platform information */ - writeu8(dstate, cosmoD_isBigEndian()); - writeu8(dstate, sizeof(cosmo_Number)); - writeu8(dstate, sizeof(size_t)); - writeu8(dstate, sizeof(int)); + check(writeu8(dstate, cosmoD_isBigEndian())); + check(writeu8(dstate, sizeof(cosmo_Number))); + check(writeu8(dstate, sizeof(size_t))); + check(writeu8(dstate, sizeof(int))); + + return true; } -static void writeCObjString(DumpState *dstate, CObjString *obj) +static bool writeCObjString(DumpState *dstate, CObjString *obj) { if (obj == NULL) { /* this is in case cobjfunction's name or module strings are null */ - writeu32(dstate, 0); - return; + check(writeu32(dstate, 0)); + return true; } /* write string length */ - writeu32(dstate, obj->length); + check(writeu32(dstate, obj->length)); /* write string data */ - writeBlock(dstate, obj->str, obj->length); + check(writeBlock(dstate, obj->str, obj->length)); + + return true; } -static void writeCObjFunction(DumpState *dstate, CObjFunction *obj) +static bool writeCObjFunction(DumpState *dstate, CObjFunction *obj) { - writeCObjString(dstate, obj->name); - writeCObjString(dstate, obj->module); + check(writeCObjString(dstate, obj->name)); + check(writeCObjString(dstate, obj->module)); - writeu32(dstate, obj->args); - writeu32(dstate, obj->upvals); - writeu8(dstate, obj->variadic); + check(writeu32(dstate, obj->args)); + check(writeu32(dstate, obj->upvals)); + check(writeu8(dstate, obj->variadic)); /* write chunk info */ - writeVector(dstate, obj->chunk.buf, sizeof(uint8_t), obj->chunk.count); + check(writeVector(dstate, obj->chunk.buf, sizeof(uint8_t), obj->chunk.count)); /* write line info */ - writeVector(dstate, obj->chunk.lineInfo, sizeof(int), obj->chunk.count); + check(writeVector(dstate, obj->chunk.lineInfo, sizeof(int), obj->chunk.count)); /* write constants */ - writeSize(dstate, obj->chunk.constants.count); + check(writeSize(dstate, obj->chunk.constants.count)); for (int i = 0; i < obj->chunk.constants.count; i++) { - writeCValue(dstate, obj->chunk.constants.values[i]); + check(writeCValue(dstate, obj->chunk.constants.values[i])); } + + return true; } -static void writeCObj(DumpState *dstate, CObj *obj) +static bool writeCObj(DumpState *dstate, CObj *obj) { /* we can kind of cheat here since our parser only emits a few very limited CObjs... @@ -117,24 +133,27 @@ static void writeCObj(DumpState *dstate, CObj *obj) /* write object payload/body */ switch (t) { case COBJ_STRING: - writeCObjString(dstate, (CObjString *)obj); + check(writeCObjString(dstate, (CObjString *)obj)); break; case COBJ_FUNCTION: - writeCObjFunction(dstate, (CObjFunction *)obj); + check(writeCObjFunction(dstate, (CObjFunction *)obj)); break; default: - break; + cosmoV_error(dstate->state, "invalid cobj type: %d", t); + return false; } + + return true; } #define WRITE_VAR(dstate, type, expression) \ { \ type _tmp = expression; \ - writeBlock(dstate, &_tmp, sizeof(_tmp)); \ + check(writeBlock(dstate, &_tmp, sizeof(_tmp))); \ break; \ } -static void writeCValue(DumpState *dstate, CValue val) +static bool writeCValue(DumpState *dstate, CValue val) { CosmoType t = GET_TYPE(val); @@ -148,12 +167,16 @@ static void writeCValue(DumpState *dstate, CValue val) case COSMO_TBOOLEAN: WRITE_VAR(dstate, bool, cosmoV_readBoolean(val)) case COSMO_TREF: - writeCObj(dstate, cosmoV_readRef(val)); + check(writeCObj(dstate, cosmoV_readRef(val))); + break; + case COSMO_TNIL: /* no body */ break; - case COSMO_TNIL: /* fallthrough, no body */ default: - break; + cosmoV_error(dstate->state, "invalid value type: %d", t); + return false; } + + return true; } #undef WRITE_VAR @@ -174,8 +197,8 @@ int cosmoD_dump(CState *state, CObjFunction *func, cosmo_Writer writer, const vo DumpState dstate; initDumpState(state, &dstate, writer, userData); - writeHeader(&dstate); - writeCObjFunction(&dstate, func); + check(writeHeader(&dstate)); + check(writeCObjFunction(&dstate, func)); return dstate.writerStatus; } diff --git a/src/cundump.c b/src/cundump.c index 18e51aa..b92dbc1 100644 --- a/src/cundump.c +++ b/src/cundump.c @@ -172,10 +172,10 @@ static bool readCObj(UndumpState *udstate, CObj **obj) static bool readCValue(UndumpState *udstate, CValue *val) { - uint8_t type; - check(readu8(udstate, &type)); + uint8_t t; + check(readu8(udstate, &t)); - switch (type) { + switch (t) { case COSMO_TNUMBER: READ_VAR(udstate, val, cosmo_Number, cosmoV_newNumber) case COSMO_TBOOLEAN: @@ -190,7 +190,8 @@ static bool readCValue(UndumpState *udstate, CValue *val) *val = cosmoV_newNil(); break; default: - break; + cosmoV_error(udstate->state, "invalid value type: %d", t); + return false; } return true;