Skip to content

Commit e87a7d4

Browse files
committed
Handle the case of junk following new line.
@art0007i also reported archives containing paths with junk following the new line, this will handle the situation and also adds unit tests for this. Update cargo libraries.
1 parent b457013 commit e87a7d4

File tree

3 files changed

+108
-48
lines changed

3 files changed

+108
-48
lines changed

Cargo.lock

Lines changed: 31 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main.rs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ use tokio::io::AsyncWriteExt;
1111
use tokio::task::JoinHandle;
1212
use tokio::{fs, io};
1313

14+
mod sanitize_path;
15+
1416
struct Config {
1517
input_path: String,
1618
log_level: LevelFilter,
1719
}
1820

19-
const TRIM_CHARS: &[char] = &['\0', ' ', '\n', '\t', '\r', '/', '.'];
20-
2121
type AssetMap = HashMap<PathBuf, Vec<u8>>;
2222
type FolderMap = HashMap<OsString, bool>;
2323
type ExtractTask = Vec<JoinHandle<Result<(), io::Error>>>;
@@ -59,20 +59,6 @@ fn parse_arguments() -> Config {
5959
}
6060
}
6161

62-
fn sanitize_path(path: &str) -> Result<String, io::Error> {
63-
let sanitized_path = path.trim_matches(TRIM_CHARS).replace('\\', "/");
64-
65-
if sanitized_path.contains("..") {
66-
warn!("path «{}» contains .., this isn't supported", path);
67-
return Err(io::Error::new(
68-
io::ErrorKind::InvalidInput,
69-
"Path contains invalid '..'",
70-
));
71-
}
72-
73-
Ok(sanitized_path)
74-
}
75-
7662
fn read_asset_to_memory<R: Read>(
7763
assets: &mut AssetMap,
7864
mut entry: tar::Entry<'_, R>,
@@ -135,7 +121,7 @@ async fn write_asset_to_pathname(
135121
entry_hash: PathBuf,
136122
path_name: String,
137123
) -> Result<(), io::Error> {
138-
let target_path = sanitize_path(&path_name)?;
124+
let target_path = sanitize_path::sanitize_path(&path_name)?;
139125

140126
if path_name != target_path {
141127
debug!(

src/sanitize_path.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use log::warn;
2+
use std::io;
3+
4+
const TRIM_CHARS: &[char] = &['\0', ' ', '\n', '\t', '\r', '/', '.'];
5+
const END_OF_STRING_CHARS: &[char] = &['\0', '\n', '\r'];
6+
7+
pub fn sanitize_path(path: &str) -> Result<String, io::Error> {
8+
let sanitized_path = path.trim_matches(TRIM_CHARS).replace('\\', "/");
9+
10+
if let Some(idx) = sanitized_path.rfind('/') {
11+
let (dir_part, _) = sanitized_path.split_at(idx);
12+
13+
// Check for ".." only in the directory part
14+
if dir_part.contains("..") {
15+
warn!(
16+
"path «{}» contains .. in directory part, this isn't supported",
17+
path
18+
);
19+
return Err(io::Error::new(
20+
io::ErrorKind::InvalidInput,
21+
"Path contains invalid '..' in directory part",
22+
));
23+
}
24+
}
25+
26+
match sanitized_path.find(END_OF_STRING_CHARS) {
27+
Some(idx) => {
28+
let (final_path, _) = sanitized_path.split_at(idx);
29+
Ok(final_path.to_string())
30+
}
31+
None => Ok(sanitized_path),
32+
}
33+
}
34+
35+
#[cfg(test)]
36+
mod tests {
37+
use super::*;
38+
39+
#[test]
40+
fn test_sanitize_path() {
41+
// Normal filename
42+
assert_eq!(sanitize_path("filename.ext").unwrap(), "filename.ext");
43+
44+
// Normal path
45+
assert_eq!(
46+
sanitize_path("folder\\file.ext").unwrap(),
47+
"folder/file.ext"
48+
);
49+
50+
// Unix path
51+
assert_eq!(sanitize_path("folder/file.ext").unwrap(), "folder/file.ext");
52+
53+
// Any number or ../ at the start will be removed.
54+
assert_eq!(
55+
sanitize_path("../folder/file.ext").unwrap(),
56+
"folder/file.ext"
57+
);
58+
59+
// .. anywhere in the dir part will error out.
60+
assert!(sanitize_path("folder/../file.ext").is_err());
61+
62+
// new line/empty chars at the end should be removed
63+
assert_eq!(
64+
sanitize_path("folder/file.ext\r\n\0").unwrap(),
65+
"folder/file.ext"
66+
);
67+
68+
// anything after a new line should be trimmed off
69+
assert_eq!(
70+
sanitize_path("folder/file.ext\n00").unwrap(),
71+
"folder/file.ext"
72+
);
73+
}
74+
}

0 commit comments

Comments
 (0)