actix / actix/actix-web

deadlock in Tempfile::read_field with TestRequest

Abierto
#3,202 3 comentarios 0 reacciones 0 asignados Ver en GitHub
A-multipart needs-investigation
Lenguaje dominante
Rust
Estrellas
24.8k
Forks
1.9k
Merge medio
23 h 10 min
PR fusionados (30 d)
26

Descripción

I was creating a test for a case where a client sends an invalid multipart request without a closing boundary:

```rs
use actix_multipart::{
form::{tempfile::TempFile, FieldReader},
Multipart,
};
use actix_web::{
dev::{self, ServiceResponse},
error::ErrorBadRequest,
web, App, FromRequest, HttpServer, middleware::Logger,
};
use futures::StreamExt;

async fn test(srv_req: dev::ServiceRequest) -> actix_web::Result {
let (req, mut pl) = srv_req.into_parts();
let mut multipart = Multipart::from_request(&req, &mut pl).await?;
let file_field = multipart.next().await.ok_or(ErrorBadRequest("no file"))??;
let mut limits = actix_multipart::form::Limits::new(1000, 1000);
let file_obj = TempFile::read_field(&req, file_field, &mut limits).await?;
let resp = format!(
"Loaded file {:?} in {:?}",
file_obj.file_name,
file_obj.file.path()
);
Ok(ServiceResponse::new(
req,
actix_web::HttpResponse::Ok().body(resp),
))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init();
let srv = HttpServer::new(||
App::new().service(web::service("/").finish(test))
.wrap(Logger::default())
)
.bind("127.0.0.1:8080")?
.run();
srv.await
}

#[actix_web::test]
async fn test_problematic_payload() -> std::io::Result<()> {
use actix_web::test::TestRequest;

let testrequest = TestRequest::get()
.insert_header(("content-type", "multipart/form-data;boundary=xxx"))
.set_payload(
"--xxx\r\n\
Content-Disposition: form-data; name=\"my_uploaded_file\"; filename=\"test.txt\"\r\n\
\r\n\
Hello World\r\n\
", // no closing boundary
)
.to_srv_request();
let resp = test(testrequest).await.unwrap();
println!("Response: {:?}", resp.response().body());
Ok(())
}
```

## Expected Behavior

I would have expected the behavior with `TestRequest` to be the same as the one with the live server.

## Current Behavior

When running the live server and testing it manually with

```bash
nc -N localhost 8080 << EOF
POST / HTTP/1.1
Host: localhost:8081
User-Agent: curl/7.81.0
Accept: */*
Content-Length: 452
Content-Type: multipart/form-data; boundary=------------------------bf59f5a0357ff623

--------------------------bf59f5a0357ff623
Content-Disposition: form-data; name="my_file"; filename="hosts"
Content-Type: application/octet-stream

hello world
I do not have a closing boundary
EOF
```
Nothing deadlocks, and I get a proper response:

```http
HTTP/1.1 400 Bad Request
content-length: 30
content-type: text/plain; charset=utf-8
date: Thu, 23 Nov 2023 20:17:20 GMT

Multipart stream is incomplete
```

But when running the test with `cargo test`, it simply never returns.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.