Net::HTTP::NB bug with chunked responses when there is a delay around the chunk header [rt.cpan.org #107744]
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 35/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 停滞
- 技術スタック
- perl
- 領域
- networking
調査の方向性
参照されている行の周辺で説明されている、Net::HTTP::NB::read_entity_body() と関連する Net::HTTP::Methods::read_entity_body() の動作から始めます。test-http-server.pl を test-http-async-2.pl とともに実行して、遅延した chunked response を再現し、期待される SHA-1 response check が通ることを確認します。
索引モデルが issue の本文から書いたものです。
説明
Migrated from rt.cpan.org#107744 (status was 'open')
Requestors:
Attachments:
From [email protected] on 2015-10-13 07:51:31
:
Net::HTTP::NB v6.09
Net::HTTP::Methods v6.09
OS: RedHat 6.7 on x86_64
Dear Net::HTTP developers,
I have discovered a bug in Net::HTTP::NB if the server it connects to responds with chunked data and the client cannot read the chunk length field *and* at least 1 byte of the data in a single call to read_entity_body().
The details of the bug are as follows:
When Net::HTTP::NB::read_entity_body() calls Net::HTTP::Methods::read_entity_body() for the first time, the Transfer-Encoding headers are inspected. If chunked mode is to be used, the chunk length is read (line 534) and the data is read (line 571). This all works fine if the data buffer has sufficient data already within it for both reads. If there is insufficient data to complete either or both reads then a second call is made to Net::HTTP::NB::sysread() and this causes the "Multi-Read" die() on line 16 after restoring the original data buffer from "httpnb_save".
When Net::HTTP::NB::read_entity_body() is retried, the call to Net::HTTP::Methods::read_entity_body() skips the header inspection because "http_first_body" was reset to zero on the first attempt. This means that it assumes that the data is not chunked and just reads all the data as the content, ignoring any chunked encoding.
I believe that the solution is to preserve and restore "http_first_body" and "http_request_method" around the "eval { }" block in Net::HTTP::NB::read_entity_body() so that subsequent retry attempts to Net::HTTP::Methods::read_entity_body() correctly restore its state if an error occurs.
I have attached two test utilities that trigger the bug and validate the patch.
The first, test-http-server.pl, is a small web server that can chunk its response into configurable sizes and can also flush and pause its output at configurable data positions. This is used to cause specific jitter patterns in the web server response so that we can reliably exercise the various paths through the client.
The second, test-http-async-2.pl, is a small client using HTTP::Async that performs a set of tests against the web server with different chunked/non-chunked encodings and with different delay patterns. The client knows what web response to expect so it uses a SHA-1 digest to validate the response.
I have also attached a patch for Net::HTTP::NB which causes all tests to pass on my machine.
I apologise for renaming all files with a .txt extension but our email uses Microsoft Outlook and this often blocks extensions that it doesn't think are safe. Renaming files to .txt means that they always get through.
As an FYI, this bug was original spotted with Net::HTTPS::NB when working with an HTTPS connection. That part of the code in Net::HTTPS::NB was copied from Net::HTTP::NB and the investigation continued to find the root cause as described above. I'll be offering an similar patch to the Net::HTTPS::NB developers.
Best regards,
Roger Lucas
From [email protected] on 2015-10-14 05:10:10
:
On Tue Oct 13 03:51:31 2015, [email protected] wrote:
> Net::HTTP::NB v6.09
> Net::HTTP::Methods v6.09
> OS: RedHat 6.7 on x86_64
>
> Dear Net::HTTP developers,
>
> I have discovered a bug in Net::HTTP::NB if the server it connects to
> responds with chunked data and the client cannot read the chunk length
> field *and* at least 1 byte of the data in a single call to
> read_entity_body().
>
> The details of the bug are as follows:
>
> When Net::HTTP::NB::read_entity_body() calls
> Net::HTTP::Methods::read_entity_body() for the first time, the
> Transfer-Encoding headers are inspected. If chunked mode is to be
> used, the chunk length is read (line 534) and the data is read (line
> 571). This all works fine if the data buffer has sufficient data
> already within it for both reads. If there is insufficient data to
> complete either or both reads then a second call is made to
> Net::HTTP::NB::sysread() and this causes the "Multi-Read" die() on
> line 16 after restoring the original data buffer from "httpnb_save".
>
> When Net::HTTP::NB::read_entity_body() is retried, the call to
> Net::HTTP::Methods::read_entity_body() skips the header inspection
> because "http_first_body" was reset to zero on the first attempt.
> This means that it assumes that the data is not chunked and just reads
> all the data as the content, ignoring any chunked encoding.
>
> I believe that the solution is to preserve and restore
> "http_first_body" and "http_request_method" around the "eval { }"
> block in Net::HTTP::NB::read_entity_body() so that subsequent retry
> attempts to Net::HTTP::Methods::read_entity_body() correctly restore
> its state if an error occurs.
>
> I have attached two test utilities that trigger the bug and validate
> the patch.
>
> The first, test-http-server.pl, is a small web server that can chunk
> its response into configurable sizes and can also flush and pause its
> output at configurable data positions. This is used to cause specific
> jitter patterns in the web server response so that we can reliably
> exercise the various paths through the client.
>
> The second, test-http-async-2.pl, is a small client using HTTP::Async
> that performs a set of tests against the web server with different
> chunked/non-chunked encodings and with different delay patterns. The
> client knows what web response to expect so it uses a SHA-1 digest to
> validate the response.
>
> I have also attached a patch for Net::HTTP::NB which causes all tests
> to pass on my machine.
>
> I apologise for renaming all files with a .txt extension but our email
> uses Microsoft Outlook and this often blocks extensions that it
> doesn't think are safe. Renaming files to .txt means that they always
> get through.
>
> As an FYI, this bug was original spotted with Net::HTTPS::NB when
> working with an HTTPS connection. That part of the code in
> Net::HTTPS::NB was copied from Net::HTTP::NB and the investigation
> continued to find the root cause as described above. I'll be offering
> an similar patch to the Net::HTTPS::NB developers.
>
> Best regards,
>
> Roger Lucas
With Roger we found that his patch doesn't cover all cases. This test server and client demonstrates problem: https://gist.github.com/olegwtf/c4dc83711c03a66ba07a
So, I reworked his patch a little and now it seems it looks good for both of us.
- 主要言語
- Perl
- スター
- 20
- フォーク
- 27
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
libwww-perl/Net-HTTP のほかの issue
-
難易度 4/5 3〜5日 初心者へのやさしさ 50/100
libwww-perl/Net-HTTP#99 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
libwww-perl/Net-HTTP#95 ·
-
t/live.t may failオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 45/100
libwww-perl/Net-HTTP#87 · コメント 2 件 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 45/100
libwww-perl/Net-HTTP#79 · コメント 6 件 ·
-
難易度 1/5 1時間未満 初心者へのやさしさ 48/100
libwww-perl/Net-HTTP#74 ·
libwww-perl/Net-HTTP の issue をすべて見る
似ている issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 85/100
PerlDancer/Dancer2#1854 ·
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
major/MySQLTuner-perl#1007 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 69/100
bioconda/bioconda-recipes#70187 ·
メンテナーはふだん 2 日以内に返信
-
documentation Needs Triage
難易度 1/5 1時間未満 初心者へのやさしさ 93/100
メンテナーはふだん 1 日以内に返信