]> git.kaiwu.me - njs.git/commitdiff
Buffer: check QJS allocation sizes before narrowing
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 24 Sep 2026 22:48:09 +0000 (15:48 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Fri, 25 Sep 2026 23:00:29 +0000 (16:00 -0700)
Take a 64-bit size in qjs_buffer_alloc() and reject sizes above
QJS_BUFFER_MAX_LENGTH before converting them.  Previously, a caller
holding a wider size had to narrow it to size_t first, which truncated
it silently on 32-bit platforms.

src/qjs.h
src/qjs_buffer.c

index 69c593ab093eedbd07f72d5a037590ac28f16393..865db0d2e9a51716794ef787cfb87ed2da20bfe2 100644 (file)
--- a/src/qjs.h
+++ b/src/qjs.h
@@ -56,6 +56,9 @@ typedef struct {
 } qjs_module_t;
 
 
+#define QJS_BUFFER_MAX_LENGTH  INT32_MAX
+
+
 JSContext *qjs_new_context(JSRuntime *rt, qjs_module_t **addons);
 JSValue qjs_call_exit_hook(JSContext *ctx);
 void *qjs_chb_ctx_alloc(void *ctx, size_t size);
@@ -66,7 +69,7 @@ JSValue qjs_new_uint8_array(JSContext *ctx, int argc, JSValueConst *argv);
 JSValue qjs_new_array_buffer(JSContext *cx, uint8_t *src, size_t len);
 JSValue qjs_new_external_array_buffer(JSContext *cx, uint8_t *src, size_t len,
     int is_shared);
-JSValue qjs_buffer_alloc(JSContext *ctx, size_t size);
+JSValue qjs_buffer_alloc(JSContext *ctx, uint64_t size);
 JSValue qjs_buffer_create(JSContext *ctx, u_char *start, size_t size);
 JSValue qjs_buffer_chb_alloc(JSContext *ctx, njs_chb_t *chain);
 
index b61251353f167d234b6a22e29b312001714f4081..ade8559e37136e6ac7b11399f1bdd87617ebda53 100644 (file)
@@ -125,7 +125,7 @@ static qjs_buffer_encoding_t  qjs_buffer_encodings[] =
 
 
 static const JSCFunctionListEntry qjs_buffer_constants[] = {
-    JS_PROP_INT32_DEF("MAX_LENGTH", INT32_MAX, JS_PROP_ENUMERABLE),
+    JS_PROP_INT32_DEF("MAX_LENGTH", QJS_BUFFER_MAX_LENGTH, JS_PROP_ENUMERABLE),
     JS_PROP_INT32_DEF("MAX_STRING_LENGTH", 0x3fffffff, JS_PROP_ENUMERABLE),
 };
 
@@ -2570,10 +2570,14 @@ qjs_hex_encode_length(JSContext *ctx, const njs_str_t *src)
 
 
 JSValue
-qjs_buffer_alloc(JSContext *ctx, size_t size)
+qjs_buffer_alloc(JSContext *ctx, uint64_t size)
 {
     JSValue  ret, proto, value;
 
+    if (size > QJS_BUFFER_MAX_LENGTH) {
+        return JS_ThrowRangeError(ctx, "invalid array buffer length");
+    }
+
     value = JS_NewInt64(ctx, size);
 
     ret = qjs_new_uint8_array(ctx, 1, &value);