135 lines
3.7 KiB
Diff
135 lines
3.7 KiB
Diff
From be5bf4f1e2a8a61e6277e0a568cd3d0be058f0ae Mon Sep 17 00:00:00 2001
|
|
From: licunlong <licunlong1@huawei.com>
|
|
Date: Mon, 24 Jul 2023 11:47:53 +0800
|
|
Subject: [PATCH] fix: add two helper function to check if the path name is
|
|
safe, and path length is valid
|
|
|
|
---
|
|
libs/basic/src/path_util.rs | 98 +++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 98 insertions(+)
|
|
|
|
diff --git a/libs/basic/src/path_util.rs b/libs/basic/src/path_util.rs
|
|
index 7391615..58f8e49 100644
|
|
--- a/libs/basic/src/path_util.rs
|
|
+++ b/libs/basic/src/path_util.rs
|
|
@@ -14,6 +14,12 @@
|
|
//!
|
|
use std::path::Path;
|
|
|
|
+/// The maximum length of a linux path
|
|
+pub const PATH_LENGTH_MAX: usize = 4096;
|
|
+
|
|
+/// The maximum length of a linux file name
|
|
+pub const FILE_LENGTH_MAX: usize = 255;
|
|
+
|
|
/// return true if the path of a and b equaled.
|
|
pub fn path_equal(a: &str, b: &str) -> bool {
|
|
let p_a = Path::new(a);
|
|
@@ -21,6 +27,58 @@ pub fn path_equal(a: &str, b: &str) -> bool {
|
|
p_a == p_b
|
|
}
|
|
|
|
+/// check if the path name contains unsafe character
|
|
+///
|
|
+/// return true if it doesn't contain unsafe character
|
|
+pub fn path_name_is_safe(s: &str) -> bool {
|
|
+ if s.is_empty() {
|
|
+ return false;
|
|
+ }
|
|
+ for c in s.chars() {
|
|
+ if c > 0 as char && c < ' ' {
|
|
+ return false;
|
|
+ }
|
|
+ if (c as char).is_ascii_control() {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ true
|
|
+}
|
|
+
|
|
+/// check if the path length is valid
|
|
+pub fn path_length_is_valid(s: &str) -> bool {
|
|
+ if s.is_empty() {
|
|
+ return false;
|
|
+ }
|
|
+ if s.len() > PATH_LENGTH_MAX {
|
|
+ return false;
|
|
+ }
|
|
+ let mut de_len = 0;
|
|
+ let mut last_c = '/';
|
|
+ for c in s.chars() {
|
|
+ match c {
|
|
+ '/' => {
|
|
+ de_len = 0;
|
|
+ }
|
|
+ '.' => {
|
|
+ if last_c == '/' {
|
|
+ de_len = 1;
|
|
+ } else {
|
|
+ de_len += 1;
|
|
+ }
|
|
+ }
|
|
+ _ => {
|
|
+ de_len += 1;
|
|
+ }
|
|
+ }
|
|
+ if de_len > FILE_LENGTH_MAX {
|
|
+ return false;
|
|
+ }
|
|
+ last_c = c;
|
|
+ }
|
|
+ true
|
|
+}
|
|
+
|
|
/// Remove redundant inner and trailing slashes and unnecessary dots to simplify path.
|
|
/// e.g., //foo//.//bar/ becomes /foo/bar
|
|
/// .//foo//.//bar/ becomes foo/bar
|
|
@@ -77,4 +135,44 @@ mod tests {
|
|
assert_eq!(path_simplify(".//foo//.//bar/"), "foo/bar");
|
|
assert_eq!(path_simplify("foo//.//bar/"), "foo/bar");
|
|
}
|
|
+
|
|
+ #[test]
|
|
+ fn test_path_name_is_safe() {
|
|
+ assert!(!path_name_is_safe(""));
|
|
+ assert!(path_name_is_safe("/abc"));
|
|
+ assert!(!path_name_is_safe("/abc\x7f/a"));
|
|
+ assert!(!path_name_is_safe("/abc\x1f/a"));
|
|
+ assert!(!path_name_is_safe("/\x0a/a"));
|
|
+ }
|
|
+
|
|
+ #[test]
|
|
+ fn test_path_length_is_valid() {
|
|
+ assert!(!path_length_is_valid(""));
|
|
+
|
|
+ let path = "/a/".to_string() + &String::from_iter(vec!['1'; 255]);
|
|
+ assert!(path_length_is_valid(&path));
|
|
+
|
|
+ let path = "/a/".to_string() + &String::from_iter(vec!['1'; 256]);
|
|
+ assert!(!path_length_is_valid(&path));
|
|
+
|
|
+ let path = "/a/".to_string() + &String::from_iter(vec!['/'; 256]);
|
|
+ assert!(path_length_is_valid(&path));
|
|
+
|
|
+ let path = "/a/".to_string() + &String::from_iter(vec!['.'; 255]);
|
|
+ assert!(path_length_is_valid(&path));
|
|
+
|
|
+ let mut path = "".to_string();
|
|
+ for _ in 0..40 {
|
|
+ path += "/";
|
|
+ path += &String::from_iter(vec!['1'; 100]);
|
|
+ }
|
|
+ assert!(path_length_is_valid(&path));
|
|
+
|
|
+ let mut path = "".to_string();
|
|
+ for _ in 0..41 {
|
|
+ path += "/";
|
|
+ path += &String::from_iter(vec!['1'; 100]);
|
|
+ }
|
|
+ assert!(!path_length_is_valid(&path));
|
|
+ }
|
|
}
|
|
--
|
|
2.33.0
|
|
|