]> git.kaiwu.me - nginx.git/commitdiff
JSON: fixed overflow detection in length calculation
authorDmitry Plotnikov <d.plotnikov@f5.com>
Tue, 18 Aug 2026 01:40:08 +0000 (01:40 +0000)
committerdplotnikov-f5 <67346902+dplotnikov-f5@users.noreply.github.com>
Mon, 31 Aug 2026 21:22:50 +0000 (14:22 -0700)
src/core/ngx_json.c

index f826d431245a2fd7024067d2d5dfbf376e7f7ea4..f99378fc5e836f7b069e02ea39814d0a7f76e698 100644 (file)
@@ -96,10 +96,21 @@ ngx_json_obj_length(ngx_data_item_t *item)
 
     if (i) {
         for ( ;; ) {
-            len = sizeof("\"\":") - 1 + i->name.len
-                  + ngx_escape_json(NULL, i->name.data, i->name.len);
+            if (i->name.len > NGX_MAX_SIZE_T_VALUE - (sizeof("\"\":") - 1)) {
+                return NGX_ERROR;
+            }
 
-            if (total > NGX_MAX_SIZE_T_VALUE - len) {
+            len = sizeof("\"\":") - 1 + i->name.len;
+
+            if (len > NGX_MAX_SIZE_T_VALUE - total) {
+                return NGX_ERROR;
+            }
+
+            total += len;
+
+            len = ngx_escape_json(NULL, i->name.data, i->name.len);
+
+            if (len > NGX_MAX_SIZE_T_VALUE - total) {
                 return NGX_ERROR;
             }
 
@@ -110,7 +121,7 @@ ngx_json_obj_length(ngx_data_item_t *item)
                 return NGX_ERROR;
             }
 
-            if (total > NGX_MAX_SIZE_T_VALUE - len) {
+            if (len > NGX_MAX_SIZE_T_VALUE - total) {
                 return NGX_ERROR;
             }
 
@@ -190,7 +201,7 @@ ngx_json_list_length(ngx_data_item_t *item)
                 return NGX_ERROR;
             }
 
-            if (total > NGX_MAX_SIZE_T_VALUE - len) {
+            if (len > NGX_MAX_SIZE_T_VALUE - total) {
                 return NGX_ERROR;
             }
 
@@ -248,12 +259,24 @@ ngx_json_list_encode(u_char *p, ngx_data_item_t *item)
 static ssize_t
 ngx_json_string_length(ngx_data_item_t *item)
 {
+    size_t      len, total;
     ngx_str_t  *str;
 
     str = &item->data.string;
 
-    return sizeof("\"\"") - 1 + str->len
-           + ngx_escape_json(NULL, str->data, str->len);
+    if (str->len > NGX_MAX_SIZE_T_VALUE - (sizeof("\"\"") - 1)) {
+        return NGX_ERROR;
+    }
+
+    total = sizeof("\"\"") - 1 + str->len;
+
+    len = ngx_escape_json(NULL, str->data, str->len);
+
+    if (len > NGX_MAX_SIZE_T_VALUE - total) {
+        return NGX_ERROR;
+    }
+
+    return total + len;
 }