]> git.kaiwu.me - njs.git/commitdiff
WebCrypto: fix AES-CTR out-of-bounds write on empty input
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 29 Oct 2026 16:17:33 +0000 (09:17 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Thu, 29 Oct 2026 20:00:23 +0000 (13:00 -0700)
Previously, the AES-CTR block count helper computed the number of
blocks as "1 + (dend - 1) / dsor".  This underflows for a zero-length
input, so njs_ceil_div(0, 16) and qjs_ceiling_div(0, 16) returned
2^28 instead of 0.

The fix is to use the zero-safe "(dend + dsor - 1) / dsor" form.

The njs engine code was introduced in 7b2b7612 (0.7.0) and the
QuickJS counterpart in 75ca26f8 (0.8.10).

external/njs_webcrypto_module.c
external/qjs_webcrypto_module.c
test/webcrypto/aes.t.mjs

index 547917a4501af6746a3f83a9adf2669baaf1cf25..8ed5fbbdde30d6bbda594d484ed39189c4aea8d9 100644 (file)
@@ -1185,7 +1185,7 @@ fail:
 njs_inline njs_uint_t
 njs_ceil_div(njs_uint_t dend, njs_uint_t dsor)
 {
-    return (dsor == 0) ? 0 : 1 + (dend - 1) / dsor;
+    return (dsor == 0) ? 0 : (dend + dsor - 1) / dsor;
 }
 
 
index 4a70b9426a2f8a286674df1087629f4ce747e4cb..3b4bfc5a83221d0a539e9b8c7563f0ee9216838e 100644 (file)
@@ -985,7 +985,7 @@ qjs_bn_counter128(njs_str_t *ctr, unsigned bits)
 njs_inline unsigned
 qjs_ceiling_div(unsigned dend, unsigned dsor)
 {
-    return (dsor == 0) ? 0 : 1 + (dend - 1) / dsor;
+    return (dsor == 0) ? 0 : (dend + dsor - 1) / dsor;
 }
 
 
index 7c4825838d560acf636986a98d3bbaef4ec948cd..88ebe402dbe5d6948951c2e10a21cf72e3a26eff 100644 (file)
@@ -87,6 +87,8 @@ let aes_tsuite = {
         { name: "AES-CTR", data: "aabbcc", key: "001122330011223300112233001122330011223300112233" },
         { name: "AES-CTR", data: "aabbccdd", length: 129,
           exception: "TypeError: AES-CTR algorithm.length must be between 1 and 128" },
+        { name: "AES-CTR", data: "", length: 128 },
+        { name: "AES-CTR", data: "", counter: "ffffffffffffffffffffffffffffffff", length: 128 },
 
         { name: "AES-CBC", data: "aa" },
         { name: "AES-CBC", data: "aabbccdd".repeat(4) },