Fix validate exception handling #473

This commit is contained in:
Nicholas Dudfield
2025-03-18 13:08:40 +07:00
parent d9659dc226
commit f3ee0dd322

View File

@@ -1278,6 +1278,38 @@ public:
}
};
/**
* Helper function to handle a JS exception by extracting its message
* and freeing any additional JSValues
*/
template <typename... JSValues>
static std::string
handleException(
JSContext* ctx,
const char* defaultMsg,
JSValues... valuesToFree)
{
// Get the actual exception object
JSValue exception = JS_GetException(ctx);
// Extract the error message property
JSValue msgProp = JS_GetPropertyStr(ctx, exception, "message");
const char* str = JS_ToCString(ctx, msgProp);
std::string result = (str != nullptr) ? str : defaultMsg;
if (str != nullptr)
JS_FreeCString(ctx, str);
JS_FreeValue(ctx, msgProp);
JS_FreeValue(ctx, exception);
// Free all additional values passed
(JS_FreeValue(ctx, valuesToFree), ...);
return result;
}
/**
* Validate that a js blob can be loaded by quickjs
*/
@@ -1299,38 +1331,15 @@ public:
JSValue obj = JS_ReadObject(
ctx, (uint8_t const*)buf, buf_len, JS_READ_OBJ_BYTECODE);
if (JS_IsException(obj))
if (JS_IsException(obj) || JS_IsUndefined(obj))
{
if (const char* str = JS_ToCString(ctx, obj); str)
{
retval.emplace(str);
JS_FreeCString(ctx, str);
}
else
{
retval.emplace("invalid bytecode");
}
JS_FreeValue(ctx, obj);
return retval;
return handleException(ctx, "invalid bytecode");
}
JSValue val = JS_EvalFunction(ctx, obj);
if (JS_IsException(val))
{
if (const char* str = JS_ToCString(ctx, val); str)
{
retval.emplace(str);
JS_FreeCString(ctx, str);
}
else
{
retval.emplace("bytecode eval failure");
}
JS_FreeValue(ctx, val);
// JS_FreeValue(ctx, obj);
return retval;
return handleException(ctx, "bytecode eval failure", obj);
}
JS_FreeValue(ctx, val);
@@ -1341,18 +1350,19 @@ public:
"\"undefined\")) "
"throw Error(\"Hook/Callback function required\")";
val = JS_Eval(vm.ctx, testCalls, sizeof(testCalls) - 1, "<qjsvm>", 0);
val = JS_Eval(vm.ctx, testCalls, strlen(testCalls), "<qjsvm>", 0);
if (JS_IsException(val))
{
if (const char* str = JS_ToCString(ctx, val); str)
{
retval.emplace(str);
JS_FreeCString(ctx, str);
}
std::string errMsg =
handleException(ctx, "Hook/Callback validation failure", obj);
return errMsg;
}
JS_FreeValue(ctx, val);
// We don't manually free the bytecode object (obj) here because
// JS_EvalFunction internally transforms it into a closure and takes
// ownership of its internal structures.
// JS_FreeValue(ctx, obj);
return retval;