diff --git a/actix-files/src/path_buf.rs b/actix-files/src/path_buf.rs index b20743a7d..f7f7cdab6 100644 --- a/actix-files/src/path_buf.rs +++ b/actix-files/src/path_buf.rs @@ -85,8 +85,7 @@ impl FromRequest for PathBufWrap { type Future = Ready>; fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { - // preferred over `req.path()` for safe percent decoding - ready(req.match_info().as_str().parse()) + ready(req.match_info().unprocessed().parse()) } } diff --git a/actix-files/src/service.rs b/actix-files/src/service.rs index 1a8cedbb9..5d494f878 100644 --- a/actix-files/src/service.rs +++ b/actix-files/src/service.rs @@ -120,16 +120,16 @@ impl Service for FilesService { )); } - // `req.match_info().as_str()` preferred over `req.path()` for safe percent decoding - - let real_path = - match PathBufWrap::parse_path(req.match_info().as_str(), this.hidden_files) { - Ok(item) => item, - Err(err) => return Ok(req.error_response(err)), - }; + let path_on_disk = match PathBufWrap::parse_path( + req.match_info().unprocessed(), + this.hidden_files, + ) { + Ok(item) => item, + Err(err) => return Ok(req.error_response(err)), + }; if let Some(filter) = &this.path_filter { - if !filter(real_path.as_ref(), req.head()) { + if !filter(path_on_disk.as_ref(), req.head()) { if let Some(ref default) = this.default { return default.call(req).await; } else { @@ -139,7 +139,7 @@ impl Service for FilesService { } // full file path - let path = this.directory.join(&real_path); + let path = this.directory.join(&path_on_disk); if let Err(err) = path.canonicalize() { return this.handle_err(err, req).await; } diff --git a/actix-router/src/path.rs b/actix-router/src/path.rs index 21bc63151..dfb645d72 100644 --- a/actix-router/src/path.rs +++ b/actix-router/src/path.rs @@ -62,6 +62,7 @@ impl Path { #[inline] pub fn unprocessed(&self) -> &str { profile_method!(unprocessed); + // clamp skip to path length let skip = (self.skip as usize).min(self.as_str().len()); &self.path.path()[skip..] }