Subject: | Ifinite loop in POE::Filter::HTTPChunk on broken trailer |
When web server returns invalid chunked response, Filter::HTTPChunk hang
in infinite loop.
Patch with unit-test for version 0.87 attached.
Example of broken response:
"b\nuseful data\n0\n\n7\ngarbage\n0\n"
Subject: | POE-Component-Client-HTTP-0.87.broken_trailer.patch |
diff --git a/lib/POE/Filter/HTTPChunk.pm b/lib/POE/Filter/HTTPChunk.pm
index 69be8d0..561cdaa 100644
--- a/lib/POE/Filter/HTTPChunk.pm
+++ b/lib/POE/Filter/HTTPChunk.pm
@@ -167,7 +167,12 @@ sub get_one {
unshift (@{$self->[FRAMING_BUFFER]}, $chunk) if (length $chunk);
return $retval;
}
- unshift (@{$self->[FRAMING_BUFFER]}, $chunk);
+ if (@{$self->[FRAMING_BUFFER]}) {
+ $self->[FRAMING_BUFFER]->[0] = $chunk . $self->[FRAMING_BUFFER]->[0];
+ } else {
+ unshift (@{$self->[FRAMING_BUFFER]}, $chunk);
+ return $retval;
+ }
}
}
return $retval;
diff --git a/t/04_chunk_filter.t b/t/04_chunk_filter.t
index 11fa1cf..6b9cb05 100644
--- a/t/04_chunk_filter.t
+++ b/t/04_chunk_filter.t
@@ -9,7 +9,7 @@ use HTTP::Headers;
sub DEBUG () { 0 }
-plan tests => 18;
+plan tests => 20;
use_ok ('POE::Filter::HTTPChunk');
@@ -173,3 +173,14 @@ use_ok ('POE::Filter::HTTPChunk');
my $pending = $filter->get_pending;
is (shift @$pending, 'garbage', "got expected pending data");
}
+{ # extra-extra garbage at the end gets retrieved by get_pending()
+ my @input = ("9\nchunk_333\nA\nchunk_4444\n", "0\n", "7\ngarbage\n", "0\n");
+ my $filter = POE::Filter::HTTPChunk->new;
+ $filter->get_one_start( \@input );
+
+ my $output = $filter->get_one();
+ is_deeply($output, [qw/chunk_333 chunk_4444/], "got expected chunks");
+
+ my $pending = $filter->get_pending;
+ is_deeply($pending, ["7\ngarbage\n0\n"], "got expected pending data");
+}