From 6ae19e30ba70f6df1ab367427d3ebd2969419119 Mon Sep 17 00:00:00 2001 From: Matt Riggott Date: Sat, 27 Dec 2025 19:45:12 +0000 Subject: [PATCH 1/2] Propagate errors in get_svg_input_paths Until now, get_svg_input_paths swallowed entry and recursion errors (despite what the function's docs said), letting unreadable directories or I/O failures silently skip SVGs. The traversal now uses ? on each entry and recursive call to make sure the errors aren't swallowed. There's also a test to check this behaviour works. --- src/fs.rs | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/src/fs.rs b/src/fs.rs index 037db06..9d5106d 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -39,23 +39,18 @@ fn is_useful_input(entry: &DirEntry) -> bool { /// /// This function will return an error if Rust's underlying [`read_dir`] returns an error. pub fn get_svg_input_paths>(path: P, recursive: bool) -> SpreetResult> { - Ok(read_dir(path)? - .filter_map(|entry| { - if let Ok(entry) = entry { - let path_buf = entry.path(); - if recursive && path_buf.is_dir() { - get_svg_input_paths(path_buf, true).ok() - } else if is_useful_input(&entry) { - Some(vec![path_buf]) - } else { - None - } - } else { - None - } - }) - .flatten() - .collect()) + let mut results = Vec::new(); + for entry in read_dir(path)? { + let entry = entry?; + let path_buf = entry.path(); + if recursive && path_buf.is_dir() { + let nested = get_svg_input_paths(path_buf, true)?; + results.extend(nested); + } else if is_useful_input(&entry) { + results.push(path_buf); + } + } + Ok(results) } /// Load an SVG image from a file path. @@ -123,6 +118,8 @@ fn svg_data_to_text(data: &[u8]) -> Result, UsvgError> { mod tests { use super::*; use assert_fs::prelude::*; + #[cfg(unix)] + use std::os::unix::fs::PermissionsExt; fn entry_for(temp: &assert_fs::TempDir, name: &str) -> DirEntry { std::fs::read_dir(temp.path()) @@ -163,4 +160,20 @@ mod tests { let dir_entry = entry_for(&tmp_dir, "icons.svg"); assert!(!is_svg_file(&dir_entry)); } + + #[cfg(unix)] + #[test] + fn get_svg_input_paths_returns_error_on_unreadable_directory() { + let tmp_dir = assert_fs::TempDir::new().unwrap(); + let restricted = tmp_dir.child("no-access"); + restricted.create_dir_all().unwrap(); + std::fs::set_permissions(restricted.path(), std::fs::Permissions::from_mode(0o000)) + .unwrap(); + + let result = get_svg_input_paths(tmp_dir.path(), true); + + std::fs::set_permissions(restricted.path(), std::fs::Permissions::from_mode(0o700)) + .unwrap(); + assert!(result.is_err()); + } } From cdb970c1582cfa21ef4128fd94859c37b06b9837 Mon Sep 17 00:00:00 2001 From: Matt Riggott Date: Sat, 27 Dec 2025 19:48:59 +0000 Subject: [PATCH 2/2] Add CHANGELOG entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2016c54..bd48932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Text in SVG `` elements now rendered in PNG sprites (see [#102]) - Support loading SVG files compressed with gzip (`*.svgz`; see [#107]) +- Propagate errors in `get_svg_input_paths` (see [#108]) - Update Oxipng dependency from v9 to v10 (see [#106]) - Update thiserror dependency from v1 to v2 (see [#106]) @@ -12,6 +13,7 @@ The minimum supported version of Rust is now 1.85.1 (released March 2025). [#102]: https://github.com/flother/spreet/pull/102 [#106]: https://github.com/flother/spreet/pull/106 [#107]: https://github.com/flother/spreet/pull/107 +[#108]: https://github.com/flother/spreet/pull/108 ## v0.13.1 (2025-12-24)