Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/fix-fs-scope-escape-paths.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
fs: patch
---

Paths given to the `Scope` methods are now correctly escaped, preventing issues with paths containing `[]`.
2 changes: 1 addition & 1 deletion plugins/fs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]

[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
windows = { level = "full", notes = "No write access to `$RESOURCES` folder with MSI installer and NSIS installers in `perMachine` or `both` mode" }
linux = { level = "full", notes = "No write access to `$RESOURCES` folder" }
macos = { level = "full", notes = "No write access to `$RESOURCES` folder" }
android = { level = "partial", notes = "Access is restricted to Application folder by default" }
Expand Down
44 changes: 38 additions & 6 deletions plugins/fs/src/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ impl Scope {

{
let mut allowed = self.allowed.lock().unwrap();
allowed.push(path.to_path_buf());
allowed.push(path.join(if recursive { "**" } else { "*" }));
let p = path.to_string_lossy();
allowed.push(escape(&p));
allowed.push(PathBuf::from(if recursive { "**" } else { "*" }));
}

self.emit(Event::PathAllowed(path.to_path_buf()));
Expand All @@ -69,7 +70,10 @@ impl Scope {
pub fn allow_file<P: AsRef<Path>>(&self, path: P) {
let path = path.as_ref();

self.allowed.lock().unwrap().push(path.to_path_buf());
self.allowed
.lock()
.unwrap()
.push(escape(&path.to_string_lossy()));

self.emit(Event::PathAllowed(path.to_path_buf()));
}
Expand All @@ -82,8 +86,9 @@ impl Scope {

{
let mut denied = self.denied.lock().unwrap();
denied.push(path.to_path_buf());
denied.push(path.join(if recursive { "**" } else { "*" }));
let p = path.to_string_lossy();
denied.push(escape(&p));
denied.push(PathBuf::from(if recursive { "**" } else { "*" }));
}

self.emit(Event::PathForbidden(path.to_path_buf()));
Expand All @@ -95,7 +100,10 @@ impl Scope {
pub fn forbid_file<P: AsRef<Path>>(&self, path: P) {
let path = path.as_ref();

self.denied.lock().unwrap().push(path.to_path_buf());
self.denied
.lock()
.unwrap()
.push(escape(&path.to_string_lossy()));

self.emit(Event::PathForbidden(path.to_path_buf()));
}
Expand Down Expand Up @@ -129,3 +137,27 @@ impl Scope {
id
}
}

// taken from https://github.com/rust-lang/glob/blob/master/src/lib.rs#L717C5-L737C6
/// Escape metacharacters within the given string by surrounding them in
/// brackets. The resulting string will, when compiled into a `Pattern`,
/// match the input string and nothing else.
pub fn escape(s: &str) -> PathBuf {
let mut escaped = String::new();
for c in s.chars() {
match c {
// note that ! does not need escaping because it is only special
// inside brackets
/* disabled to not break paths '?' | */
'*' | '[' | ']' => {
escaped.push('[');
escaped.push(c);
escaped.push(']');
}
c => {
escaped.push(c);
}
}
}
PathBuf::from(escaped)
}
Loading