From 55db1978e25eb2befd3cd96304f11b5d5cd947c9 Mon Sep 17 00:00:00 2001 From: Roman Semenov Date: Wed, 12 Aug 2026 09:42:28 -0700 Subject: [PATCH] Core: allowed top-level scalars in the JSON parser 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 | 48 ++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/src/core/ngx_json_parse.c b/src/core/ngx_json_parse.c index 9295380bd..7eefae0b1 100644 --- a/src/core/ngx_json_parse.c +++ b/src/core/ngx_json_parse.c @@ -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) {