Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fixed a few limit bugs in Mojo::Message
  • Loading branch information
kraih committed Dec 16, 2014
1 parent 7ce419f commit dee50a7
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 24 deletions.
3 changes: 2 additions & 1 deletion Changes
@@ -1,6 +1,7 @@

5.70 2014-12-16
5.70 2014-12-17
- Improved Mojo::Template performance.
- Fixed a few limit bugs in Mojo::Message.
- Fixed Windows bug in Mojo::IOLoop::Client. (OlegG)

5.69 2014-12-13
Expand Down
20 changes: 11 additions & 9 deletions lib/Mojo/Message.pm
Expand Up @@ -144,13 +144,10 @@ sub json {
}

sub parse {
my ($self, $chunk) = @_;

# Check message size
my $max = $self->max_message_size;
return $self->_limit('Maximum message size exceeded', 413)
if $max && ($self->{raw_size} += length($chunk //= '')) > $max;
my $self = shift;

return $self if $self->{limit};
$self->{raw_size} += length(my $chunk = shift // '');
$self->{buffer} .= $chunk;

# Start line
Expand All @@ -170,13 +167,17 @@ sub parse {
$self->content($self->content->parse(delete $self->{buffer}))
if $state eq 'content' || $state eq 'finished';

# Check message size
my $max = $self->max_message_size;
return $self->_limit('Maximum message size exceeded', 413)
if $max && $max < $self->{raw_size};

# Check line size
return $self->_limit('Maximum line size exceeded', 431)
if $self->headers->is_limit_exceeded;

# Check buffer size
return $self->error(
{message => 'Maximum buffer size exceeded', advice => 400})
return $self->_limit('Maximum buffer size exceeded', 400)
if $self->content->is_limit_exceeded;

return $self->emit('progress')->content->is_finished ? $self->finish : $self;
Expand Down Expand Up @@ -591,7 +592,8 @@ Check if message parser/generator is finished.
my $bool = $msg->is_limit_exceeded;
Check if message has exceeded L</"max_line_size"> or L</"max_message_size">.
Check if message has exceeded L</"max_line_size">, L</"max_message_size">,
L<Mojo::Content/"max_buffer_size"> or L<Mojo::Headers/"max_line_size">.
=head2 json
Expand Down
28 changes: 17 additions & 11 deletions t/mojo/request.t
Expand Up @@ -13,16 +13,19 @@ use Mojo::Util 'encode';
# Parse HTTP 1.1 message with huge "Cookie" header exceeding all limits
my $req = Mojo::Message::Request->new;
my $finished;
$req->max_message_size($req->headers->max_line_size);
my $huge = 'a=b; ' x $req->max_message_size;
$req->on(finish => sub { $finished = shift->is_finished });
$req->parse("GET / HTTP/1.1\x0d\x0a");
$req->parse('Cookie: ' . ('a=b; ' x (1024 * 1024 * 2)) . "\x0d\x0a");
$req->parse("PUT /upload HTTP/1.1\x0d\x0aCookie: $huge\x0d\x0a");
$req->parse("Content-Length: 0\x0d\x0a\x0d\x0a");
ok $finished, 'finish event has been emitted';
ok $req->is_finished, 'request is finished';
is $req->content->leftovers, '', 'no leftovers';
is $req->error->{message}, 'Maximum message size exceeded', 'right error';
is $req->method, 'GET', 'right method';
is $req->version, '1.1', 'right version';
is $req->url, '/', 'right URL';
ok $req->is_limit_exceeded, 'limit is exceeded';
is $req->method, 'PUT', 'right method';
is $req->version, '1.1', 'right version';
is $req->url, '/upload', 'right URL';
is $req->cookie('a'), undef, 'no value';

# Parse HTTP 1.1 message with huge "Cookie" header exceeding line limit
Expand All @@ -33,9 +36,10 @@ $req->parse('Cookie: ' . ('a=b; ' x 131072) . "\x0d\x0a");
$req->parse("Content-Length: 0\x0d\x0a\x0d\x0a");
ok $req->is_finished, 'request is finished';
is $req->error->{message}, 'Maximum line size exceeded', 'right error';
is $req->method, 'GET', 'right method';
is $req->version, '1.1', 'right version';
is $req->url, '/', 'right URL';
ok $req->is_limit_exceeded, 'limit is exceeded';
is $req->method, 'GET', 'right method';
is $req->version, '1.1', 'right version';
is $req->url, '/', 'right URL';
is $req->cookie('a'), undef, 'no value';
is $req->body, '', 'no content';

Expand All @@ -48,9 +52,10 @@ $req->parse("Content-Length: 4\x0d\x0aCookie: "
. "\x0d\x0aX-Test: 23\x0d\x0a\x0d\x0aabcd");
ok $req->is_finished, 'request is finished';
is $req->error->{message}, 'Maximum line size exceeded', 'right error';
is $req->method, 'GET', 'right method';
is $req->version, '1.1', 'right version';
is $req->url, '/', 'right URL';
ok $req->is_limit_exceeded, 'limit is exceeded';
is $req->method, 'GET', 'right method';
is $req->version, '1.1', 'right version';
is $req->url, '/', 'right URL';
is $req->cookie('a'), undef, 'no value';
is $req->body, '', 'no content';

Expand All @@ -72,6 +77,7 @@ $req->parse("12345\x0d\x0a");
ok $req->is_finished, 'request is finished';
is $req->error->{message}, 'Bad request start line', 'right error';
is $req->error->{advice}, 400, 'right advice';
ok !$req->is_limit_exceeded, 'limit is not exceeded';

# Parse broken HTTP 1.1 message with header exceeding line limit
$req = Mojo::Message::Request->new;
Expand Down
8 changes: 5 additions & 3 deletions t/mojo/response.t
Expand Up @@ -368,14 +368,16 @@ is $res->headers->content_length, undef, 'right "Content-Length" value';
$res->parse("HTTP/1.1 200 OK\x0d\x0a");
$res->parse("Content-Type: text/plain\x0d\x0a");
$res->parse("Transfer-Encoding: chunked\x0d\x0a\x0d\x0a");
ok !$res->is_limit_exceeded, 'limit is not exceeded';
$res->parse('a' x 1000);
ok $res->is_finished, 'response is finished';
ok $res->content->is_finished, 'content is finished';
is $res->error->{message}, 'Maximum buffer size exceeded', 'right error';
is $res->error->{advice}, 400, 'right advice';
is $res->code, 200, 'right status';
is $res->message, 'OK', 'right message';
is $res->version, '1.1', 'right version';
ok $res->is_limit_exceeded, 'limit is not exceeded';
is $res->code, 200, 'right status';
is $res->message, 'OK', 'right message';
is $res->version, '1.1', 'right version';
is $res->headers->content_type, 'text/plain', 'right "Content-Type" value';
}

Expand Down

0 comments on commit dee50a7

Please sign in to comment.