From 0c664cd79aae0889524f6066d77ead30a9530147 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Tue, 12 Oct 2021 05:32:11 +0300 Subject: [PATCH] dontuse lossy decoding --- actix-files/src/error.rs | 3 +++ actix-files/src/path_buf.rs | 4 ++++ actix-files/src/service.rs | 12 +++++------- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/actix-files/src/error.rs b/actix-files/src/error.rs index f8e32eef7..242eda4be 100644 --- a/actix-files/src/error.rs +++ b/actix-files/src/error.rs @@ -33,6 +33,9 @@ pub enum UriSegmentError { /// The segment ended with the wrapped invalid character. #[display(fmt = "The segment ended with the wrapped invalid character")] BadEnd(char), + /// The path is not a valid UTF-8 string after doing percent decoding. + #[display(fmt = "The path is not a valif UTF-8 string after percent-decoding")] + NotValidUtf8, } /// Return `BadRequest` for `UriSegmentError` diff --git a/actix-files/src/path_buf.rs b/actix-files/src/path_buf.rs index 76f589307..1eef8e009 100644 --- a/actix-files/src/path_buf.rs +++ b/actix-files/src/path_buf.rs @@ -24,6 +24,10 @@ impl PathBufWrap { pub fn parse_path(path: &str, hidden_files: bool) -> Result { let mut buf = PathBuf::new(); + let path = percent_encoding::percent_decode_str(path) + .decode_utf8() + .map_err(|_| UriSegmentError::NotValidUtf8)?; + for segment in path.split('/') { if segment == ".." { buf.pop(); diff --git a/actix-files/src/service.rs b/actix-files/src/service.rs index 300937967..09122c63e 100644 --- a/actix-files/src/service.rs +++ b/actix-files/src/service.rs @@ -77,13 +77,11 @@ impl Service for FilesService { ))); } - let path_decoded = - percent_encoding::percent_decode_str(req.match_info().path()).decode_utf8_lossy(); - - let real_path = match PathBufWrap::parse_path(&path_decoded, self.hidden_files) { - Ok(item) => item, - Err(e) => return Box::pin(ok(req.error_response(e))), - }; + let real_path = + match PathBufWrap::parse_path(req.match_info().path(), self.hidden_files) { + Ok(item) => item, + Err(e) => return Box::pin(ok(req.error_response(e))), + }; if let Some(filter) = &self.path_filter { if !filter(real_path.as_ref(), req.head()) {