From 2a1aad83b2b3f2f2bf5a0a59ab2b00327d1305c7 Mon Sep 17 00:00:00 2001 From: haonan Date: Wed, 4 Nov 2026 10:56:34 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=8D=87=E7=BA=A7=20zip=20=E5=88=B0=209?= =?UTF-8?q?=20=E5=B9=B6=E9=80=82=E9=85=8D=20ZIP=20=E8=AF=BB=E5=8F=96/?= =?UTF-8?q?=E5=86=99=E5=85=A5=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 82 ++++++++++++------- apps/shield-cli/Cargo.toml | 2 +- apps/shield-cli/src/commands.rs | 14 ++-- apps/shield-gui/src-tauri/Cargo.toml | 2 +- crates/shield-core/Cargo.toml | 2 +- crates/shield-core/src/apk_inspect.rs | 19 +++-- crates/shield-core/src/bundle_inspect.rs | 2 +- crates/shield-core/src/native_vmp.rs | 7 +- crates/shield-core/src/preflight.rs | 6 +- .../shield-core/src/protect/native_alias.rs | 4 +- .../src/protect/resource_format.rs | 19 +++-- crates/shield-core/src/protect/runtime.rs | 2 +- crates/shield-core/src/protection_report.rs | 4 +- crates/shield-core/src/runtime_ui.rs | 2 +- crates/shield-core/src/zipalign.rs | 47 ++++++----- crates/shield-ios/Cargo.toml | 2 +- crates/shield-ios/src/archive_verify.rs | 2 +- crates/shield-ios/src/dependency_cache.rs | 6 +- 18 files changed, 139 insertions(+), 85 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53cf33f..f6d9690 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -87,7 +87,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -98,7 +98,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -496,7 +496,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -815,7 +815,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -997,7 +997,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1061,6 +1061,7 @@ checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", + "zlib-rs", ] [[package]] @@ -2224,7 +2225,7 @@ dependencies = [ "uuid", "which", "windows-sys 0.61.2", - "zip 2.4.2", + "zip 9.3.0", ] [[package]] @@ -2257,7 +2258,7 @@ dependencies = [ "png 0.18.1", "serde", "thiserror 2.0.18", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2290,6 +2291,18 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +dependencies = [ + "bitflags 2.13.0", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "num-conv" version = "0.2.2" @@ -2917,7 +2930,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3225,7 +3238,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3283,7 +3296,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3649,7 +3662,7 @@ dependencies = [ "shield-ios", "tempfile", "toml 0.8.2", - "zip 2.4.2", + "zip 9.3.0", ] [[package]] @@ -3676,7 +3689,7 @@ dependencies = [ "url", "walkdir", "which", - "zip 2.4.2", + "zip 9.3.0", "zstd", ] @@ -3690,7 +3703,7 @@ dependencies = [ "sha2", "tempfile", "toml 0.8.2", - "zip 2.4.2", + "zip 9.3.0", ] [[package]] @@ -3746,7 +3759,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4315,10 +4328,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4665,7 +4678,7 @@ dependencies = [ "png 0.18.1", "serde", "thiserror 2.0.18", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4674,6 +4687,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typed-path" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce898823d8cd0f028662d2f349694b1af0a5cc9be83f1d213a00d3147445e1e" + [[package]] name = "typeid" version = "1.0.3" @@ -5131,7 +5150,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5780,33 +5799,40 @@ dependencies = [ [[package]] name = "zip" -version = "2.4.2" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50" +checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1" dependencies = [ "arbitrary", "crc32fast", - "crossbeam-utils", - "displaydoc", - "flate2", "indexmap 2.14.0", "memchr", - "thiserror 2.0.18", - "zopfli", ] [[package]] name = "zip" -version = "4.6.1" +version = "9.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1" +checksum = "eaeb7f16d2605b49aef586996ded29e65642fab7259a3077e537351df6d80426" dependencies = [ - "arbitrary", "crc32fast", + "flate2", + "getrandom 0.4.3", "indexmap 2.14.0", + "libc", "memchr", + "nix", + "typed-path", + "windows-sys 0.61.2", + "zopfli", ] +[[package]] +name = "zlib-rs" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" + [[package]] name = "zmij" version = "1.0.21" diff --git a/apps/shield-cli/Cargo.toml b/apps/shield-cli/Cargo.toml index 846bd77..69e1f06 100644 --- a/apps/shield-cli/Cargo.toml +++ b/apps/shield-cli/Cargo.toml @@ -16,7 +16,7 @@ clap = { version = "4.5", features = ["derive", "cargo", "env"] } anyhow = "1.0" env_logger = "0.11" log = "0.4" -zip = { version = "2.4", default-features = false, features = ["deflate"] } +zip = { version = "9", default-features = false, features = ["deflate"] } colored = "3.1" shield-core = { path = "../../crates/shield-core" } shield-ios = { path = "../../crates/shield-ios" } diff --git a/apps/shield-cli/src/commands.rs b/apps/shield-cli/src/commands.rs index bfe64f1..9e7283d 100644 --- a/apps/shield-cli/src/commands.rs +++ b/apps/shield-cli/src/commands.rs @@ -1077,7 +1077,8 @@ fn extract_aab_modules( let mut seen = std::collections::BTreeSet::new(); for index in 0..archive.len() { let mut entry = archive.by_index(index)?; - let Some((module, relative)) = entry.name().split_once('/') else { + let name = entry.name()?.into_owned(); + let Some((module, relative)) = name.split_once('/') else { continue; }; if !requested.contains(module) || relative.is_empty() { @@ -1088,13 +1089,13 @@ fn extract_aab_modules( .components() .any(|component| !matches!(component, std::path::Component::Normal(_))) { - anyhow::bail!("AAB 模块条目路径非法:{}", entry.name()); + anyhow::bail!("AAB 模块条目路径非法:{name}"); } if entry .unix_mode() .is_some_and(|mode| mode & 0o170000 == 0o120000) { - anyhow::bail!("AAB 模块不允许符号链接:{}", entry.name()); + anyhow::bail!("AAB 模块不允许符号链接:{name}"); } let destination = root.join(module).join(relative_path); if entry.is_dir() { @@ -1102,7 +1103,7 @@ fn extract_aab_modules( continue; } if !seen.insert((module.to_string(), relative.to_string())) { - anyhow::bail!("AAB 模块包含重复条目:{}", entry.name()); + anyhow::bail!("AAB 模块包含重复条目:{name}"); } if let Some(parent) = destination.parent() { std::fs::create_dir_all(parent)?; @@ -1875,7 +1876,10 @@ mod tests { super::zip_bundle_module(&module, &module_zip).unwrap(); let file = std::fs::File::open(module_zip).unwrap(); let archive = zip::ZipArchive::new(file).unwrap(); - let names: Vec<_> = archive.file_names().map(str::to_string).collect(); + let names: Vec<_> = archive + .file_names() + .map(|name| name.unwrap().into_owned()) + .collect(); assert!(names.contains(&"manifest/AndroidManifest.xml".to_string())); assert!(names.contains(&"dex/classes.dex".to_string())); assert!(names.contains(&"resources.pb".to_string())); diff --git a/apps/shield-gui/src-tauri/Cargo.toml b/apps/shield-gui/src-tauri/Cargo.toml index cbd425e..904e0e7 100644 --- a/apps/shield-gui/src-tauri/Cargo.toml +++ b/apps/shield-gui/src-tauri/Cargo.toml @@ -24,7 +24,7 @@ semver = "1" shield-core = { path = "../../../crates/shield-core" } shield-cli = { path = "../../shield-cli" } shield-ios = { path = "../../../crates/shield-ios" } -zip = { version = "2", default-features = false, features = ["deflate"] } +zip = { version = "9", default-features = false, features = ["deflate"] } which = "8" dunce = "1" url = "2" diff --git a/crates/shield-core/Cargo.toml b/crates/shield-core/Cargo.toml index 4c5c7b9..9dfff73 100644 --- a/crates/shield-core/Cargo.toml +++ b/crates/shield-core/Cargo.toml @@ -12,7 +12,7 @@ anyhow = "1.0" thiserror = "2.0" log = "0.4" walkdir = "2.5" -zip = { version = "2.4", default-features = false, features = ["deflate"] } +zip = { version = "9", default-features = false, features = ["deflate"] } zstd = { workspace = true } which = "8.0" colored = "3.1" diff --git a/crates/shield-core/src/apk_inspect.rs b/crates/shield-core/src/apk_inspect.rs index 0eab590..44cc0ca 100644 --- a/crates/shield-core/src/apk_inspect.rs +++ b/crates/shield-core/src/apk_inspect.rs @@ -29,18 +29,21 @@ pub fn check_apk(path: &Path, apksigner_path: Option<&Path>) -> Result continue, }; - if entry.name() == "classes.dex" && !already_protected { + let name = match entry.name() { + Ok(name) => name.into_owned(), + Err(_) => continue, + }; + if name == "classes.dex" && !already_protected { let entry_size = entry.size(); already_protected = contains_valid_mshd_block(&mut entry, entry_size) .context("读取 classes.dex 失败")?; } // Xop 使用 assets/protector 目录保存壳载荷。即使没有 MSHD trailer, // 也必须拒绝把它再次交给 Shellsmith,避免形成两套 Application/Loader。 - if is_known_protection_marker(entry.name()) { + if is_known_protection_marker(&name) { already_protected = true; } - if let Some(abi) = entry - .name() + if let Some(abi) = name .strip_prefix("lib/") .and_then(|name| name.split_once('/').map(|(abi, _)| abi)) { @@ -274,7 +277,10 @@ fn check_apk_signed(apk_path: &Path, apksigner_path: Option<&Path>) -> Result name.into_owned(), + Err(_) => continue, + }; if name.starts_with("META-INF/") && (name.ends_with(".RSA") || name.ends_with(".DSA") || name.ends_with(".EC")) { @@ -459,7 +465,8 @@ Source Stamp Signer certificate SHA-256 digest: 22222222222222222222222222222222 let dir = tempfile::tempdir().unwrap(); let apk = dir.path().join("empty.apk"); std::fs::write(&apk, []).unwrap(); - let message = classify_apk_zip_error(&apk, &zip::result::ZipError::InvalidArchive("eof")); + let message = + classify_apk_zip_error(&apk, &zip::result::ZipError::InvalidArchive("eof".into())); assert!(message.starts_with("文件为空,不是有效 APK")); } diff --git a/crates/shield-core/src/bundle_inspect.rs b/crates/shield-core/src/bundle_inspect.rs index 2eda5f1..9b1e477 100644 --- a/crates/shield-core/src/bundle_inspect.rs +++ b/crates/shield-core/src/bundle_inspect.rs @@ -42,7 +42,7 @@ pub fn inspect_aab(path: &Path) -> Result { let entry = archive .by_index(index) .with_context(|| format!("读取 AAB 条目 {index} 失败"))?; - let name = entry.name(); + let name = entry.name()?.into_owned(); if name == "BundleConfig.pb" { has_bundle_config = true; } diff --git a/crates/shield-core/src/native_vmp.rs b/crates/shield-core/src/native_vmp.rs index bba5df5..86d2f21 100644 --- a/crates/shield-core/src/native_vmp.rs +++ b/crates/shield-core/src/native_vmp.rs @@ -134,7 +134,12 @@ fn validate_entry(entry: &str) -> Result<(&str, &str, &str)> { fn zip_library(archive: &mut zip::ZipArchive, name: &str) -> Result> { ensure!( - archive.file_names().filter(|n| *n == name).count() == 1, + archive + .file_names() + .filter_map(|n| n.ok()) + .filter(|n| n.as_ref() == name) + .count() + == 1, "Native 归档条目缺失或重复:{name}" ); let entry = archive.by_name(name)?; diff --git a/crates/shield-core/src/preflight.rs b/crates/shield-core/src/preflight.rs index 80c1199..c11a23c 100644 --- a/crates/shield-core/src/preflight.rs +++ b/crates/shield-core/src/preflight.rs @@ -124,15 +124,15 @@ fn inspect_archive(path: &Path) -> Result { for index in 0..zip.len() { let entry = zip.by_index(index).context("读取 APK ZIP 条目失败")?; - let name = entry.name(); + let name = entry.name()?.to_string(); if name == "AndroidManifest.xml" { facts.has_manifest = true; } - if is_dex_entry(name) { + if is_dex_entry(&name) { facts.dex_count += 1; facts.dex_total_size = facts.dex_total_size.saturating_add(entry.size()); } - if is_native_library(name) { + if is_native_library(&name) { facts.native_library_count += 1; if entry.compression() != zip::CompressionMethod::Stored { facts.compressed_native_library_count += 1; diff --git a/crates/shield-core/src/protect/native_alias.rs b/crates/shield-core/src/protect/native_alias.rs index 8d79ffd..cf8ae12 100644 --- a/crates/shield-core/src/protect/native_alias.rs +++ b/crates/shield-core/src/protect/native_alias.rs @@ -137,7 +137,7 @@ pub(crate) fn inspect_original_apk(apk_path: &Path) -> Result let mut found_abis = HashSet::new(); for index in 0..archive.len() { let mut entry = archive.by_index(index)?; - let name = entry.name().to_string(); + let name = entry.name()?.to_string(); let base_name = name.rsplit('/').next().unwrap_or(""); if base_name.eq_ignore_ascii_case(&runtime.canonical_file_name) { anyhow::bail!("加固 APK 仍包含 Native 规范库名称: {name}"); diff --git a/crates/shield-core/src/protect/resource_format.rs b/crates/shield-core/src/protect/resource_format.rs index 6e8bc7f..6fd3a85 100644 --- a/crates/shield-core/src/protect/resource_format.rs +++ b/crates/shield-core/src/protect/resource_format.rs @@ -96,16 +96,17 @@ pub(crate) fn restore_original_resources(original_apk: &Path, rebuilt_apk: &Path let mut temp = NamedTempFile::new_in(parent).context("创建资源恢复临时 APK 失败")?; { let mut writer = ZipWriter::new(BufWriter::new(temp.as_file_mut())); - writer.set_raw_comment(rebuilt.comment().to_vec().into_boxed_slice()); - if let Some(comment) = rebuilt.zip64_comment() { - writer.set_raw_zip64_comment(Some(comment.to_vec().into_boxed_slice())); - } + // zip 9 移除了 raw ZIP64 注释 API;标准归档注释仍按原字节保留。 + writer + .set_raw_comment(rebuilt.comment().to_vec().into_boxed_slice()) + .context("写入重编 APK 注释失败")?; for index in 0..rebuilt.len() { let entry = rebuilt .by_index(index) .with_context(|| format!("读取重编 APK 条目失败:index={index}"))?; - if !is_resource_entry(entry.name()) { + let name = entry.name()?.into_owned(); + if !is_resource_entry(&name) { writer .raw_copy_file(entry) .context("复制受保护 APK 条目失败")?; @@ -115,7 +116,8 @@ pub(crate) fn restore_original_resources(original_apk: &Path, rebuilt_apk: &Path let entry = original .by_index(index) .with_context(|| format!("读取原 APK 资源条目失败:index={index}"))?; - if is_resource_entry(entry.name()) { + let name = entry.name()?.into_owned(); + if is_resource_entry(&name) { writer .raw_copy_file(entry) .context("恢复原 APK 混淆资源条目失败")?; @@ -168,8 +170,9 @@ fn resource_index( let entry = archive .by_index(position) .with_context(|| format!("读取 APK 资源索引失败:index={position}"))?; - if is_resource_entry(entry.name()) { - index.push((entry.name().to_string(), entry.size(), entry.crc32())); + let name = entry.name()?.into_owned(); + if is_resource_entry(&name) { + index.push((name, entry.size(), entry.crc32())); } } index.sort(); diff --git a/crates/shield-core/src/protect/runtime.rs b/crates/shield-core/src/protect/runtime.rs index 10db763..a0f69de 100644 --- a/crates/shield-core/src/protect/runtime.rs +++ b/crates/shield-core/src/protect/runtime.rs @@ -43,7 +43,7 @@ pub(crate) fn inject_runtime( for i in 0..archive.len() { let mut file = archive.by_index(i)?; - let file_name = file.name().to_string(); + let file_name = file.name()?.to_string(); if file_name == "metadata.json" || file_name.contains("libzstd-jni") { continue; diff --git a/crates/shield-core/src/protection_report.rs b/crates/shield-core/src/protection_report.rs index e304651..77ece8a 100644 --- a/crates/shield-core/src/protection_report.rs +++ b/crates/shield-core/src/protection_report.rs @@ -635,10 +635,10 @@ fn archive_dexes(path: &Path) -> Result> { let mut values = BTreeMap::new(); for i in 0..archive.len() { let mut entry = archive.by_index(i)?; - if !entry.name().ends_with(".dex") { + let name = entry.name()?.to_string(); + if !name.ends_with(".dex") { continue; } - let name = entry.name().to_owned(); let mut hasher = Sha256::new(); std::io::copy(&mut entry, &mut hasher)?; ensure!( diff --git a/crates/shield-core/src/runtime_ui.rs b/crates/shield-core/src/runtime_ui.rs index 594e281..843f05b 100644 --- a/crates/shield-core/src/runtime_ui.rs +++ b/crates/shield-core/src/runtime_ui.rs @@ -136,7 +136,7 @@ pub(crate) fn apk_index(path: &Path) -> Result { for i in 0..archive.len() { let entry = archive.by_index(i)?; if index - .insert(entry.name().to_string(), (entry.size(), entry.crc32())) + .insert(entry.name()?.to_string(), (entry.size(), entry.crc32())) .is_some() { bail!("APK 包含重复条目"); diff --git a/crates/shield-core/src/zipalign.rs b/crates/shield-core/src/zipalign.rs index 312473f..6811dd3 100644 --- a/crates/shield-core/src/zipalign.rs +++ b/crates/shield-core/src/zipalign.rs @@ -44,13 +44,14 @@ fn is_directory_name(name: &str) -> bool { name.ends_with('/') } -fn build_file_options( - file: &zip::read::ZipFile<'_>, +fn build_file_options( + file: &zip::read::ZipFile<'_, R>, alignment: u16, native_packaging: NativeLibraryPackaging, -) -> SimpleFileOptions { +) -> Result { + let name = file.name()?.into_owned(); let compression = - if native_packaging == NativeLibraryPackaging::Store && is_native_library(file.name()) { + if native_packaging == NativeLibraryPackaging::Store && is_native_library(&name) { CompressionMethod::Stored } else { file.compression() @@ -72,7 +73,7 @@ fn build_file_options( options = options.unix_permissions(mode); } - options + Ok(options) } pub fn verify_apk_alignment(path: &Path) -> Result> { @@ -86,15 +87,17 @@ pub fn verify_apk_alignment(path: &Path) -> Result> { let file = archive .by_index(i) .with_context(|| format!("读取 ZIP 条目失败: index={i}"))?; - if file.is_dir() || is_directory_name(file.name()) { + let name = file.name()?.into_owned(); + if file.is_dir() || is_directory_name(&name) { continue; } - let required = required_alignment(file.name()) as u64; - let actual = file.data_start() % required; + let required = required_alignment(&name) as u64; + let data_start = file.data_start().context("ZIP 条目缺少数据偏移")?; + let actual = data_start % required; if actual != 0 { issues.push(AlignmentIssue { - name: file.name().to_string(), + name, required, actual, }); @@ -171,8 +174,9 @@ pub(crate) fn find_compressed_native_libraries(path: &Path) -> Result Result<()> { let mut has_executable_container = false; for index in 0..archive.len() { let entry = archive.by_index(index)?; - let name = entry.name(); + let name = entry.name()?.into_owned(); if name.starts_with("Payload/") && name.ends_with(".app/Info.plist") { has_info = true; } diff --git a/crates/shield-ios/src/dependency_cache.rs b/crates/shield-ios/src/dependency_cache.rs index 28960f4..3ae26d0 100644 --- a/crates/shield-ios/src/dependency_cache.rs +++ b/crates/shield-ios/src/dependency_cache.rs @@ -205,15 +205,15 @@ fn read_sdk( for index in 0..zip.len() { check_cancel(cancel)?; let entry = zip.by_index(index)?; - let name = entry.name(); + let name = entry.name()?.into_owned(); anyhow::ensure!( !name.contains('\\') - && Path::new(name) + && Path::new(&name) .components() .all(|part| matches!(part, Component::Normal(_))), "freeRASP ZIP 包含不安全路径" ); - anyhow::ensure!(names.insert(name.to_string()), "freeRASP ZIP 包含重复条目"); + anyhow::ensure!(names.insert(name.clone()), "freeRASP ZIP 包含重复条目"); let kind = entry.unix_mode().unwrap_or(0) & 0o170000; anyhow::ensure!( matches!(kind, 0 | 0o100000 | 0o040000),