aboutsummaryrefslogtreecommitdiffstats
path: root/src/file_upload.rs
diff options
context:
space:
mode:
authorAli MJ Al-Nasrawy <alimjalnasrawy@gmail.com>2021-09-04 20:08:47 +0000
committerAli MJ Al-Nasrawy <alimjalnasrawy@gmail.com>2021-09-04 20:12:33 +0000
commitdd528b3a32c9d653f99c0bb41b002a6744720189 (patch)
tree1241fd61a99f7b4bf7f2b30e04f314aa3e6fa927 /src/file_upload.rs
parentfile_upload.rs: sanitize path input (diff)
downloadminiserve-dd528b3a32c9d653f99c0bb41b002a6744720189.tar.gz
miniserve-dd528b3a32c9d653f99c0bb41b002a6744720189.zip
Adress review comments
Diffstat (limited to '')
-rw-r--r--src/file_upload.rs41
1 files changed, 39 insertions, 2 deletions
diff --git a/src/file_upload.rs b/src/file_upload.rs
index 2319b6a..5009f36 100644
--- a/src/file_upload.rs
+++ b/src/file_upload.rs
@@ -8,7 +8,10 @@ use std::{
use crate::errors::ContextualError;
use crate::listing::{self};
-/// Create future to save file.
+/// Saves file data from a multipart form field (`field`) to `file_path`, optionally overwriting
+/// existing file.
+///
+/// Returns total bytes written to file.
async fn save_file(
field: actix_multipart::Field,
file_path: PathBuf,
@@ -34,7 +37,7 @@ async fn save_file(
Ok(written_len)
}
-/// Create new future to handle file as multipart data.
+/// Handles a single field in a multipart form
async fn handle_multipart(
field: actix_multipart::Field,
path: PathBuf,
@@ -121,6 +124,8 @@ pub async fn upload_file(
/// Guarantee that the path is relative and cannot traverse back to parent directories
/// and optionally prevent traversing hidden directories.
+///
+/// See the unit tests tests::test_sanitize_path* for examples
fn sanitize_path(path: &Path, traverse_hidden: bool) -> Option<PathBuf> {
let mut buf = PathBuf::new();
@@ -145,3 +150,35 @@ fn sanitize_path(path: &Path, traverse_hidden: bool) -> Option<PathBuf> {
Some(buf)
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use pretty_assertions::assert_eq;
+ use rstest::rstest;
+
+ #[rstest]
+ #[case("/foo", "foo")]
+ #[case("////foo", "foo")]
+ #[case("C:/foo", if cfg!(windows) { "foo" } else { "C:/foo" })]
+ #[case("../foo", "foo")]
+ #[case("../foo/../bar/abc", "bar/abc")]
+ fn test_sanitize_path(#[case] input: &str, #[case] output: &str) {
+ assert_eq!(
+ sanitize_path(Path::new(input), true).unwrap(),
+ Path::new(output)
+ );
+ assert_eq!(
+ sanitize_path(Path::new(input), false).unwrap(),
+ Path::new(output)
+ );
+ }
+
+ #[rstest]
+ #[case(".foo")]
+ #[case("/.foo")]
+ #[case("foo/.bar/foo")]
+ fn test_sanitize_path_no_hidden_files(#[case] input: &str) {
+ assert_eq!(sanitize_path(Path::new(input), false), None);
+ }
+}