actix / actix/actix-web

deadlock in Tempfile::read_field with TestRequest

オープン
#3,202 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る
A-multipart needs-investigation
主要言語
Rust
スター
24.8k
フォーク
1.9k
平均マージ
23時間 10分
マージ済み PR(30日)
26

説明

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.

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。