From 11d3b51d06fc2fbd89dcb66b10af58c586c8479b Mon Sep 17 00:00:00 2001 From: Itay Brenner Date: Mon, 14 Jul 2025 18:00:35 -0300 Subject: [PATCH] fix: ignore non dsym files --- Cargo.lock | 36 +++++++++++++++++++++++++++++++-- Cargo.toml | 1 + src/utils/dif.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd3d273085..9608f1d2e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1157,6 +1157,17 @@ dependencies = [ "scroll 0.12.0", ] +[[package]] +name = "goblin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e961b33649994dcf69303af6b3a332c1228549e604d455d61ec5d2ab5e68d3a" +dependencies = [ + "log", + "plain", + "scroll 0.13.0", +] + [[package]] name = "h2" version = "0.4.6" @@ -2615,7 +2626,16 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6" dependencies = [ - "scroll_derive", + "scroll_derive 0.12.0", +] + +[[package]] +name = "scroll" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1257cd4248b4132760d6524d6dda4e053bc648c9070b960929bf50cfb1e7add" +dependencies = [ + "scroll_derive 0.13.0", ] [[package]] @@ -2629,6 +2649,17 @@ dependencies = [ "syn", ] +[[package]] +name = "scroll_derive" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22fc4f90c27b57691bbaf11d8ecc7cfbfe98a4da6dbe60226115d322aa80c06e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -2714,6 +2745,7 @@ dependencies = [ "flate2", "git2", "glob", + "goblin 0.10.0", "if_chain", "ignore", "indicatif", @@ -3056,7 +3088,7 @@ dependencies = [ "fallible-iterator 0.3.0", "flate2", "gimli 0.31.0", - "goblin", + "goblin 0.8.2", "lazy_static", "nom", "nom-supreme", diff --git a/Cargo.toml b/Cargo.toml index 9676e1cf74..c5c7aa4808 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ flate2 = { version = "1.0.25", default-features = false, features = [ ] } git2 = { version = "0.18.1", default-features = false } glob = "0.3.1" +goblin = "0.10.0" if_chain = "1.0.2" ignore = "0.4.20" # Do not update due to https://github.com/console-rs/indicatif/issues/317 and https://github.com/getsentry/sentry-cli/pull/1055 diff --git a/src/utils/dif.rs b/src/utils/dif.rs index c5eacb526c..4c5b9d347d 100644 --- a/src/utils/dif.rs +++ b/src/utils/dif.rs @@ -3,6 +3,7 @@ use std::path::Path; use std::str; use anyhow::{bail, Context, Error, Result}; +use goblin; use proguard::ProguardMapping; use serde::ser::{SerializeStruct, Serializer}; use serde::Serialize; @@ -203,8 +204,59 @@ impl DifFile<'static> { } } + fn validate_macho_magic_is_dsym(data: &[u8]) -> Result<()> { + // Parse the file as a MachO file and validate the file type + match goblin::Object::parse(data) { + Ok(goblin::Object::Mach(mach)) => { + match mach { + goblin::mach::Mach::Fat(fat) => { + for (i, arch_result) in fat.iter_arches().enumerate() { + match arch_result { + Ok(arch) => { + let offset = arch.offset as usize; + let bytes = &data[offset..][..arch.size as usize]; + match goblin::mach::MachO::parse(bytes, 0) { + Ok(macho) => { + // As defined in https://github.com/apple-oss-distributions/xnu/blob/e3723e1f17661b24996789d8afc084c0c3303b26/EXTERNAL_HEADERS/mach-o/loader.h#L120, look for MH_DSYM file type + const MH_DSYM: u32 = 0xa; + if macho.header.filetype != MH_DSYM { + bail!("Invalid architecture in fat MachO file, not a dSYM"); + } + } + Err(e) => { + bail!("Invalid architecture in fat MachO file, not a dSYM"); + } + } + } + Err(e) => { + bail!("Invalid architecture in fat MachO file, not a dSYM"); + } + } + } + Ok(()) + } + goblin::mach::Mach::Binary(bin) => { + Ok(()) + } + } + } + Ok(_) => { + bail!("File is not a valid MachO format"); + } + Err(e) => { + bail!("Invalid MachO file: {}", e); + } + } + } + fn open_object>(path: P, format: FileFormat) -> Result { let data = ByteView::open(&path)?; + + // Only run this check for dSYM files + if format == FileFormat::MachO { + Self::validate_macho_magic_is_dsym(data.as_slice())?; + } + let archive = SelfCell::try_new(data, |d| Archive::parse(unsafe { &*d }))?; if archive.get().file_format() != format {