Skip to content

Commit

Permalink
improved error messages for start-line and header limits
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Jan 11, 2015
1 parent 6a88449 commit 8cb57c5
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 66 deletions.
5 changes: 3 additions & 2 deletions Changes
Expand Up @@ -4,6 +4,7 @@
[foo="bar" i] to Mojo::DOM::CSS.
- Improved Mojo::Reactor::EV to update the current time before starting a
timer.
- Improved error messages for start-line and header limits.
- Fixed bug in Mojo::Headers where max_line_size was not checked correctly.
- Fixed whitespace bug in Mojo::DOM::CSS.

Expand Down Expand Up @@ -3172,7 +3173,7 @@
- Made automatic file storage upgrade smarter.
- Fixed overload stringification and improved overall performance by about
25%.
- Fixed start line/header buffering and improved performance by 8%.
- Fixed start-line/header buffering and improved performance by 8%.

0.999934 2010-11-01
- Fixed relaxed HTTP parsing.
Expand Down Expand Up @@ -4130,7 +4131,7 @@
- Hooks for upload progress and stuff added.
- Refactored transfer encoding code into Mojo::Filter and
Mojo::Filter::Chunked.
- Added callbacks for start line and header generators.
- Added callbacks for start-line and header generators.
- Added workaround for missing IO::Seekable support in older versions of
File::Temp (Perl 5.8).
- script/mojo.pl got renamed to bin/mojo.
Expand Down
2 changes: 1 addition & 1 deletion examples/microhttpd.pl
Expand Up @@ -14,7 +14,7 @@
# Append chunk to buffer
$buffer{$id} .= $chunk;

# Check if we got start line and headers (no body support)
# Check if we got start-line and headers (no body support)
if (index($buffer{$id}, "\x0d\x0a\x0d\x0a") >= 0) {

# Clean buffer
Expand Down
20 changes: 10 additions & 10 deletions lib/Mojo/Message.pm
Expand Up @@ -150,13 +150,13 @@ sub parse {
$self->{raw_size} += length(my $chunk = shift // '');
$self->{buffer} .= $chunk;

# Start line
# Start-line
unless ($self->{state}) {

# Check line size
# Check start-line size
my $len = index $self->{buffer}, "\x0a";
$len = length $self->{buffer} if $len < 0;
return $self->_limit('Maximum line size exceeded', 431)
return $self->_limit('Maximum start-line size exceeded', 431)
if $len > $self->max_line_size;

$self->{state} = 'content' if $self->extract_start_line(\$self->{buffer});
Expand All @@ -172,8 +172,8 @@ sub parse {
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)
# Check header size
return $self->_limit('Maximum header size exceeded', 431)
if $self->headers->is_limit_exceeded;

# Check buffer size
Expand Down Expand Up @@ -384,7 +384,7 @@ Default charset used for form-data parsing, defaults to C<UTF-8>.
my $size = $msg->max_line_size;
$msg = $msg->max_line_size(1024);
Maximum start line size in bytes, defaults to the value of the
Maximum start-line size in bytes, defaults to the value of the
C<MOJO_MAX_LINE_SIZE> environment variable or C<10240> (10KB).
=head2 max_message_size
Expand Down Expand Up @@ -455,7 +455,7 @@ Render all headers.
my $bytes = $msg->build_start_line;
Render start line.
Render start-line.
=head2 cookie
Expand Down Expand Up @@ -537,7 +537,7 @@ an array reference.
my $bool = $msg->extract_start_line(\$str);
Extract start line from string. Meant to be overloaded in a subclass.
Extract start-line from string. Meant to be overloaded in a subclass.
=head2 finish
Expand Down Expand Up @@ -567,7 +567,7 @@ Get a chunk of header data, starting from a specific position.
my $bytes = $msg->get_start_line_chunk($offset);
Get a chunk of start line data starting from a specific position. Meant to be
Get a chunk of start-line data starting from a specific position. Meant to be
overloaded in a subclass.
=head2 header_size
Expand Down Expand Up @@ -622,7 +622,7 @@ Parse message chunk.
my $size = $msg->start_line_size;
Size of the start line in bytes.
Size of the start-line in bytes.
=head2 text
Expand Down
8 changes: 4 additions & 4 deletions lib/Mojo/Message/Request.pm
Expand Up @@ -59,8 +59,8 @@ sub extract_start_line {
# Ignore any leading empty lines
return undef unless $$bufref =~ s/^\s*(.*?)\x0d?\x0a//;

# We have a (hopefully) full request line
return !$self->error({message => 'Bad request start line', advice => 400})
# We have a (hopefully) full request-line
return !$self->error({message => 'Bad request start-line', advice => 400})
unless $1 =~ $START_LINE_RE;
my $url = $self->method($1)->version($3)->url;
return !!($1 eq 'CONNECT' ? $url->authority($2) : $url->parse($2));
Expand Down Expand Up @@ -367,7 +367,7 @@ array reference.
my $bool = $req->extract_start_line(\$str);
Extract request line from string.
Extract request-line from string.
=head2 fix_headers
Expand All @@ -379,7 +379,7 @@ Make sure request has all required headers.
my $bytes = $req->get_start_line_chunk($offset);
Get a chunk of request line data starting from a specific position.
Get a chunk of request-line data starting from a specific position.
=head2 is_handshake
Expand Down
6 changes: 3 additions & 3 deletions lib/Mojo/Message/Response.pm
Expand Up @@ -94,7 +94,7 @@ sub extract_start_line {

# We have a full response line
return undef unless $$bufref =~ s/^(.*?)\x0d?\x0a//;
return !$self->error({message => 'Bad response start line'})
return !$self->error({message => 'Bad response start-line'})
unless $1 =~ m!^\s*HTTP/(\d\.\d)\s+(\d\d\d)\s*(.+)?$!;

my $content = $self->content;
Expand Down Expand Up @@ -223,7 +223,7 @@ L</"code">.
my $bool = $res->extract_start_line(\$str);
Extract status line from string.
Extract status-line from string.
=head2 fix_headers
Expand All @@ -235,7 +235,7 @@ Make sure response has all required headers.
my $bytes = $res->get_start_line_chunk($offset);
Get a chunk of status line data starting from a specific position.
Get a chunk of status-line data starting from a specific position.
=head2 is_empty
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/Server/CGI.pm
Expand Up @@ -23,7 +23,7 @@ sub run {
# Handle request
$self->emit(request => $tx);

# Response start line
# Response start-line
STDOUT->autoflush(1);
binmode STDOUT;
my $res = $tx->res->fix_headers;
Expand Down
6 changes: 3 additions & 3 deletions lib/Mojo/Transaction/HTTP.pm
Expand Up @@ -119,7 +119,7 @@ sub _headers {
sub _start_line {
my ($self, $msg) = @_;

# Prepare start line chunk
# Prepare start-line chunk
my $buffer = $msg->get_start_line_chunk($self->{offset});
my $written = defined $buffer ? length $buffer : 0;
$self->{write} -= $written;
Expand Down Expand Up @@ -149,11 +149,11 @@ sub _write {
$headers->connection($self->keep_alive ? 'keep-alive' : 'close')
unless $headers->connection;

# Switch to start line
# Switch to start-line
@$self{qw(http_state write)} = ('start_line', $msg->start_line_size);
}

# Start line
# Start-line
my $chunk = '';
$chunk .= $self->_start_line($msg) if $self->{http_state} eq 'start_line';

Expand Down
14 changes: 10 additions & 4 deletions lib/Mojolicious/Guides/FAQ.pod
Expand Up @@ -140,13 +140,19 @@ around 10MB by default, you can use the attribute
L<Mojo::Message/"max_message_size"> or C<MOJO_MAX_MESSAGE_SIZE> environment
variable to change this value.

=head2 What does the error "Maximum line size exceeded" mean?
=head2 What does the error "Maximum start-line size exceeded" mean?

This is a very similar protection mechanism to the one described in the
previous answer, but a little more specific. It limits the maximum length of
the C<\x0d\x0a> terminated parts of a HTTP message, such as request line,
status line and headers. This limit is around 10KB by default, you can use the
attributes L<Mojo::Message/"max_line_size"> and
the start-line for HTTP requests and responses. This limit is around 10KB by
default, you can use the attribute L<Mojo::Message/"max_line_size"> or
C<MOJO_MAX_LINE_SIZE> environment variable to change this value.

=head2 What does the error "Maximum header size exceeded" mean?

Almost the same as the previous answer, but this protection mechanism limits
the maximum length of the HTTP request and response headers. This limit is
around 10KB by default, you can use the attribute
L<Mojo::Headers/"max_line_size"> or C<MOJO_MAX_LINE_SIZE> environment variable
to change this value.

Expand Down

0 comments on commit 8cb57c5

Please sign in to comment.