@@ -280,16 +280,26 @@ defmodule Bandit.HTTP1.Socket do
280280 # do_read_chunked_data! reads up to the configured length, reading multiple
281281 # chunks to do so. It accumulates data in the 'body' list, adding to it
282282 # chunk by (possibly partial) chunk until either the end of the body is reached
283- # or the configured length is exceeded
284- @ dialyzer { :no_improper_lists , do_read_chunked_data!: 5 }
283+ # or the configured length is exceeded. Note that an exhausted read budget must
284+ # be checked before attempting to read a chunk, since a zero-byte chunk read is
285+ # otherwise indistinguishable from the terminal chunk
285286 defp do_read_chunked_data! ( socket , buffer , body , body_length , opts ) do
286287 max_to_read = Keyword . get ( opts , :length , 8_000_000 ) - body_length
287288
289+ if max_to_read <= 0 do
290+ { :more , body , buffer }
291+ else
292+ do_read_next_chunk! ( socket , buffer , body , body_length , max_to_read , opts )
293+ end
294+ end
295+
296+ @ dialyzer { :no_improper_lists , do_read_next_chunk!: 6 }
297+ defp do_read_next_chunk! ( socket , buffer , body , body_length , max_to_read , opts ) do
288298 case do_read_chunk! ( socket , buffer , max_to_read , opts ) do
289- { << >> , rest } ->
299+ { :done , rest } ->
290300 { :ok , body , rest }
291301
292- { chunk , rest } ->
302+ { :chunk , chunk , rest } ->
293303 length = IO . iodata_length ( chunk )
294304
295305 if length < max_to_read do
@@ -319,7 +329,7 @@ defmodule Bandit.HTTP1.Socket do
319329 if trailers != [ ] ,
320330 do: Logger . warning ( "Encountered trailers in chunked request; ignoring" )
321331
322- { << >> , fake_socket . buffer }
332+ { :done , fake_socket . buffer }
323333
324334 { chunk_size , rest } ->
325335 to_read = min ( chunk_size , max_to_read )
@@ -335,11 +345,11 @@ defmodule Bandit.HTTP1.Socket do
335345 if IO . iodata_to_binary ( newline ) != "\r \n " ,
336346 do: request_error! ( "Malformed chunked encoding request body" )
337347
338- { to_return , rest }
348+ { :chunk , to_return , rest }
339349
340350 remaining when remaining > 0 ->
341351 # Build a binary since we'll be passing it to read_chunk_size! which expects a binary
342- { to_return , Integer . to_string ( remaining , 16 ) <> "\r \n " <> rest }
352+ { :chunk , to_return , Integer . to_string ( remaining , 16 ) <> "\r \n " <> rest }
343353 end
344354 end
345355 end
0 commit comments