From aeef0bfe283032d0a66d5299472c75407b9a6073 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Fri, 9 Oct 2026 18:40:28 -0700 Subject: [PATCH] Modules: fix shared dict state JSON separators When saving a shared dict zone with timeout=, expired entries are skipped. A comma is appended whenever another tree node follows a live entry, even if all remaining nodes are expired. This can leave a trailing comma in the state file, making it invalid JSON. Insert commas before live entries only when a previous entry has been rendered, so skipped entries do not affect the separators. --- nginx/ngx_js_shared_dict.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/nginx/ngx_js_shared_dict.c b/nginx/ngx_js_shared_dict.c index 22526f5b..5c14d67c 100644 --- a/nginx/ngx_js_shared_dict.c +++ b/nginx/ngx_js_shared_dict.c @@ -1999,6 +1999,7 @@ ngx_js_dict_render_json(ngx_js_dict_t *dict, njs_chb_t *chain) { u_char *p, *dst; size_t len; + ngx_uint_t first; ngx_msec_t now; ngx_time_t *tp; ngx_rbtree_t *rbtree; @@ -2017,6 +2018,8 @@ ngx_js_dict_render_json(ngx_js_dict_t *dict, njs_chb_t *chain) return NGX_OK; } + first = 1; + for (rn = ngx_rbtree_min(rbtree->root, rbtree->sentinel); rn != NULL; rn = next) @@ -2029,6 +2032,12 @@ ngx_js_dict_render_json(ngx_js_dict_t *dict, njs_chb_t *chain) continue; } + if (!first) { + njs_chb_append_literal(chain, ","); + } + + first = 0; + if (ngx_js_render_string(chain, &node->sn.str) != NGX_OK) { return NGX_ERROR; } @@ -2067,10 +2076,6 @@ ngx_js_dict_render_json(ngx_js_dict_t *dict, njs_chb_t *chain) } njs_chb_append_literal(chain, "}"); - - if (next != NULL) { - njs_chb_append_literal(chain, ","); - } } njs_chb_append_literal(chain, "}"); -- 2.47.3