[PATCH 04 of 10] Charset: fixed reuse of buffers without associated memory

Maxim Dounin mdounin at mdounin.ru
Sun May 17 00:12:37 UTC 2026


# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1778975065 -10800
#      Sun May 17 02:44:25 2026 +0300
# Node ID 7dca2cab958f44f580af78bef97bc0037032d7f4
# Parent  52d992b6a7d5e79107616f948fed273a69fb7d53
Charset: fixed reuse of buffers without associated memory.

Previously, in ngx_http_charset_body_filter() buffers with b->pos set
were assumed to have an associated memory allocation and were saved to
the ctx->free_buffers list.  However, b->pos is set in all buffers,
including ones without associated memory.  This was safe, since such
buffers were ignored by ngx_http_charset_get_buffer(), yet reuse of such
buffers via ngx_http_charset_get_buf() was broken.

The fix is to check b->start instead in ngx_http_charset_body_filter().
To make sure cached buffers can actually be used, various internal
fields are now properly cleared when using cached buffers.

Also, b->sync is now properly cleared in cached buffers returned by
ngx_http_charset_get_buffer().  And b->pos of the known-to-be-empty sync
buffer allocated in ngx_http_charset_recode_from_utf8() is set to
b->last, to avoid unexpected sizes shown in logs.

diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c
--- a/src/http/modules/ngx_http_charset_filter_module.c
+++ b/src/http/modules/ngx_http_charset_filter_module.c
@@ -630,7 +630,7 @@ ngx_http_charset_body_filter(ngx_http_re
                 b->shadow->pos = b->shadow->last;
             }
 
-            if (b->pos) {
+            if (b->start) {
                 cl->next = ctx->free_buffers;
                 ctx->free_buffers = cl;
                 continue;
@@ -821,7 +821,7 @@ ngx_http_charset_recode_from_utf8(ngx_po
 
             b = out->buf;
 
-            b->pos = buf->pos;
+            b->pos = buf->last;
             b->last = buf->last;
             b->sync = 1;
             b->shadow = buf;
@@ -1094,15 +1094,23 @@ recode:
 static ngx_chain_t *
 ngx_http_charset_get_buf(ngx_pool_t *pool, ngx_http_charset_ctx_t *ctx)
 {
+    ngx_buf_t    *b;
     ngx_chain_t  *cl;
 
     cl = ctx->free_bufs;
 
     if (cl) {
         ctx->free_bufs = cl->next;
+        cl->next = NULL;
 
-        cl->buf->shadow = NULL;
-        cl->next = NULL;
+        b = cl->buf;
+
+        b->temporary = 0;
+        b->memory = 0;
+        b->mmap = 0;
+        b->flush = 0;
+        b->sync = 0;
+        b->shadow = NULL;
 
         return cl;
     }
@@ -1144,6 +1152,7 @@ ngx_http_charset_get_buffer(ngx_pool_t *
 
             b->pos = b->start;
             b->temporary = 1;
+            b->sync = 0;
             b->shadow = NULL;
 
             return cl;



More information about the nginx-devel mailing list