Skip to content

Commit

Permalink
add tests + support backreference
Browse files Browse the repository at this point in the history
  • Loading branch information
TheAlgorythm committed Dec 4, 2023
1 parent dff7211 commit 4a03b74
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@
//! filename.push_component(SinglePathComponent::new(user_input).unwrap());
//! # }
#[cfg(test)]
mod tests;

use std::path::PathBuf;

/// A safe wrapper for a path with only a single component.
/// This prevents path traversal attacks.
///
/// It allows just a single normal path element and no parent, root directory or prefix like `C:`.
/// Allows reference to the current directory of the path (`.`).
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct SinglePathComponent {
path: PathBuf,
Expand All @@ -47,6 +51,7 @@ impl SinglePathComponent {
/// # {
/// let some_valid_folder: SinglePathComponent = SinglePathComponent::new("foo").unwrap();
/// let some_valid_file: SinglePathComponent = SinglePathComponent::new("bar.txt").unwrap();
/// let with_backreference: SinglePathComponent = SinglePathComponent::new("./bar.txt").unwrap();
/// assert!(SinglePathComponent::new("/etc/shadow").is_none());
/// # }
/// ```
Expand All @@ -61,7 +66,11 @@ impl SinglePathComponent {
fn is_valid(&self) -> bool {
use std::path::Component;

let mut components = self.path.components();
let mut components = self
.path
.components()
.filter(|component| !matches!(component, Component::CurDir));

matches!(
(components.next(), components.next()),
(Some(Component::Normal(_)), None)
Expand Down
26 changes: 26 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use crate::prelude::*;
use std::path::PathBuf;

fn non_existing_absolute() -> PathBuf {
PathBuf::from("/23271d44-a599-4423-bb43-29b89b371ed0")
}

fn assert_single_disallow(path: &str) {
assert!(SinglePathComponent::new(path).is_none());
}

#[test]
fn single_disallow_parent() {
assert_single_disallow("../file");
}

#[test]
fn single_strip_current_dir() {
let mut path = non_existing_absolute();
let mut replica_path = non_existing_absolute();

path.push_component(SinglePathComponent::new("./file/.").unwrap());
replica_path.push("file");

assert_eq!(path, replica_path);
}

0 comments on commit 4a03b74

Please sign in to comment.