From cb8d7732ef039d1a42b4698d35cb965cdaad3c7d Mon Sep 17 00:00:00 2001 From: andriyDev Date: Mon, 17 Nov 2025 18:33:34 -0800 Subject: [PATCH 1/3] Add a test to show that resolve paths with .. should work reasonably. --- crates/bevy_asset/src/path.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/bevy_asset/src/path.rs b/crates/bevy_asset/src/path.rs index de9dfa5ca583a..9086bd6494d15 100644 --- a/crates/bevy_asset/src/path.rs +++ b/crates/bevy_asset/src/path.rs @@ -996,6 +996,24 @@ mod tests { ); } + #[test] + fn resolve_embed_relative_to_external_path() { + let base = AssetPath::from("../../a/b.gltf"); + assert_eq!( + base.resolve_embed("c.bin").unwrap(), + AssetPath::from("../../a/c.bin") + ); + } + + #[test] + fn resolve_relative_to_external_path() { + let base = AssetPath::from("../../a/b.gltf"); + assert_eq!( + base.resolve("c.bin").unwrap(), + AssetPath::from("../../a/b.gltf/c.bin") + ); + } + #[test] fn test_get_extension() { let result = AssetPath::from("http://a.tar.gz#Foo"); From 862d880d3d675b1603170229ca1cacf342d9aefe Mon Sep 17 00:00:00 2001 From: andriyDev Date: Mon, 17 Nov 2025 18:47:21 -0800 Subject: [PATCH 2/3] Prevent AssetPath normalization from collapsing .. with another .. --- crates/bevy_asset/src/path.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/bevy_asset/src/path.rs b/crates/bevy_asset/src/path.rs index 9086bd6494d15..6ff18af60bed7 100644 --- a/crates/bevy_asset/src/path.rs +++ b/crates/bevy_asset/src/path.rs @@ -648,7 +648,12 @@ pub(crate) fn normalize_path(path: &Path) -> PathBuf { if elt == "." { // Skip } else if elt == ".." { - if !result_path.pop() { + if let Some(file_name) = result_path.file_name() + // Don't collapse .. with another .. + && file_name != ".." + { + assert!(result_path.pop()); + } else { // Preserve ".." if insufficient matches (per RFC 1808). result_path.push(elt); } From 9d830d99bb0af64a97709561ccd03d2f7d7bf546 Mon Sep 17 00:00:00 2001 From: andriyDev Date: Mon, 17 Nov 2025 19:43:13 -0800 Subject: [PATCH 3/3] Remove extra checks and add comments. --- crates/bevy_asset/src/path.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/bevy_asset/src/path.rs b/crates/bevy_asset/src/path.rs index 6ff18af60bed7..4d8d647940000 100644 --- a/crates/bevy_asset/src/path.rs +++ b/crates/bevy_asset/src/path.rs @@ -648,10 +648,11 @@ pub(crate) fn normalize_path(path: &Path) -> PathBuf { if elt == "." { // Skip } else if elt == ".." { - if let Some(file_name) = result_path.file_name() - // Don't collapse .. with another .. - && file_name != ".." - { + // Note: If the result_path ends in `..`, Path::file_name returns None, so we'll end up + // preserving it. + if result_path.file_name().is_some() { + // This assert is just a sanity check - we already know the path has a file_name, so + // we know there is something to pop. assert!(result_path.pop()); } else { // Preserve ".." if insufficient matches (per RFC 1808).