Remove check that paths are inside game path

It didn't work correctly for OpenMW or for additional data paths, fixing it would be significantly more complicated, and it doesn't really add any value.
This commit is contained in:
Oliver Hamlet
2025-04-27 18:37:40 +01:00
parent 50d9d11b6b
commit dbbbcd58e5
2 changed files with 8 additions and 113 deletions
+8 -103
View File
@@ -1,4 +1,4 @@
use std::path::{Component, Path, PathBuf}; use std::path::PathBuf;
use std::str; use std::str;
use nom::branch::alt; use nom::branch::alt;
@@ -12,7 +12,7 @@ use regex::{Regex, RegexBuilder};
use super::{ComparisonOperator, Function}; use super::{ComparisonOperator, Function};
use crate::error::ParsingErrorKind; use crate::error::ParsingErrorKind;
use crate::{map_err, whitespace, ParsingError, ParsingResult}; use crate::{map_err, whitespace, ParsingResult};
impl ComparisonOperator { impl ComparisonOperator {
pub fn parse(input: &str) -> IResult<&str, ComparisonOperator> { pub fn parse(input: &str) -> IResult<&str, ComparisonOperator> {
@@ -32,20 +32,6 @@ const INVALID_PATH_CHARS: &str = "\":*?<>|";
const INVALID_NON_REGEX_PATH_CHARS: &str = "\":*?<>|\\"; // \ is treated as invalid to distinguish regex strings. const INVALID_NON_REGEX_PATH_CHARS: &str = "\":*?<>|\\"; // \ is treated as invalid to distinguish regex strings.
const INVALID_REGEX_PATH_CHARS: &str = "\"<>"; const INVALID_REGEX_PATH_CHARS: &str = "\"<>";
fn is_in_game_path(path: &Path) -> bool {
let mut previous_component = Component::CurDir;
for component in path.components() {
match (component, previous_component) {
(Component::Prefix(_) | Component::RootDir, _)
| (Component::ParentDir, Component::ParentDir) => return false,
(Component::CurDir, _) => {}
_ => previous_component = component,
}
}
true
}
fn build_regex(input: &str) -> Result<(&'static str, Regex), regex::Error> { fn build_regex(input: &str) -> Result<(&'static str, Regex), regex::Error> {
RegexBuilder::new(input) RegexBuilder::new(input)
.case_insensitive(true) .case_insensitive(true)
@@ -62,10 +48,6 @@ fn parse_anchored_regex(input: &str) -> ParsingResult<Regex> {
.map_err(|e| Err::Failure(ParsingErrorKind::from(e).at(input))) .map_err(|e| Err::Failure(ParsingErrorKind::from(e).at(input)))
} }
fn not_in_game_directory(input: &str, path: PathBuf) -> Err<ParsingError<&str>> {
Err::Failure(ParsingErrorKind::PathIsNotInGameDirectory(path).at(input))
}
fn parse_path(input: &str) -> IResult<&str, PathBuf> { fn parse_path(input: &str) -> IResult<&str, PathBuf> {
map( map(
delimited(tag("\""), is_not(INVALID_PATH_CHARS), tag("\"")), delimited(tag("\""), is_not(INVALID_PATH_CHARS), tag("\"")),
@@ -89,11 +71,7 @@ fn parse_file_size_args(input: &str) -> ParsingResult<(PathBuf, u64)> {
let (remaining_input, (path, _, size)) = parser.parse(input)?; let (remaining_input, (path, _, size)) = parser.parse(input)?;
if is_in_game_path(&path) { Ok((remaining_input, (path, size)))
Ok((remaining_input, (path, size)))
} else {
Err(not_in_game_directory(input, path))
}
} }
fn parse_version(input: &str) -> IResult<&str, String> { fn parse_version(input: &str) -> IResult<&str, String> {
@@ -115,11 +93,7 @@ fn parse_version_args(input: &str) -> ParsingResult<(PathBuf, String, Comparison
let (remaining_input, (path, _, version, _, comparator)) = map_err(parser).parse(input)?; let (remaining_input, (path, _, version, _, comparator)) = map_err(parser).parse(input)?;
if is_in_game_path(&path) { Ok((remaining_input, (path, version, comparator)))
Ok((remaining_input, (path, version, comparator)))
} else {
Err(not_in_game_directory(input, path))
}
} }
fn parse_filename_version_args( fn parse_filename_version_args(
@@ -175,11 +149,7 @@ fn parse_checksum_args(input: &str) -> ParsingResult<(PathBuf, u32)> {
let (remaining_input, (path, _, crc)) = parser.parse(input)?; let (remaining_input, (path, _, crc)) = parser.parse(input)?;
if is_in_game_path(&path) { Ok((remaining_input, (path, crc)))
Ok((remaining_input, (path, crc)))
} else {
Err(not_in_game_directory(input, path))
}
} }
fn parse_non_regex_path(input: &str) -> ParsingResult<PathBuf> { fn parse_non_regex_path(input: &str) -> ParsingResult<PathBuf> {
@@ -188,11 +158,7 @@ fn parse_non_regex_path(input: &str) -> ParsingResult<PathBuf> {
}) })
.parse(input)?; .parse(input)?;
if is_in_game_path(&path) { Ok((remaining_input, path))
Ok((remaining_input, path))
} else {
Err(not_in_game_directory(input, path))
}
} }
/// Parse a string that is a path where the last component is a regex string /// Parse a string that is a path where the last component is a regex string
@@ -210,10 +176,6 @@ fn parse_regex_path(input: &str) -> ParsingResult<(PathBuf, Regex)> {
let parent_path = PathBuf::from(parent_path_slice); let parent_path = PathBuf::from(parent_path_slice);
if !is_in_game_path(&parent_path) {
return Err(not_in_game_directory(input, parent_path));
}
let regex = parse_anchored_regex(regex_slice)?.1; let regex = parse_anchored_regex(regex_slice)?.1;
Ok((remaining_input, (parent_path, regex))) Ok((remaining_input, (parent_path, regex)))
@@ -356,6 +318,8 @@ impl Function {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::path::Path;
use super::*; use super::*;
#[test] #[test]
@@ -397,11 +361,6 @@ mod tests {
} }
} }
#[test]
fn function_parse_should_error_if_the_file_path_is_outside_the_game_directory() {
assert!(Function::parse("file(\"../../Cargo.toml\")").is_err());
}
#[test] #[test]
fn function_parse_should_parse_a_file_regex_function_with_no_parent_path() { fn function_parse_should_parse_a_file_regex_function_with_no_parent_path() {
let output = Function::parse("file(\"Cargo.*\")").unwrap(); let output = Function::parse("file(\"Cargo.*\")").unwrap();
@@ -435,11 +394,6 @@ mod tests {
assert!(Function::parse("file(\"sub\\dir/\")").is_err()); assert!(Function::parse("file(\"sub\\dir/\")").is_err());
} }
#[test]
fn function_parse_should_error_if_the_file_regex_parent_path_is_outside_the_game_directory() {
assert!(Function::parse("file(\"../../Cargo.*\")").is_err());
}
#[test] #[test]
fn function_parse_should_parse_a_file_size_function() { fn function_parse_should_parse_a_file_size_function() {
let output = Function::parse("file_size(\"Cargo.toml\", 1234)").unwrap(); let output = Function::parse("file_size(\"Cargo.toml\", 1234)").unwrap();
@@ -454,11 +408,6 @@ mod tests {
} }
} }
#[test]
fn function_parse_should_error_if_the_file_size_is_outside_the_game_directory() {
assert!(Function::parse("file_size(\"../../Cargo.toml\", 1234)").is_err());
}
#[test] #[test]
fn function_parse_should_parse_a_readable_function() { fn function_parse_should_parse_a_readable_function() {
let output = Function::parse("readable(\"Cargo.toml\")").unwrap(); let output = Function::parse("readable(\"Cargo.toml\")").unwrap();
@@ -470,11 +419,6 @@ mod tests {
} }
} }
#[test]
fn function_parse_should_error_if_the_readable_path_is_outside_the_game_directory() {
assert!(Function::parse("readable(\"../../Cargo.toml\")").is_err());
}
#[test] #[test]
fn function_parse_should_parse_an_is_executable_function() { fn function_parse_should_parse_an_is_executable_function() {
let output = Function::parse("is_executable(\"Cargo.toml\")").unwrap(); let output = Function::parse("is_executable(\"Cargo.toml\")").unwrap();
@@ -486,11 +430,6 @@ mod tests {
} }
} }
#[test]
fn function_parse_should_error_if_the_is_executable_path_is_outside_the_game_directory() {
assert!(Function::parse("is_executable(\"../../Cargo.toml\")").is_err());
}
#[test] #[test]
fn function_parse_should_parse_an_active_path_function() { fn function_parse_should_parse_an_active_path_function() {
let output = Function::parse("active(\"Cargo.toml\")").unwrap(); let output = Function::parse("active(\"Cargo.toml\")").unwrap();
@@ -502,13 +441,6 @@ mod tests {
} }
} }
#[test]
fn function_parse_should_error_if_the_active_path_is_outside_the_game_directory() {
// Trying to check if a path that isn't a plugin in the data folder is
// active is pointless, but it's not worth having a more specific check.
assert!(Function::parse("active(\"../../Cargo.toml\")").is_err());
}
#[test] #[test]
fn function_parse_should_parse_an_active_regex_function() { fn function_parse_should_parse_an_active_regex_function() {
let output = Function::parse("active(\"Cargo.*\")").unwrap(); let output = Function::parse("active(\"Cargo.*\")").unwrap();
@@ -533,13 +465,6 @@ mod tests {
} }
} }
#[test]
fn function_parse_should_error_if_the_is_master_path_is_outside_the_game_directory() {
// Trying to check if a path that isn't a plugin in the data folder is
// active is pointless, but it's not worth having a more specific check.
assert!(Function::parse("is_master(\"../../Blank.esm\")").is_err());
}
#[test] #[test]
fn function_parse_should_parse_a_many_function_with_no_parent_path() { fn function_parse_should_parse_a_many_function_with_no_parent_path() {
let output = Function::parse("many(\"Cargo.*\")").unwrap(); let output = Function::parse("many(\"Cargo.*\")").unwrap();
@@ -573,11 +498,6 @@ mod tests {
assert!(Function::parse("many(\"subdir/\")").is_err()); assert!(Function::parse("many(\"subdir/\")").is_err());
} }
#[test]
fn function_parse_should_error_if_the_many_parent_path_is_outside_the_game_directory() {
assert!(Function::parse("file(\"../../Cargo.*\")").is_err());
}
#[test] #[test]
fn function_parse_should_parse_a_many_active_function() { fn function_parse_should_parse_a_many_active_function() {
let output = Function::parse("many_active(\"Cargo.*\")").unwrap(); let output = Function::parse("many_active(\"Cargo.*\")").unwrap();
@@ -605,11 +525,6 @@ mod tests {
} }
} }
#[test]
fn function_parse_should_error_if_the_checksum_path_is_outside_the_game_directory() {
assert!(Function::parse("checksum(\"../../Cargo.toml\", DEADBEEF)").is_err());
}
#[test] #[test]
fn function_parse_should_parse_a_version_equals_function() { fn function_parse_should_parse_a_version_equals_function() {
let output = Function::parse("version(\"Cargo.toml\", \"1.2\", ==)").unwrap(); let output = Function::parse("version(\"Cargo.toml\", \"1.2\", ==)").unwrap();
@@ -715,11 +630,6 @@ mod tests {
} }
} }
#[test]
fn function_parse_should_error_if_the_version_path_is_outside_the_game_directory() {
assert!(Function::parse("version(\"../../Cargo.toml\", \"1.2\", ==)").is_err());
}
#[test] #[test]
fn function_parse_should_parse_a_product_version_equals_function() { fn function_parse_should_parse_a_product_version_equals_function() {
let output = Function::parse("product_version(\"Cargo.toml\", \"1.2\", ==)").unwrap(); let output = Function::parse("product_version(\"Cargo.toml\", \"1.2\", ==)").unwrap();
@@ -735,11 +645,6 @@ mod tests {
} }
} }
#[test]
fn function_parse_should_error_if_the_product_version_path_is_outside_the_game_directory() {
assert!(Function::parse("product_version(\"../../Cargo.toml\", \"1.2\", ==)").is_err());
}
#[test] #[test]
fn function_parse_should_parse_a_filename_version_equals_function() { fn function_parse_should_parse_a_filename_version_equals_function() {
let output = let output =
-10
View File
@@ -488,16 +488,6 @@ mod tests {
); );
} }
#[test]
fn expression_from_str_should_error_with_input_on_path_outside_game_directory() {
let error = Expression::from_str("file(\"../../Cargo.toml\")").unwrap_err();
assert_eq!(
"An error was encountered while parsing the expression \"../../Cargo.toml\\\")\": \"../../Cargo.toml\" is not in the game directory",
error.to_string()
);
}
#[test] #[test]
fn expression_parse_should_handle_a_single_compound_condition() { fn expression_parse_should_handle_a_single_compound_condition() {
let result = Expression::from_str("file(\"Cargo.toml\")").unwrap(); let result = Expression::from_str("file(\"Cargo.toml\")").unwrap();