]> git.kaiwu.me - njs.git/commitdiff
Fixed memory overlap checks
authorDmitry Volyntsev <xeioex@nginx.com>
Sat, 23 May 2026 00:07:47 +0000 (17:07 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Tue, 26 May 2026 21:45:24 +0000 (14:45 -0700)
src/njs_buffer.c
src/njs_str.h
src/njs_typed_array.c
src/qjs_buffer.c
test/buffer.t.js

index 49ead27740750452eaf8282ce7b78747fff4fafc..622d906823d8ab642923f10149da688814fc8083 100644 (file)
@@ -2007,7 +2007,7 @@ njs_buffer_prototype_copy(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     njs_int_t           ret;
     njs_value_t         *val1, *val2;
     njs_typed_array_t   *source, *target;
-    njs_array_buffer_t  *buffer, *array;
+    njs_array_buffer_t  *buffer;
 
     val1 = njs_argument(args, 0);
     val2 = njs_arg(args, nargs, 1);
@@ -2041,11 +2041,9 @@ njs_buffer_prototype_copy(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
         return NJS_ERROR;
     }
 
-    array = njs_typed_array_buffer(source);
-
     size = njs_min(trg_end - trg, src_end - src);
 
-    if (buffer->u.data != array->u.data) {
+    if (!njs_memory_overlaps(trg, size, src, size)) {
         memcpy(trg, src, size);
 
     } else {
index e64d88a976772cd8fcbfebfe80b81c6295ca0742..1eb46aaf4e96ae781456f547036b1297968e5528 100644 (file)
@@ -85,6 +85,18 @@ njs_cpymem(dst, src, n)                                                       \
     (((u_char *) memcpy(dst, src, n)) + (n))
 
 
+njs_inline njs_bool_t
+njs_memory_overlaps(const u_char *p1, size_t n1, const u_char *p2, size_t n2)
+{
+    uintptr_t  s1, s2;
+
+    s1 = (uintptr_t) p1;
+    s2 = (uintptr_t) p2;
+
+    return (s1 < s2 + n2 && s2 < s1 + n1);
+}
+
+
 #define                                                                       \
 njs_strncmp(s1, s2, n)                                                        \
     strncmp((char *) s1, (char *) s2, n)
index f74f175faefddfab29e6521ed7910d2437b337a1..d007285ad86a7a5a8ac69704e11ca3178d4d63bd 100644 (file)
@@ -920,8 +920,7 @@ njs_typed_array_prototype_fill(njs_vm_t *vm, njs_value_t *args,
 static void
 njs_slice_memcpy(uint8_t *dst, const uint8_t *src, size_t len)
 {
-    if (dst + len <= src || dst >= src + len) {
-        /* no overlap: can use memcpy */
+    if (!njs_memory_overlaps(dst, len, src, len)) {
         memcpy(dst, src, len);
 
     } else {
index 2243822d090da47ba9d14a64d22779b21e313aa6..b870be91778e00baa1747eee75317138d7e1fc69 100644 (file)
@@ -582,8 +582,8 @@ qjs_buffer_fill(JSContext *ctx, JSValueConst buffer, JSValueConst fill,
         return buffer;
     }
 
-    if (src.start >= (dst.start + dst.length)
-        || dst.start >= (dst.start + dst.length))
+    if (!njs_memory_overlaps(dst.start + offset, end - offset,
+                             src.start, src.length))
     {
         while (offset < end) {
             n = njs_min(src.length, end - offset);
@@ -862,9 +862,7 @@ qjs_buffer_prototype_copy(JSContext *ctx, JSValueConst this_val, int argc,
 
     size = njs_min(src.length, target.length);
 
-    if (src.start >= (target.start + size)
-        || target.start >= (src.start + size))
-    {
+    if (!njs_memory_overlaps(target.start, size, src.start, size)) {
         memcpy(target.start, src.start, size);
 
     } else {
index d02dca1f5530c1cc28eb39e3c81ff232e97c07c7..c10b0180942787b042cba87813e285b8fa00c7d2 100644 (file)
@@ -254,11 +254,18 @@ let fill_tsuite = {
     name: "buf.fill() tests",
     skip: () => (!has_buffer()),
     T: async (params) => {
+        let value = params.value;
+
+        if (params.value_from_buf) {
+            value = params.buf.subarray(params.value_from_buf[0],
+                                        params.value_from_buf[1]);
+        }
+
         if (params.detach_value) {
-            detach(params.value.buffer);
+            detach(value.buffer);
         }
 
-        let r = params.buf.fill(params.value, params.offset, params.end);
+        let r = params.buf.fill(value, params.offset, params.end);
 
         if (r.toString() !== params.expected) {
             throw Error(`unexpected output "${r.toString()}" != "${params.expected}"`);
@@ -286,6 +293,15 @@ let fill_tsuite = {
         { buf: Buffer.from(new Uint8Array([0x60, 0x61, 0x62, 0x63]).buffer, 1),
           value: Buffer.from('def'),
           expected: 'def' },
+        { buf: Buffer.from('0123456789'),
+          value_from_buf: [0, 4],
+          offset: 6,
+          expected: '0123450123' },
+        { buf: Buffer.from('0123456789'),
+          value_from_buf: [0, 4],
+          offset: 2,
+          end: 8,
+          expected: '0101230189' },
     ],
 };