Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Fix 0-length range responses. #87

Merged
merged 2 commits into from

2 participants

@pmundkur

There were two issues:

  • file:pread() returns eof in the case when the length of the
    read is 0 bytes, for any offset. This causes badarg exceptions
    later in iolist_size when the 'eof' atom is encountered instead
    of a binary

  • The range-length computation is off by 1 for 0-length ranges:
    {Skip, Skip + Length - 1, PartialBody} would result in e.g.
    {0, -1, eof}. {0, -1} is invalid HTTP according to

    http://tools.ietf.org/html/rfc2616#section-14.16

    A byte-content-range-spec with a byte-range-resp-spec whose
    last-byte-pos value is less than its first-byte-pos value,
    or whose instance-length value is less than or equal to its
    last-byte-pos value, is invalid.

This patch fixes both issues.

@pmundkur pmundkur Fix 0-length range responses.
There were two issues:

- file:pread() returns eof in the case when the length of the
  read is 0 bytes, for any offset.  This causes badarg exceptions
  later in iolist_size when the 'eof' atom is encountered instead
  of a binary

- The range-length computation is off by 1 for 0-length ranges:
  {Skip, Skip + Length - 1, PartialBody} would result in e.g.
  {0, -1, eof}. {0, -1} is invalid HTTP according to

  http://tools.ietf.org/html/rfc2616#section-14.16

     A byte-content-range-spec with a byte-range-resp-spec whose
     last-byte-pos value is less than its first-byte-pos value,
     or whose instance-length value is less than or equal to its
     last-byte-pos value, is invalid.

This patch fixes both issues.
8ec8af1
@etrepum
Owner

It'd be really great if there were tests that showed the issue and ensured that this doesn't regress

@pmundkur

I didn't find any existing tests in mochiweb_{http, request} that could be adapted for the purpose. Where should I look?

@etrepum
Owner

Well, it doesn't appear that there's an obvious test in this repo that you can just copy and modify. The way that I've done this kind of test in the past is to just have the test start up a server listening on a random port on loopback, send a request to that port with the right headers, and inspect the response for correctness. A bit heavyweight but it does verify the functionality and cover all of the code in that path.

@pmundkur

The problem with such tests is that they tend to be sensitive to timing (see for e.g. the tests I supplied for pull #44). You suggested there to use meck instead; that is probably a better approach, but I won't be able to get to it anytime soon.

@etrepum
Owner
@etrepum etrepum merged commit 510766b into mochi:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 6, 2012
  1. @pmundkur

    Fix 0-length range responses.

    pmundkur authored
    There were two issues:
    
    - file:pread() returns eof in the case when the length of the
      read is 0 bytes, for any offset.  This causes badarg exceptions
      later in iolist_size when the 'eof' atom is encountered instead
      of a binary
    
    - The range-length computation is off by 1 for 0-length ranges:
      {Skip, Skip + Length - 1, PartialBody} would result in e.g.
      {0, -1, eof}. {0, -1} is invalid HTTP according to
    
      http://tools.ietf.org/html/rfc2616#section-14.16
    
         A byte-content-range-spec with a byte-range-resp-spec whose
         last-byte-pos value is less than its first-byte-pos value,
         or whose instance-length value is less than or equal to its
         last-byte-pos value, is invalid.
    
    This patch fixes both issues.
Commits on Nov 19, 2012
  1. @pmundkur
This page is out of date. Refresh to see the latest.
Showing with 6 additions and 1 deletion.
  1. +6 −1 src/mochiweb_request.erl
View
7 src/mochiweb_request.erl
@@ -655,7 +655,12 @@ range_parts({file, IoDevice}, Ranges) ->
LocNums = lists:foldr(F, [], Ranges),
{ok, Data} = file:pread(IoDevice, LocNums),
Bodies = lists:zipwith(fun ({Skip, Length}, PartialBody) ->
- {Skip, Skip + Length - 1, PartialBody}
+ case Length of
+ 0 ->
+ {Skip, Skip, <<>>};
+ _ ->
+ {Skip, Skip + Length - 1, PartialBody}
+ end
end,
LocNums, Data),
{Bodies, Size};
Something went wrong with that request. Please try again.