@@ -138,7 +138,7 @@ stream_chunked(Data, State) ->
138138
139139% % New chunk.
140140stream_chunked (Data = << C , _ /bits >>, {0 , Streamed }, Acc ) when C =/= $\r ->
141- case chunked_len (Data , Streamed , Acc , 0 ) of
141+ case chunked_len (Data , Streamed , Acc , 0 , 0 ) of
142142 {next , Rest , State , Acc2 } ->
143143 stream_chunked (Rest , State , Acc2 );
144144 {more , State , Acc2 } ->
@@ -174,54 +174,54 @@ stream_chunked(Data, {Rem, Streamed}, Acc) when Rem > 2 ->
174174 {more , << Acc /binary , Data /binary >>, Rem2 , {Rem2 , Streamed + DataSize }}
175175 end .
176176
177- chunked_len (<< $0 , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 );
178- chunked_len (<< $1 , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 1 );
179- chunked_len (<< $2 , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 2 );
180- chunked_len (<< $3 , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 3 );
181- chunked_len (<< $4 , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 4 );
182- chunked_len (<< $5 , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 5 );
183- chunked_len (<< $6 , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 6 );
184- chunked_len (<< $7 , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 7 );
185- chunked_len (<< $8 , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 8 );
186- chunked_len (<< $9 , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 9 );
187- chunked_len (<< $A , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 10 );
188- chunked_len (<< $B , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 11 );
189- chunked_len (<< $C , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 12 );
190- chunked_len (<< $D , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 13 );
191- chunked_len (<< $E , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 14 );
192- chunked_len (<< $F , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 15 );
193- chunked_len (<< $a , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 10 );
194- chunked_len (<< $b , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 11 );
195- chunked_len (<< $c , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 12 );
196- chunked_len (<< $d , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 13 );
197- chunked_len (<< $e , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 14 );
198- chunked_len (<< $f , R /bits >>, S , A , Len ) -> chunked_len (R , S , A , Len * 16 + 15 );
177+ chunked_len (<< $0 , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 , D + 1 );
178+ chunked_len (<< $1 , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 1 , D + 1 );
179+ chunked_len (<< $2 , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 2 , D + 1 );
180+ chunked_len (<< $3 , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 3 , D + 1 );
181+ chunked_len (<< $4 , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 4 , D + 1 );
182+ chunked_len (<< $5 , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 5 , D + 1 );
183+ chunked_len (<< $6 , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 6 , D + 1 );
184+ chunked_len (<< $7 , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 7 , D + 1 );
185+ chunked_len (<< $8 , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 8 , D + 1 );
186+ chunked_len (<< $9 , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 9 , D + 1 );
187+ chunked_len (<< $A , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 10 , D + 1 );
188+ chunked_len (<< $B , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 11 , D + 1 );
189+ chunked_len (<< $C , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 12 , D + 1 );
190+ chunked_len (<< $D , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 13 , D + 1 );
191+ chunked_len (<< $E , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 14 , D + 1 );
192+ chunked_len (<< $F , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 15 , D + 1 );
193+ chunked_len (<< $a , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 10 , D + 1 );
194+ chunked_len (<< $b , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 11 , D + 1 );
195+ chunked_len (<< $c , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 12 , D + 1 );
196+ chunked_len (<< $d , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 13 , D + 1 );
197+ chunked_len (<< $e , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 14 , D + 1 );
198+ chunked_len (<< $f , R /bits >>, S , A , Len , D ) when D < 16 -> chunked_len (R , S , A , Len * 16 + 15 , D + 1 );
199199% % Chunk extensions.
200200% %
201201% % Note that we currently skip the first character we encounter here,
202202% % and not in the skip_chunk_ext function. If we latter implement
203203% % chunk extensions (unlikely) we will need to change this clause too.
204- chunked_len (<< C , R /bits >>, S , A , Len ) when ? IS_WS (C ); C =:= $; -> skip_chunk_ext (R , S , A , Len , 0 );
204+ chunked_len (<< C , R /bits >>, S , A , Len , _ ) when ? IS_WS (C ); C =:= $; -> skip_chunk_ext (R , S , A , Len , 0 );
205205% % Final chunk.
206206% %
207207% % When trailers are following we simply return them as the Rest.
208208% % Then the user code can decide to call the stream_trailers function
209209% % to parse them. The user can therefore ignore trailers as necessary
210210% % if they do not wish to handle them.
211- chunked_len (<< " \r\n\r\n " , R /bits >>, _ , <<>>, 0 ) -> {done , no_trailers , R };
212- chunked_len (<< " \r\n\r\n " , R /bits >>, _ , A , 0 ) -> {done , A , no_trailers , R };
213- chunked_len (<< " \r\n " , R /bits >>, _ , <<>>, 0 ) when byte_size (R ) > 2 -> {done , trailers , R };
214- chunked_len (<< " \r\n " , R /bits >>, _ , A , 0 ) when byte_size (R ) > 2 -> {done , A , trailers , R };
215- chunked_len (_ , _ , _ , 0 ) -> more ;
211+ chunked_len (<< " \r\n\r\n " , R /bits >>, _ , <<>>, 0 , _ ) -> {done , no_trailers , R };
212+ chunked_len (<< " \r\n\r\n " , R /bits >>, _ , A , 0 , _ ) -> {done , A , no_trailers , R };
213+ chunked_len (<< " \r\n " , R /bits >>, _ , <<>>, 0 , _ ) when byte_size (R ) > 2 -> {done , trailers , R };
214+ chunked_len (<< " \r\n " , R /bits >>, _ , A , 0 , _ ) when byte_size (R ) > 2 -> {done , A , trailers , R };
215+ chunked_len (_ , _ , _ , 0 , _ ) -> more ;
216216% % Normal chunk. Add 2 to Len for the trailing \r\n.
217- chunked_len (<< " \r\n " , R /bits >>, S , A , Len ) -> {next , R , {Len + 2 , S }, A };
218- chunked_len (<<" \r " >>, _ , <<>>, _ ) -> more ;
219- chunked_len (<<" \r " >>, S , A , _ ) -> {more , {0 , S }, A };
220- chunked_len (<<>>, _ , <<>>, _ ) -> more ;
221- chunked_len (<<>>, S , A , _ ) -> {more , {0 , S }, A }.
222-
223- skip_chunk_ext (R = << " \r " , _ /bits >>, S , A , Len , _ ) -> chunked_len (R , S , A , Len );
224- skip_chunk_ext (R = <<>>, S , A , Len , _ ) -> chunked_len (R , S , A , Len );
217+ chunked_len (<< " \r\n " , R /bits >>, S , A , Len , _ ) -> {next , R , {Len + 2 , S }, A };
218+ chunked_len (<<" \r " >>, _ , <<>>, _ , _ ) -> more ;
219+ chunked_len (<<" \r " >>, S , A , _ , _ ) -> {more , {0 , S }, A };
220+ chunked_len (<<>>, _ , <<>>, _ , _ ) -> more ;
221+ chunked_len (<<>>, S , A , _ , _ ) -> {more , {0 , S }, A }.
222+
223+ skip_chunk_ext (R = << " \r " , _ /bits >>, S , A , Len , _ ) -> chunked_len (R , S , A , Len , 0 );
224+ skip_chunk_ext (R = <<>>, S , A , Len , _ ) -> chunked_len (R , S , A , Len , 0 );
225225% % We skip up to 128 characters of chunk extensions. The value
226226% % is hardcoded: chunk extensions are very rarely seen in the
227227% % wild and Cowboy doesn't do anything with them anyway.
@@ -305,6 +305,7 @@ stream_chunked_n_passes_test() ->
305305 {more , <<" abc" >>, 2 , {2 , 3 }} = stream_chunked (<<" \n 3\r\n abc" >>, {1 , 0 }),
306306 {more , <<" abc" >>, {1 , 3 }} = stream_chunked (<<" 3\r\n abc\r " >>, {0 , 0 }),
307307 {more , <<" abc" >>, <<" 123" >>, {0 , 3 }} = stream_chunked (<<" 3\r\n abc\r\n 123" >>, {0 , 0 }),
308+ {more , <<>>, 18446744073709551617 , _ } = stream_chunked (<<" FFFFFFFFFFFFFFFF\r\n " >>, {0 , 0 }),
308309 ok .
309310
310311stream_chunked_dripfeed_test () ->
@@ -339,7 +340,8 @@ stream_chunked_dripfeed2_test() ->
339340stream_chunked_error_test_ () ->
340341 Tests = [
341342 {<<>>, undefined },
342- {<<" \n\n aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" >>, {2 , 0 }}
343+ {<<" \n\n aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" >>, {2 , 0 }},
344+ {<<" 10000000000000000\r\n " >>, {0 , 0 }}
343345 ],
344346 [{lists :flatten (io_lib :format (" value ~p state ~p " , [V , S ])),
345347 fun () -> {'EXIT' , _ } = (catch stream_chunked (V , S )) end }
0 commit comments