[njs] Detecting memory error in njs_chb_*() functions.

Dmitry Volyntsev xeioex at nginx.com
Tue Feb 18 15:56:36 UTC 2020


details:   https://hg.nginx.org/njs/rev/aa9ac79f7fd9
branches:  
changeset: 1330:aa9ac79f7fd9
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Tue Feb 18 18:41:38 2020 +0300
description:
Detecting memory error in njs_chb_*() functions.

diffstat:

 src/njs_array.c |   9 +++++++--
 src/njs_chb.c   |  17 ++++++++++++-----
 src/njs_chb.h   |  12 ++++++++++--
 src/njs_json.c  |  14 ++++++++------
 4 files changed, 37 insertions(+), 15 deletions(-)

diffs (158 lines):

diff -r d2877d602d39 -r aa9ac79f7fd9 src/njs_array.c
--- a/src/njs_array.c	Mon Feb 17 16:18:40 2020 +0300
+++ b/src/njs_array.c	Tue Feb 18 18:41:38 2020 +0300
@@ -1381,8 +1381,8 @@ njs_array_prototype_join(njs_vm_t *vm, n
     njs_index_t unused)
 {
     u_char             *p, *last;
-    int64_t            length;
-    uint64_t           i, len, size;
+    int64_t            size, length;
+    uint64_t           i, len;
     njs_int_t          ret;
     njs_chb_t          chain;
     njs_utf8_t         utf8;
@@ -1497,6 +1497,11 @@ njs_array_prototype_join(njs_vm_t *vm, n
     njs_chb_drop(&chain, separator.size);
 
     size = njs_chb_size(&chain);
+    if (njs_slow_path(size < 0)) {
+        njs_memory_error(vm);
+        return NJS_ERROR;
+    }
+
     length -= separator.length;
 
     p = njs_string_alloc(vm, &vm->retval, size, utf8 ? length : 0);
diff -r d2877d602d39 -r aa9ac79f7fd9 src/njs_chb.c
--- a/src/njs_chb.c	Mon Feb 17 16:18:40 2020 +0300
+++ b/src/njs_chb.c	Tue Feb 18 18:41:38 2020 +0300
@@ -134,9 +134,13 @@ njs_chb_drain(njs_chb_t *chain, size_t d
 void
 njs_chb_drop(njs_chb_t *chain, size_t drop)
 {
-    size_t          size;
+    uint64_t        size;
     njs_chb_node_t  *n, *next;
 
+    if (njs_slow_path(chain->error)) {
+        return;
+    }
+
     n = chain->last;
 
     if (njs_fast_path(n != NULL && (njs_chb_node_size(n) > drop))) {
@@ -145,7 +149,7 @@ njs_chb_drop(njs_chb_t *chain, size_t dr
     }
 
     n = chain->nodes;
-    size = njs_chb_size(chain);
+    size = (uint64_t) njs_chb_size(chain);
 
     if (drop >= size) {
         njs_chb_destroy(chain);
@@ -181,10 +185,10 @@ njs_int_t
 njs_chb_join(njs_chb_t *chain, njs_str_t *str)
 {
     u_char          *start;
-    size_t          size;
+    uint64_t        size;
     njs_chb_node_t  *n;
 
-    if (chain->error) {
+    if (njs_slow_path(chain->error)) {
         return NJS_DECLINED;
     }
 
@@ -196,7 +200,10 @@ njs_chb_join(njs_chb_t *chain, njs_str_t
         return NJS_OK;
     }
 
-    size = njs_chb_size(chain);
+    size = (uint64_t) njs_chb_size(chain);
+    if (njs_slow_path(size >= UINT32_MAX)) {
+        return NJS_ERROR;
+    }
 
     start = njs_mp_alloc(chain->pool, size);
     if (njs_slow_path(start == NULL)) {
diff -r d2877d602d39 -r aa9ac79f7fd9 src/njs_chb.h
--- a/src/njs_chb.h	Mon Feb 17 16:18:40 2020 +0300
+++ b/src/njs_chb.h	Tue Feb 18 18:41:38 2020 +0300
@@ -61,12 +61,16 @@ njs_chb_init(njs_chb_t *chain, njs_mp_t 
 }
 
 
-njs_inline uint64_t
+njs_inline int64_t
 njs_chb_size(njs_chb_t *chain)
 {
     uint64_t        size;
     njs_chb_node_t  *n;
 
+    if (njs_slow_path(chain->error)) {
+        return -1;
+    }
+
     n = chain->nodes;
 
     size = 0;
@@ -86,6 +90,10 @@ njs_chb_utf8_length(njs_chb_t *chain)
     int64_t         len, length;
     njs_chb_node_t  *n;
 
+    if (njs_slow_path(chain->error)) {
+        return -1;
+    }
+
     n = chain->nodes;
 
     length = 0;
@@ -93,7 +101,7 @@ njs_chb_utf8_length(njs_chb_t *chain)
     while (n != NULL) {
         len = njs_utf8_length(n->start, njs_chb_node_size(n));
         if (njs_slow_path(len < 0)) {
-            return len;
+            return 0;
         }
 
         length += len;
diff -r d2877d602d39 -r aa9ac79f7fd9 src/njs_json.c
--- a/src/njs_json.c	Mon Feb 17 16:18:40 2020 +0300
+++ b/src/njs_json.c	Tue Feb 18 18:41:38 2020 +0300
@@ -1120,8 +1120,7 @@ njs_json_stringify_iterator(njs_vm_t *vm
     njs_value_t *object)
 {
     u_char            *p;
-    int64_t           length;
-    uint64_t          size;
+    int64_t           size, length;
     njs_int_t         ret;
     njs_chb_t         chain;
     njs_value_t       *key, *value, index, wrapper;
@@ -1295,18 +1294,21 @@ done:
     }
 
     size = njs_chb_size(&chain);
-    if (njs_slow_path(size == 0)) {
+    if (njs_slow_path(size < 0)) {
+        njs_chb_destroy(&chain);
+        goto memory_error;
+    }
+
+    if (size == 0) {
         njs_set_undefined(&vm->retval);
         goto release;
     }
 
     length = njs_chb_utf8_length(&chain);
-    if (njs_slow_path(length < 0)) {
-        length = 0;
-    }
 
     p = njs_string_alloc(vm, &vm->retval, size, length);
     if (njs_slow_path(p == NULL)) {
+        njs_chb_destroy(&chain);
         goto memory_error;
     }
 


More information about the nginx-devel mailing list