@@ -1163,8 +1163,10 @@ defmodule Plug.Conn do
11631163 @ doc """
11641164 Reads the headers of a multipart request.
11651165
1166- It returns `{:ok, headers, conn}` with the headers or
1167- `{:done, conn}` if there are no more parts.
1166+ It returns `{:ok, headers, conn}` with the headers,
1167+ `{:error, :too_large, conn}` if the current multipart header block
1168+ exceeds the configured `:length`, or `{:done, conn}` if there are
1169+ no more parts.
11681170
11691171 Once `read_part_headers/2` is invoked, you may call
11701172 `read_part_body/2` to read the body associated to the headers.
@@ -1173,40 +1175,42 @@ defmodule Plug.Conn do
11731175
11741176 ## Options
11751177
1176- * `:length` - sets the maximum number of bytes to read from the body for
1177- each chunk , defaults to `64_000` bytes
1178+ * `:length` - sets the maximum number of bytes to read while parsing the
1179+ current multipart header block , defaults to `64_000` bytes
11781180 * `:read_length` - sets the amount of bytes to read at one time from the
11791181 underlying socket to fill the chunk, defaults to `64_000` bytes
11801182 * `:read_timeout` - sets the timeout for each socket read, defaults to
11811183 `5_000` milliseconds
11821184
11831185 """
1184- @ spec read_part_headers ( t , Keyword . t ( ) ) :: { :ok , headers , t } | { :done , t }
1186+ @ spec read_part_headers ( t , Keyword . t ( ) ) ::
1187+ { :ok , headers , t } | { :error , :too_large , t } | { :done , t }
11851188 def read_part_headers ( % Conn { adapter: { adapter , state } } = conn , opts \\ [ ] ) do
1186- opts = opts ++ [ length: 64_000 , read_length: 64_000 , read_timeout: 5000 ]
1187-
11881189 case init_multipart ( conn ) do
11891190 { boundary , buffer } ->
1191+ opts = opts ++ [ length: 64_000 , read_length: 64_000 , read_timeout: 5000 ]
1192+ length = Keyword . fetch! ( opts , :length )
11901193 { data , state } = read_multipart_from_buffer_or_adapter ( buffer , adapter , state , opts )
1191- read_part_headers ( conn , data , boundary , adapter , state , opts )
1194+ read_part_headers ( conn , data , length , boundary , adapter , state , opts )
11921195
11931196 :done ->
11941197 { :done , conn }
11951198 end
11961199 end
11971200
1198- defp read_part_headers ( conn , data , boundary , adapter , state , opts ) do
1201+ defp read_part_headers ( conn , data , length , boundary , adapter , state , opts ) do
11991202 case :plug_multipart . parse_headers ( data , boundary ) do
1203+ { :ok , _headers , rest } when byte_size ( data ) - byte_size ( rest ) > length ->
1204+ { :error , :too_large , store_multipart ( conn , { boundary , data } , adapter , state ) }
1205+
12001206 { :ok , headers , rest } ->
12011207 { :ok , headers , store_multipart ( conn , { boundary , rest } , adapter , state ) }
12021208
12031209 :more ->
1204- { _ , next , state } = next_multipart ( adapter , state , opts )
1205- read_part_headers ( conn , data <> next , boundary , adapter , state , opts )
1210+ read_part_headers_more ( conn , data , length , boundary , adapter , state , opts )
12061211
12071212 { :more , rest } ->
1208- { _ , next , state } = next_multipart ( adapter , state , opts )
1209- read_part_headers ( conn , rest <> next , boundary , adapter , state , opts )
1213+ read_part_headers_more ( conn , rest , length , boundary , adapter , state , opts )
12101214
12111215 { :done , _ } ->
12121216 { :done , store_multipart ( conn , :done , adapter , state ) }
@@ -1295,6 +1299,16 @@ defmodule Plug.Conn do
12951299 % { put_in ( conn . private [ :plug_multipart ] , multipart ) | adapter: { adapter , state } }
12961300 end
12971301
1302+ defp read_part_headers_more ( conn , data , length , boundary , adapter , state , _opts )
1303+ when byte_size ( data ) >= length do
1304+ { :error , :too_large , store_multipart ( conn , { boundary , data } , adapter , state ) }
1305+ end
1306+
1307+ defp read_part_headers_more ( conn , data , length , boundary , adapter , state , opts ) do
1308+ { _ , next , state } = next_multipart ( adapter , state , opts )
1309+ read_part_headers ( conn , data <> next , length , boundary , adapter , state , opts )
1310+ end
1311+
12981312 defp read_multipart_from_buffer_or_adapter ( "" , adapter , state , opts ) do
12991313 { _ , data , state } = adapter . read_req_body ( state , opts )
13001314 { data , state }
0 commit comments