]> git.kaiwu.me - nginx.git/commitdiff
Core: allowed top-level scalars in the JSON parser
authorRoman Semenov <r.semenov@f5.com>
Wed, 12 Aug 2026 16:42:28 +0000 (09:42 -0700)
committerRoman S <141866642+roman-f5@users.noreply.github.com>
Mon, 24 Aug 2026 18:08:31 +0000 (11:08 -0700)
RFC 8259 permits any JSON value as a complete document, not just
objects and arrays.  The start state now accepts strings, numbers,
and the true/false/null literals as well.  A bare top-level number,
having no closing delimiter, is emitted when input ends.

src/core/ngx_json_parse.c

index 9295380bd2304f187b26ea635d4f65c30c9d0960..7eefae0b17a1e0fddc73553af057486b79535bd1 100644 (file)
@@ -103,35 +103,9 @@ ngx_json_parse_ctx(ngx_json_ctx_t *ctx, u_char *data, size_t len)
                 break;
             }
 
-            if (*p == '{') {
-                rc = ngx_json_push_state(ctx, ngx_json_ctx_object);
-                if (rc != NGX_OK) {
-                    return rc;
-                }
-
-                if (ngx_json_emit(ctx, NGX_JSON_OBJECT_OPEN, p, 1) != NGX_OK) {
-                    return NGX_ERROR;
-                }
-
-                state = ngx_json_object;
-                break;
-            }
-
-            if (*p == '[') {
-                rc = ngx_json_push_state(ctx, ngx_json_ctx_array);
-                if (rc != NGX_OK) {
-                    return rc;
-                }
-
-                if (ngx_json_emit(ctx, NGX_JSON_ARRAY_OPEN, p, 1) != NGX_OK) {
-                    return NGX_ERROR;
-                }
-
-                state = ngx_json_array;
-                break;
-            }
-
-            return NGX_DECLINED;
+            p--;
+            state = ngx_json_value;
+            break;
 
         case ngx_json_object:
             if (ngx_json_ws(*p)) {
@@ -665,6 +639,22 @@ ngx_json_parse_ctx(ngx_json_ctx_t *ctx, u_char *data, size_t len)
         skip_depth = ctx->skip_until_depth;
     }
 
+    /* a bare top-level number is not self-delimited; emit it at end of input */
+
+    if (ctx->depth == 0
+        && (state == ngx_json_number_int_zero
+            || state == ngx_json_number_int
+            || state == ngx_json_number_frac_digit
+            || state == ngx_json_number_exp_digit))
+    {
+        rc = ngx_json_emit(ctx, NGX_JSON_VALUE_NUMBER, start, last - start);
+        if (rc != NGX_OK) {
+            return rc;
+        }
+
+        state = ngx_json_done;
+    }
+
     ctx->state = state;
 
     if (state == ngx_json_done) {