Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Ensure that chunk buffer contains terminating HTTP newline #42

Merged
merged 2 commits into from

2 participants

@pmakholm

If sysread() returns content just short of the termination HTTP newline, then
the content of the chunk is removed from $chunk_buffer while eventually
leaving the HTTP newline. This breaks the invariant that $chunk_buffer will
always start with the size of the next chunk.

@pmakholm pmakholm Ensure that chunk buffer contains terminating HTTP newline
If sysread() returns content just short of the termination HTTP newline, then
the content of the chunk is removed from $chunk_buffer while eventually
leaving the HTTP newline. This breaks the invariant that $chunk_buffer will
always start with the size of the next chunk.
d2a5d15
@miyagawa
Owner

Can you write a unit test to verify the fix?

@miyagawa miyagawa merged commit f0ac5bd into miyagawa:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 8, 2012
  1. @pmakholm

    Ensure that chunk buffer contains terminating HTTP newline

    pmakholm authored
    If sysread() returns content just short of the termination HTTP newline, then
    the content of the chunk is removed from $chunk_buffer while eventually
    leaving the HTTP newline. This breaks the invariant that $chunk_buffer will
    always start with the size of the next chunk.
Commits on Mar 9, 2012
  1. @pmakholm
This page is out of date. Refresh to see the latest.
Showing with 53 additions and 1 deletion.
  1. +1 −1  lib/Starman/Server.pm
  2. +52 −0 t/chunked_termination.t
View
2  lib/Starman/Server.pm
@@ -406,7 +406,7 @@ sub _prepare_env {
if ($chunk_len == 0) {
last DECHUNK;
- } elsif (length $chunk_buffer < $chunk_len) {
+ } elsif (length $chunk_buffer < $chunk_len + 2) {
$chunk_buffer = $trailer . $chunk_buffer;
last;
}
View
52 t/chunked_termination.t
@@ -0,0 +1,52 @@
+use strict;
+
+use Test::More;
+
+{
+ package Starman::Server;
+
+ # Override the sysread method enabling it to read a stream of packages
+ # from an arrayref instead of an file handle:
+ use subs 'sysread';
+
+ *Starman::Server::sysread = sub {
+ if (ref $_[0] eq "ARRAY") {
+ die "EWOULDBLOCK\n" unless @{ $_[0] };
+
+ $_[1] = shift @{ $_[0] };
+ return length $_[1];
+ }
+
+ return CORE::sysread($_[0], $_[1], $_[2]);
+ };
+
+}
+
+use Starman::Server;
+
+my $server = {
+ server => {
+ client => [
+ "3\015\012foo\015\012", # Full chunk
+ "3\015\012bar", # Chunk missing terminating HTTP newline
+ "\015\012", # ... and then the termination
+ "0\015\012", # Empty chunk to mark end of stream
+ ],
+ }
+};
+
+my $env = {
+ HTTP_TRANSFER_ENCODING => 'chunked',
+};
+
+my $blocked;
+eval {
+ Starman::Server::_prepare_env( $server, $env );
+ 1;
+} or do {
+ $blocked = 1 if $@ =~ /^EWOULDBLOCK$/;
+};
+
+ok( !$blocked, "Reading chunked encoding does not block on well-placed package borders" );
+
+done_testing;
Something went wrong with that request. Please try again.