quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

commit 8329d100a28c53f7a1ba083df7892e80447167b5
parent 3e9a2ad56852144b243254f0f5adb1eaf132f76b
Author: Florian Dold <dold@taler.net>
Date:   Sun,  9 Aug 2026 21:10:38 +0200

quickjs: harden custom native helpers

Diffstat:
Mquickjs/quickjs-libc.c | 19+++++++++++--------
Mquickjs/quickjs.c | 22++++++++++++++++++++--
2 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/quickjs/quickjs-libc.c b/quickjs/quickjs-libc.c @@ -581,15 +581,15 @@ static JSValue js_std_writeFile(JSContext *ctx, JSValueConst this_val, } if (bytes_written != data_len) { - JS_ThrowReferenceError(ctx, "could not write all bytes"); + ret = JS_ThrowReferenceError(ctx, "could not write all bytes"); goto done; } done: + if (file && fclose(file) != 0 && !JS_IsException(ret)) { + ret = JS_ThrowReferenceError(ctx, "could not close '%s'", filename_buf); + } JS_FreeCString(ctx, filename_buf); JS_FreeCString(ctx, data_buf); - if (file) { - fclose(file); - } return ret; } @@ -2429,7 +2429,7 @@ static void handle_http_resp(void *cls, struct JSHttpResponseInfo *resp_info) ret = write(hp->write_fd, &ch, 1); if (ret == 1) break; - if (ret < 0 && (errno != EAGAIN || errno != EINTR)) + if (ret < 0 && errno != EAGAIN && errno != EINTR) break; } } @@ -4727,7 +4727,7 @@ js_os_post_message_from_host(JSContext *ctx, const char *msg_str) ret = write(hp->write_fd, &ch, 1); if (ret == 1) break; - if (ret < 0 && (errno != EAGAIN || errno != EINTR)) + if (ret < 0 && errno != EAGAIN && errno != EINTR) break; } } @@ -4753,8 +4753,11 @@ static JSValue js_os_simulateHostMessage(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } - js_os_post_message_from_host(ctx, s); - + int ret = js_os_post_message_from_host(ctx, s); + JS_FreeCString(ctx, s); + if (ret != 0) { + return JS_ThrowInternalError(ctx, "could not post host message"); + } return JS_UNDEFINED; } diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c @@ -72,7 +72,7 @@ #define CONFIG_ATOMICS #endif -#if !defined(__EMSCRIPTEN__) && !defined(__APPLE__) +#if !defined(__EMSCRIPTEN__) /* enable stack limitation */ #define CONFIG_STACK_CHECK #endif @@ -8959,6 +8959,9 @@ int JS_HasPropertyStr(JSContext *ctx, JSValueConst obj, const char *propname) JSAtom atom; int ret; atom = JS_NewAtom(ctx, propname); + if (atom == JS_ATOM_NULL) { + return -1; + } ret = JS_HasProperty(ctx, obj, atom); JS_FreeAtom(ctx, atom); return ret; @@ -42809,6 +42812,10 @@ int qjs_array_append_new(JSContext *ctx, JSValue this_val, JSValue item) int64_t len, from, newLen; obj = JS_ToObject(ctx, this_val); + if (JS_IsException(obj)) { + JS_FreeValue(ctx, item); + return -1; + } if (js_get_length64(ctx, &len, obj)) goto exception; newLen = len + 1; @@ -59913,14 +59920,25 @@ static int typed_array_init(JSContext *ctx, JSValueConst obj, JSValue JS_NewTypedArraySimple(JSContext *ctx, JSValue array_buf, size_t bytes_per_element) { JSValue obj; - JSObject *p = JS_VALUE_GET_OBJ(array_buf); + JSObject *p; JSArrayBuffer *abuf = NULL; + if (bytes_per_element != 1) { + JS_FreeValue(ctx, array_buf); + return JS_ThrowRangeError(ctx, "only byte arrays are supported"); + } + if (JS_VALUE_GET_TAG(array_buf) != JS_TAG_OBJECT) { + JS_FreeValue(ctx, array_buf); + return JS_ThrowTypeError(ctx, "expected array buffer"); + } + p = JS_VALUE_GET_OBJ(array_buf); if (p->class_id != JS_CLASS_ARRAY_BUFFER) { + JS_FreeValue(ctx, array_buf); return JS_ThrowTypeError(ctx, "expected array buffer"); } abuf = p->u.array_buffer; if (abuf->detached) { + JS_FreeValue(ctx, array_buf); return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); } obj = JS_NewObjectClass(ctx, JS_CLASS_UINT8_ARRAY);