mirror of https://github.com/fafhrd91/actix-web
fix(multipart): count ignored fields towards `MultipartFormConfig` li… (#4026)
fix(multipart): count ignored fields towards `MultipartFormConfig` limits
This commit is contained in:
parent
be62050f9d
commit
4434a494ee
|
|
@ -227,7 +227,7 @@ pub fn impl_multipart_form(input: proc_macro::TokenStream) -> proc_macro::TokenS
|
|||
::actix_multipart::MultipartError::UnknownField(field.name().unwrap().to_string())
|
||||
))
|
||||
} else {
|
||||
quote!(::std::result::Result::Ok(()))
|
||||
quote!(::actix_multipart::form::discard_field(field, limits).await)
|
||||
};
|
||||
|
||||
// Value for duplicate action
|
||||
|
|
@ -289,7 +289,7 @@ pub fn impl_multipart_form(input: proc_macro::TokenStream) -> proc_macro::TokenS
|
|||
) -> ::std::pin::Pin<::std::boxed::Box<dyn ::std::future::Future<Output = ::std::result::Result<(), ::actix_multipart::MultipartError>> + 't>> {
|
||||
match field.name().unwrap() {
|
||||
#handle_field_impl
|
||||
_ => return ::std::boxed::Box::pin(::std::future::ready(#unknown_field_result)),
|
||||
_ => return ::std::boxed::Box::pin(async move { #unknown_field_result }),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,9 @@ where
|
|||
) -> Self::Future {
|
||||
if state.contains_key(&field.form_field_name) {
|
||||
match duplicate_field {
|
||||
DuplicateField::Ignore => return Box::pin(ready(Ok(()))),
|
||||
DuplicateField::Ignore => {
|
||||
return Box::pin(async move { discard_field(field, limits).await });
|
||||
}
|
||||
|
||||
DuplicateField::Deny => {
|
||||
return Box::pin(ready(Err(MultipartError::DuplicateField(
|
||||
|
|
@ -159,7 +161,9 @@ where
|
|||
) -> Self::Future {
|
||||
if state.contains_key(&field.form_field_name) {
|
||||
match duplicate_field {
|
||||
DuplicateField::Ignore => return Box::pin(ready(Ok(()))),
|
||||
DuplicateField::Ignore => {
|
||||
return Box::pin(async move { discard_field(field, limits).await });
|
||||
}
|
||||
|
||||
DuplicateField::Deny => {
|
||||
return Box::pin(ready(Err(MultipartError::DuplicateField(
|
||||
|
|
@ -312,6 +316,16 @@ impl Limits {
|
|||
}
|
||||
}
|
||||
|
||||
/// Drain a field that will not be retained while still accounting for form limits.
|
||||
#[doc(hidden)]
|
||||
pub async fn discard_field(mut field: Field, limits: &mut Limits) -> Result<(), MultipartError> {
|
||||
while let Some(chunk) = field.try_next().await? {
|
||||
limits.try_consume_limits(chunk.len(), false)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Typed `multipart/form-data` extractor.
|
||||
///
|
||||
/// To extract typed data from a multipart stream, the inner type `T` must implement the
|
||||
|
|
@ -710,6 +724,32 @@ mod tests {
|
|||
assert_eq!(response.status(), StatusCode::OK);
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_discarded_fields_count_towards_total_limit() {
|
||||
let srv = actix_test::start(|| {
|
||||
App::new()
|
||||
.route("/unknown", web::post().to(test_upload_limits_memory))
|
||||
.route("/duplicate", web::post().to(test_duplicate_ignore_route))
|
||||
.app_data(
|
||||
MultipartFormConfig::default()
|
||||
.memory_limit(usize::MAX)
|
||||
.total_limit(20),
|
||||
)
|
||||
});
|
||||
|
||||
let mut form = multipart::Form::default();
|
||||
form.add_text("field", "7 bytes");
|
||||
form.add_text("unknown", "this string is 28 bytes long");
|
||||
let response = send_form(&srv, form, "/unknown").await;
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
|
||||
let mut form = multipart::Form::default();
|
||||
form.add_text("field", "first_value");
|
||||
form.add_text("field", "this string is 28 bytes long");
|
||||
let response = send_form(&srv, form, "/duplicate").await;
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
}
|
||||
|
||||
/// Test the Limits.
|
||||
#[derive(MultipartForm)]
|
||||
struct TestMemoryUploadLimits {
|
||||
|
|
|
|||
Loading…
Reference in New Issue