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:
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);