diff options
author | Loïc Hoguin <[email protected]> | 2014-02-19 18:56:50 +0100 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2014-02-19 18:56:50 +0100 |
commit | 943d80e7ec4eaf57a8a47b60d357ec35cb336d8a (patch) | |
tree | ced5fcabcd2e2316366b3261e546c311f443652f /src | |
parent | 5bc352df0cb2010b697179d8a25d2282db03c1e3 (diff) | |
download | cowlib-943d80e7ec4eaf57a8a47b60d357ec35cb336d8a.tar.gz cowlib-943d80e7ec4eaf57a8a47b60d357ec35cb336d8a.tar.bz2 cowlib-943d80e7ec4eaf57a8a47b60d357ec35cb336d8a.zip |
Fix bugs in cow_multipart:parse_body/2 when a partial was found at the end
There was three bugs: lack of a scope argument in binary:match (I swear
I had it in a previous version, whoops!); a misinterpretation of
the returned position when the scope is used (so yeah it wouldn't
have worked either way); \r\n being incorrectly removed when
we got a partial, despite not knowing whether it was a boundary.
Added a series of different tests to ensure that it all works as intended.
Diffstat (limited to 'src')
-rw-r--r-- | src/cow_multipart.erl | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/src/cow_multipart.erl b/src/cow_multipart.erl index e1acf63..c412497 100644 --- a/src/cow_multipart.erl +++ b/src/cow_multipart.erl @@ -216,18 +216,22 @@ parse_body(Stream, Boundary) -> %% No boundary, check for a possible partial at the end. %% Return more or less of the body depending on the result. nomatch -> - From = byte_size(Stream) - BoundarySize - 3, - case binary:match(Stream, <<"\r">>) of + StreamSize = byte_size(Stream), + From = StreamSize - BoundarySize - 3, + MatchOpts = if + %% Binary too small to contain boundary, check it fully. + From < 0 -> []; + %% Optimize, only check the end of the binary. + true -> [{scope, {From, StreamSize - From}}] + end, + case binary:match(Stream, <<"\r">>, MatchOpts) of nomatch -> {ok, Stream}; {Pos, _} -> - Pos2 = From + Pos, case Stream of - << Body:Pos2/binary, "\r\n" >> -> + << Body:Pos/binary >> -> {ok, Body}; - << Body:Pos2/binary, "\r\n", Rest/bits >> -> - {ok, Body, Rest}; - << Body:Pos2/binary, Rest/bits >> -> + << Body:Pos/binary, Rest/bits >> -> {ok, Body, Rest} end end; @@ -293,6 +297,29 @@ parse_interleaved_test() -> {done, Rest4} = parse_headers(InRest4, InBoundary), {done, <<>>} = parse_headers(Rest4, ?TEST2_BOUNDARY), ok. + +parse_partial_test() -> + {ok, <<0:8000, "abcdef">>, <<"\rghij">>} + = parse_body(<<0:8000, "abcdef\rghij">>, <<"boundary">>), + {ok, <<"abcdef">>, <<"\rghij">>} + = parse_body(<<"abcdef\rghij">>, <<"boundary">>), + {ok, <<"abc">>, <<"\rdef">>} + = parse_body(<<"abc\rdef">>, <<"boundaryboundary">>), + {ok, <<0:8000, "abcdef">>, <<"\r\nghij">>} + = parse_body(<<0:8000, "abcdef\r\nghij">>, <<"boundary">>), + {ok, <<"abcdef">>, <<"\r\nghij">>} + = parse_body(<<"abcdef\r\nghij">>, <<"boundary">>), + {ok, <<"abc">>, <<"\r\ndef">>} + = parse_body(<<"abc\r\ndef">>, <<"boundaryboundary">>), + {ok, <<"boundary">>, <<"\r">>} + = parse_body(<<"boundary\r">>, <<"boundary">>), + {ok, <<"boundary">>, <<"\r\n">>} + = parse_body(<<"boundary\r\n">>, <<"boundary">>), + {ok, <<"boundary">>, <<"\r\n-">>} + = parse_body(<<"boundary\r\n-">>, <<"boundary">>), + {ok, <<"boundary">>, <<"\r\n--">>} + = parse_body(<<"boundary\r\n--">>, <<"boundary">>), + ok. -endif. -ifdef(PERF). |