[njs] Fixed njs_json_append_string().

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


details:   https://hg.nginx.org/njs/rev/9b70f038abfa
branches:  
changeset: 1331:9b70f038abfa
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Tue Feb 18 18:42:37 2020 +0300
description:
Fixed njs_json_append_string().

diffstat:

 src/njs_json.c |  91 ++++++++++++++++++++++++++-------------------------------
 1 files changed, 42 insertions(+), 49 deletions(-)

diffs (128 lines):

diff -r aa9ac79f7fd9 -r 9b70f038abfa src/njs_json.c
--- a/src/njs_json.c	Tue Feb 18 18:41:38 2020 +0300
+++ b/src/njs_json.c	Tue Feb 18 18:42:37 2020 +0300
@@ -1545,37 +1545,50 @@ njs_json_append_value(njs_chb_t *chain, 
 static void
 njs_json_append_string(njs_chb_t *chain, const njs_value_t *value, char quote)
 {
+    size_t             size;
     u_char             c, *dst, *dst_end;
-    size_t             length;
+    njs_bool_t         utf8;
     const u_char       *p, *end;
-    njs_string_prop_t  str;
-
-    static char   hex2char[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
-                                   '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-
-    (void) njs_string_prop(&str, value);
-
-    p = str.start;
-    end = p + str.size;
-    length = str.length;
-
-    dst = njs_chb_reserve(chain, length + 2);
+    njs_string_prop_t  string;
+
+    static char  hex2char[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+                                  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+    (void) njs_string_prop(&string, value);
+
+    p = string.start;
+    end = p + string.size;
+    utf8 = (string.length != 0 && string.length != string.size);
+
+    size = njs_max(string.size + 2, 7);
+    dst = njs_chb_reserve(chain, string.size + 2);
     if (njs_slow_path(dst == NULL)) {
         return;
     }
 
-    dst_end = dst + length + 2;
+    dst_end = dst + size;
 
     *dst++ = quote;
+    njs_chb_written(chain, 1);
 
     while (p < end) {
-
-        if (*p < ' '
-            || *p == '\\'
-            || (*p == '\"' && quote == '\"'))
+        if (njs_slow_path(dst_end <= dst + njs_length("\\uXXXX"))) {
+            size = njs_max(end - p + 1, 6);
+            dst = njs_chb_reserve(chain, size);
+            if (njs_slow_path(dst == NULL)) {
+                return;
+            }
+
+            dst_end = dst + size;
+        }
+
+        if (njs_slow_path(*p < ' '
+                          || *p == '\\'
+                          || (*p == '\"' && quote == '\"')))
         {
             c = (u_char) *p++;
             *dst++ = '\\';
+            njs_chb_written(chain, 2);
 
             switch (c) {
             case '\\':
@@ -1605,44 +1618,24 @@ njs_json_append_string(njs_chb_t *chain,
                 *dst++ = '0';
                 *dst++ = hex2char[(c & 0xf0) >> 4];
                 *dst++ = hex2char[c & 0x0f];
-            }
-        }
-
-        /*
-         * Control characters less than space are encoded using 6 bytes
-         * "\uXXXX".  Checking there is at least 6 bytes of destination storage
-         * space.
-         */
-
-        while (p < end && (dst_end - dst) > 6) {
-            if (*p < ' ' || (*p == '\"' && quote == '\"') || *p == '\\') {
-                break;
+                njs_chb_written(chain, 4);
             }
 
-            if (length != 0) {
-                /* UTF-8 or ASCII string. */
-                dst = njs_utf8_copy(dst, &p, end);
-
-            } else {
-                /* Byte string. */
-                *dst++ = *p++;
-            }
+            continue;
         }
 
-        if (dst_end - dst <= 6) {
-            njs_chb_written(chain, dst - chain->last->pos);
-
-            dst = njs_chb_reserve(chain, 64);
-            if (njs_slow_path(dst == NULL)) {
-                return;
-            }
-
-            dst_end = dst + 64;
+        if (utf8) {
+            /* UTF-8 string. */
+            dst = njs_utf8_copy(dst, &p, end);
+
+        } else {
+            /* Byte or ASCII string. */
+            *dst++ = *p++;
         }
+
+        njs_chb_written(chain, dst - chain->last->pos);
     }
 
-    njs_chb_written(chain, dst - chain->last->pos);
-
     njs_chb_append(chain, &quote, 1);
 }
 


More information about the nginx-devel mailing list