HTTP wrapper leaks dechunk filter when header parsing fails after Transfer-Encoding: chunked
維護者通常 1 天內回覆
還沒有人認領這個 Issue。
評估
- 難度
- 2/5
- 預估耗時
- 1-3 小時
- 新手友好度
- 78/100
- Issue 類型
- 缺陷
- 描述清晰度
- 描述清楚
- 活躍度
- 活躍
- 領域
- backend, networking
研究方向
從 ext/standard/http_fopen_wrapper.c 中的回應標頭解析部分和 out: 清理路徑開始;issue 指出了 dechunk 篩選器的建立位置,以及遇到格式錯誤的標頭後清理程序略過它的位置。使用提供的 server.php 和 client.php 命令重現問題,接著檢查 debug build 的洩漏報告。失敗的請求沒有回報洩漏,且格式正確的 chunked 回應仍能正常運作,即表示完成。
由索引模型根據 Issue 內容生成。
描述
Description
The following code:
server.php (run first, php server.php):
<?php
$srv = stream_socket_server("tcp://127.0.0.1:18231", $errno, $errstr);
$conn = stream_socket_accept($srv);
while (($line = fgets($conn, 8192)) !== false) { if (trim($line) === '') break; }
// Transfer-Encoding: chunked, then a malformed header line
fwrite($conn, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nBrokenHeaderNoColon\r\n\r\n");
fclose($conn);
client.php (debug build, php -d report_memleaks=1 client.php):
<?php
@file_get_contents("http://127.0.0.1:18231/");
Resulted in this output:
ext/standard/filters.c(1885) : Freeing 0x... (16 bytes), script=.../client.php
main/streams/filter.c(267) : Freeing 0x... (80 bytes), script=.../client.php
=== Total 2 memory leaks detected ===
But I expected this output instead:
(no leaks reported)
Root cause: when the response carries Transfer-Encoding: chunked, the wrapper creates a dechunk filter while parsing headers (php_stream_filter_create, ext/standard/http_fopen_wrapper.c:379 in 8.5.12, :366 on master). If a later header line is malformed, header_info.error is set, the caller closes the stream and jumps to out: (master :1052-1058). The out: cleanup only appends the filter to the stream's readfilters when stream != NULL (master :1257-1259), so on the error path the filter is never freed. Per failed request this leaks the php_stream_filter struct (80 bytes) plus the dechunk filter data (16 bytes).
Reproduces on current master (8.7.0-dev) as well.
Suggested patch (verified against master: repro reports 0 leaks after patching; well-formed chunked responses unaffected):
--- a/ext/standard/http_fopen_wrapper.c
+++ b/ext/standard/http_fopen_wrapper.c
@@ -1230,6 +1230,13 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
efree(header_info.location);
}
+ /* On the error path stream is NULL and the filter is never appended
+ * to readfilters below, so it must be freed here. */
+ if (header_info.transfer_encoding != NULL && stream == NULL) {
+ php_stream_filter_free(header_info.transfer_encoding);
+ header_info.transfer_encoding = NULL;
+ }
+
if (resource) {
php_uri_struct_free(resource);
}
PHP Version
PHP 8.5.12 (also reproduces on master, 8.7.0-dev)
Operating System
Linux x86_64
- 主要語言
- C
- 星號
- 40.7k
- 分支
- 8.3k
- 平均合併
- 2 天 16 小時
- 30 天內合併 PR
- 151
環境準備
- 沒有 Dockerfile 或 Docker Compose 檔案
- 沒有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
php/php-src 的其他 Issue
-
難度 2/5 1-3 小時 新手友好度 72/100
維護者通常 1 天內回覆
-
Case-insensitive substr_compare, ksort, krsort are still locale-dependent可能已有人在做 @lazerg 於 3 天前認領。 未關閉Bug Extension: standard Status: Verified
難度 2/5 1-3 小時 新手友好度 73/100
維護者通常 1 天內回覆
-
master: part of the mbstring bailout fix got lost in a merge可能已有人在做 @lazerg 於 3 天前認領。 未關閉
難度 2/5 1-3 小時 新手友好度 78/100
維護者通常 1 天內回覆
-
Bug Status: Needs Triage
難度 2/5 1-3 小時 新手友好度 64/100
維護者通常 1 天內回覆
-
quoted_printable_encode() produces lines longer than 76 characters for bytes 0xF5 to 0xFF可能已有人在做 關聯的 PR 仍在進行中或已合併。 未關閉
難度 2/5 1-3 小時 新手友好度 76/100
維護者通常 1 天內回覆
相似的 Issue
-
Test failure on FreeBSD: #26 unexpected system_clock source可能已有人在做 關聯的 PR 仍在進行中或已合併。 未關閉low priority rt_lib tests
難度 2/5 1-3 小時 新手友好度 67/100
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 85/100
維護者通常 1 天內回覆
-
bug
難度 2/5 1-3 小時 新手友好度 85/100
-
bug
難度 2/5 1-3 小時 新手友好度 82/100
-
build help wanted new feature
難度 2/5 1-3 小時 新手友好度 85/100
AOMediaCodec/SVT-AV1#2516 · 2 則留言 ·