From 9a5ded845da97c34704f31bd62444de72fcc8219 Mon Sep 17 00:00:00 2001 From: srujan-rai Date: Mon, 4 May 2026 17:02:43 +0530 Subject: [PATCH] autoindex: use temporary pool for directory entries Directory listing entries (file names, metadata) were previously allocated into the request pool and lived until request teardown. Use a temporary pool instead, destroying it immediately after the response buffer is built. This frees all entry data on the happy path without waiting for the request to finish. All error paths (pool creation failure, header send failure, read_dir errors, allocation failures, and response build failure) now destroy the pool before returning. ngx_http_autoindex_error() accepts an optional pool argument and destroys it when non-NULL. --- src/http/modules/ngx_http_autoindex_module.c | 34 +++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c index 082bcb5e6..d64840ba7 100644 --- a/src/http/modules/ngx_http_autoindex_module.c +++ b/src/http/modules/ngx_http_autoindex_module.c @@ -67,7 +67,7 @@ static ngx_buf_t *ngx_http_autoindex_xml(ngx_http_request_t *r, static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, const void *two); static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r, - ngx_dir_t *dir, ngx_str_t *name); + ngx_dir_t *dir, ngx_str_t *name, ngx_pool_t *pool); static ngx_int_t ngx_http_autoindex_init(ngx_conf_t *cf); static void *ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf); @@ -246,13 +246,15 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) #endif - /* TODO: pool should be temporary pool */ - pool = r->pool; + pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, r->connection->log); + if (pool == NULL) { + return ngx_http_autoindex_error(r, &dir, &path, NULL); + } if (ngx_array_init(&entries, pool, 40, sizeof(ngx_http_autoindex_entry_t)) != NGX_OK) { - return ngx_http_autoindex_error(r, &dir, &path); + return ngx_http_autoindex_error(r, &dir, &path, pool); } r->headers_out.status = NGX_HTTP_OK; @@ -283,6 +285,8 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { + ngx_destroy_pool(pool); + if (ngx_close_dir(&dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_dir_n " \"%V\" failed", &path); @@ -303,7 +307,7 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) if (err != NGX_ENOMOREFILES) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_read_dir_n " \"%V\" failed", &path); - return ngx_http_autoindex_error(r, &dir, &path); + return ngx_http_autoindex_error(r, &dir, &path, pool); } break; @@ -328,7 +332,7 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) filename = ngx_pnalloc(pool, allocated); if (filename == NULL) { - return ngx_http_autoindex_error(r, &dir, &path); + return ngx_http_autoindex_error(r, &dir, &path, pool); } last = ngx_cpystrn(filename, path.data, path.len + 1); @@ -348,28 +352,28 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) continue; } - return ngx_http_autoindex_error(r, &dir, &path); + return ngx_http_autoindex_error(r, &dir, &path, pool); } if (ngx_de_link_info(filename, &dir) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_de_link_info_n " \"%s\" failed", filename); - return ngx_http_autoindex_error(r, &dir, &path); + return ngx_http_autoindex_error(r, &dir, &path, pool); } } } entry = ngx_array_push(&entries); if (entry == NULL) { - return ngx_http_autoindex_error(r, &dir, &path); + return ngx_http_autoindex_error(r, &dir, &path, pool); } entry->name.len = len; entry->name.data = ngx_pnalloc(pool, len + 1); if (entry->name.data == NULL) { - return ngx_http_autoindex_error(r, &dir, &path); + return ngx_http_autoindex_error(r, &dir, &path, pool); } ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); @@ -411,10 +415,11 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) } if (b == NULL) { + ngx_destroy_pool(pool); return NGX_ERROR; } - /* TODO: free temporary pool */ + ngx_destroy_pool(pool); if (r == r->main) { b->last_buf = 1; @@ -1007,8 +1012,13 @@ ngx_http_autoindex_alloc(ngx_http_autoindex_ctx_t *ctx, size_t size) static ngx_int_t -ngx_http_autoindex_error(ngx_http_request_t *r, ngx_dir_t *dir, ngx_str_t *name) +ngx_http_autoindex_error(ngx_http_request_t *r, ngx_dir_t *dir, + ngx_str_t *name, ngx_pool_t *pool) { + if (pool != NULL) { + ngx_destroy_pool(pool); + } + if (ngx_close_dir(dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_dir_n " \"%V\" failed", name);