[nginx] Charset: fixed reuse of buffers without associated memory.

Maxim Dounin mdounin at mdounin.ru
Tue May 19 02:46:31 UTC 2026


details:   http://freenginx.org/hg/nginx/rev/317eafac071e
branches:  
changeset: 9520:317eafac071e
user:      Maxim Dounin <mdounin at mdounin.ru>
date:      Tue May 19 01:56:29 2026 +0300
description:
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.

diffstat:

 src/http/modules/ngx_http_charset_filter_module.c |  17 +++++++++++++----
 1 files changed, 13 insertions(+), 4 deletions(-)

diffs (55 lines):

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