Skip to content

Commit 8840b64

Browse files
committed
fix: make parse_ceiling_dirs resilient to illformed UTF-8
Previously it performed a conversion from bytes to OsStr which might have failed, now it stays with `OsStr`all the way.
1 parent 1eddfbd commit 8840b64

File tree

1 file changed

+14
-21
lines changed

1 file changed

+14
-21
lines changed

git-discover/src/upwards/types.rs

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::{borrow::Cow, env, path::PathBuf};
2-
3-
use bstr::{ByteSlice, ByteVec};
1+
use std::ffi::OsStr;
2+
use std::{env, path::PathBuf};
43

54
/// The error returned by [git_discover::upwards()][crate::upwards()].
65
#[derive(Debug, thiserror::Error)]
@@ -81,7 +80,7 @@ impl Options<'_> {
8180
// TODO: test
8281
pub fn apply_environment(mut self) -> Self {
8382
let name = "GIT_CEILING_DIRECTORIES";
84-
if let Some(ceiling_dirs) = env::var_os(name).and_then(|c| Vec::from_os_string(c).ok()) {
83+
if let Some(ceiling_dirs) = env::var_os(name) {
8584
self.ceiling_dirs = parse_ceiling_dirs(&ceiling_dirs);
8685
}
8786
self
@@ -92,35 +91,29 @@ impl Options<'_> {
9291
/// On Windows, paths are separated by `;`.
9392
/// Non-absolute paths are discarded.
9493
/// To match git, all paths are normalized, until an empty path is encountered.
95-
pub(crate) fn parse_ceiling_dirs(ceiling_dirs: &[u8]) -> Vec<PathBuf> {
94+
pub(crate) fn parse_ceiling_dirs(ceiling_dirs: &OsStr) -> Vec<PathBuf> {
9695
let mut should_normalize = true;
97-
let mut result = Vec::new();
98-
let path_separator = if cfg!(windows) { ";" } else { ":" };
99-
for ceiling_dir in ceiling_dirs.split_str(path_separator) {
100-
if ceiling_dir.is_empty() {
96+
let mut out = Vec::new();
97+
for ceiling_dir in std::env::split_paths(ceiling_dirs) {
98+
if ceiling_dir.as_os_str().is_empty() {
10199
should_normalize = false;
102100
continue;
103101
}
104102

105-
// Paths that are invalid unicode can't be handled
106-
let mut dir = match ceiling_dir.to_path() {
107-
Ok(dir) => Cow::Borrowed(dir),
108-
Err(_) => continue,
109-
};
110-
111103
// Only absolute paths are allowed
112-
if dir.is_relative() {
104+
if ceiling_dir.is_relative() {
113105
continue;
114106
}
115107

108+
let mut dir = ceiling_dir;
116109
if should_normalize {
117110
if let Ok(normalized) = git_path::realpath(&dir) {
118-
dir = Cow::Owned(normalized);
111+
dir = normalized;
119112
}
120113
}
121-
result.push(dir.into_owned());
114+
out.push(dir);
122115
}
123-
result
116+
out
124117
}
125118

126119
#[cfg(test)]
@@ -143,7 +136,7 @@ mod tests {
143136
// Parse & build ceiling dirs string
144137
let symlink_str = symlink_path.to_str().expect("symlink path is valid utf8");
145138
let ceiling_dir_string = format!("{}:relative::{}", symlink_str, symlink_str);
146-
let ceiling_dirs = parse_ceiling_dirs(ceiling_dir_string.as_bytes());
139+
let ceiling_dirs = parse_ceiling_dirs(OsStr::new(ceiling_dir_string.as_str()));
147140

148141
assert_eq!(ceiling_dirs.len(), 2, "Relative path is discarded");
149142
assert_eq!(
@@ -176,7 +169,7 @@ mod tests {
176169
// Parse & build ceiling dirs string
177170
let symlink_str = symlink_path.to_str().expect("symlink path is valid utf8");
178171
let ceiling_dir_string = format!("{};relative;;{}", symlink_str, symlink_str);
179-
let ceiling_dirs = parse_ceiling_dirs(ceiling_dir_string.as_bytes());
172+
let ceiling_dirs = parse_ceiling_dirs(OsStr::new(ceiling_dir_string.as_str()));
180173

181174
assert_eq!(ceiling_dirs.len(), 2, "Relative path is discarded");
182175
assert_eq!(ceiling_dirs[0], direct_path, "Symlinks are resolved");

0 commit comments

Comments
 (0)