From 7497c0b0b9a757228d85cc61fe96c77b352ea508 Mon Sep 17 00:00:00 2001 From: Marcus Kyrillos <11916253-MarcusKyrillos@users.noreply.gitlab.com> Date: Fri, 22 Sep 2023 11:46:04 +0000 Subject: [PATCH 1/3] update indexmap version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 76f499c..df1b3ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,5 +13,5 @@ exclude = ["examples/**", "axmldecoder-printer/**"] [dependencies] byteorder = "1.4.3" deku = "~0.16" -indexmap = "1.9.2" +indexmap = "2.0" thiserror = "1.0.37" From 18b11e6c8f9c5b84540202d1b7ce2125f4000962 Mon Sep 17 00:00:00 2001 From: Marcus Kyrillos <11916253-MarcusKyrillos@users.noreply.gitlab.com> Date: Sat, 23 Sep 2023 09:28:02 +0000 Subject: [PATCH 2/3] skip nodes if malformed xml --- Cargo.toml | 5 ++++- examples/AndroidManifest_malformed.xml | Bin 0 -> 17004 bytes src/binaryxml.rs | 13 +++++++++++++ src/xml.rs | 19 +++++++++++++++---- 4 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 examples/AndroidManifest_malformed.xml diff --git a/Cargo.toml b/Cargo.toml index df1b3ef..1030817 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,9 @@ exclude = ["examples/**", "axmldecoder-printer/**"] [dependencies] byteorder = "1.4.3" -deku = "~0.16" +# TODO: move to crates.io when the feature is available +# default attribute for enums not yet available at version realeased on crates.io +# https://github.com/sharksforarms/deku/pull/335 +deku = { git = "https://github.com/sharksforarms/deku" } indexmap = "2.0" thiserror = "1.0.37" diff --git a/examples/AndroidManifest_malformed.xml b/examples/AndroidManifest_malformed.xml new file mode 100644 index 0000000000000000000000000000000000000000..982ae06aefff0314c66a0038f6c8489094290077 GIT binary patch literal 17004 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∾C^-3vX<(S5D4sL@ZR@Al+ zofNSKxfW9?1?D!ctGmir4*RCZ`9D|iok4F z!xPwusg%BK4f9yht{q@T4(-}CgpD~UC4FtvQ*ijU+Y5G9Y})MwC$SMYXIcGP*@4)Jnl9UYn---pFlO3}vLH!wYyN8EPv=v{2YR7!!F`-a|gd0(H-J+iR zEBaUi^EG?~8*@-fQP20dRO@Q#`*-^fr>u%zSZa?F^LiR_q{<+h5k-19xm_qD<$nc z^Gv|zrj*oghNBKj^-+gB2XmX@{=l-2_Gh`a4*f_;%$wzKj{D}Il(cvKIS;E>N>Ov$ zZXD?_*R5(kiC$l&B(rC1QKbX>7z)N`aaC2ByydoiHz8Bc@Uc%-lEhuVE9I z)j2y@(Vyiya(KO>k9DGW1a?W#$IviW}(Jyk&>oALrIVdH4wF_lta=DvaH{@w}mGB#o=rNGR61Jg5i zC(IA95mPAzX6_r9Z)4L5^9nX%Dy6{8eFM{R(h2h_HexEJz|4IE^LyBI!u${$F_lta z=DvaX4mO=IuVEvmQVPu6H}v1fCNQh>>)ndpHk!jfAV(_tSnFIXq=#T)7kJ37&NDY# zxBs}r>sLzRZ-&hm{D$|LTUzL&jd{*d&-a#n#EZ66=e6zn2)3R|DKOvTT0be)pO?{% zR`lQGy4AY+C+NjgN`aaCMxLH`%SbnFw8Q)XHexEJz|4KcoZYNXrIc*@{jh%M`=~_G{D_rfhTbz`#Io-~?>R5@FIM!P)k6Om Q*Zz{jYK8tmuFd8D0a$nf`Tzg` literal 0 HcmV?d00001 diff --git a/src/binaryxml.rs b/src/binaryxml.rs index 049c7b8..62c682a 100644 --- a/src/binaryxml.rs +++ b/src/binaryxml.rs @@ -19,9 +19,12 @@ pub(crate) struct BinaryXmlDocument { #[deku(type = "u16")] pub(crate) enum ResourceType { NullType = 0x000, + StringPool = 0x0001, Table = 0x0002, Xml = 0x0003, + + // Chunk types in XmlNodeType XmlStartNameSpace = 0x0100, XmlEndNameSpace = 0x101, XmlStartElement = 0x0102, @@ -29,10 +32,14 @@ pub(crate) enum ResourceType { XmlCdata = 0x0104, XmlLastChunk = 0x017f, XmlResourceMap = 0x0180, + TablePackage = 0x0200, TableType = 0x0201, TableTypeSpec = 0x0202, TableLibrary = 0x0203, + + #[deku(id = "0xffff", default)] + Unknown = 0xffff, } #[derive(Clone, Debug, DekuRead, DekuWrite)] @@ -70,6 +77,9 @@ pub(crate) enum XmlNodeType { XmlEndElement(XmlEndElement), #[deku(id = "ResourceType::XmlCdata")] XmlCdata(XmlCdata), + + #[deku(id = "ResourceType::NullType", default)] + Unknown, } #[derive(Debug, DekuRead, DekuWrite)] @@ -145,6 +155,9 @@ pub(crate) enum ResourceValueType { ColorRgb8 = 0x1d, ColorArgb4 = 0x1e, ColorRgb4 = 0x1f, + + #[deku(id = "0xff", default)] + Unknown = 0xffff, } #[derive(Debug, DekuRead, DekuWrite)] diff --git a/src/xml.rs b/src/xml.rs index 35eedb6..1f43e99 100644 --- a/src/xml.rs +++ b/src/xml.rs @@ -67,6 +67,10 @@ impl XmlDocument { .unwrap() .insert_children(Node::Cdata(cdata)); } + _ => { + println!("Unknown node type: {:?}", node.element); + continue; + } }; } @@ -124,10 +128,17 @@ impl XmlDocument { } for attr in &e.attributes { - let ns = string_pool.get(usize::try_from(attr.ns).unwrap()); - let name = string_pool - .get(usize::try_from(attr.name).unwrap()) - .ok_or(ParseError::StringNotFound(attr.name))?; + let ns = match usize::try_from(attr.ns) { + Ok(val) => string_pool.get(val), + Err(_) => continue, + }; + let name = match usize::try_from(attr.name) { + Ok(val) => match string_pool.get(val) { + Some(n) => n, + None => continue, + }, + Err(_) => continue, + }; let value = attr.typed_value.get_value(string_pool); let mut final_name = String::new(); From e964ad70b6c50597bc0b6d377324e25835bafbc1 Mon Sep 17 00:00:00 2001 From: Marcus Kyrillos <11916253-MarcusKyrillos@users.noreply.gitlab.com> Date: Sat, 23 Sep 2023 09:35:58 +0000 Subject: [PATCH 3/3] refactor test --- axmldecoder-printer/src/main.rs | 14 +++++++------- src/lib.rs | 20 ++++++++++++++------ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/axmldecoder-printer/src/main.rs b/axmldecoder-printer/src/main.rs index 99ee1ce..41ab70f 100644 --- a/axmldecoder-printer/src/main.rs +++ b/axmldecoder-printer/src/main.rs @@ -13,7 +13,7 @@ fn main() -> Result<()> { let root = xml.get_root().as_ref().unwrap(); let mut s = String::new(); s.push_str("\n"); - format_xml(&root, 0_usize, &mut s); + format_xml(root, 0_usize, &mut s); let s = s.trim().to_string(); println!("{}", s); @@ -27,7 +27,7 @@ fn main() -> Result<()> { let root = xml.get_root().as_ref().unwrap(); let mut s = String::new(); s.push_str("\n"); - format_xml(&root, 0_usize, &mut s); + format_xml(root, 0_usize, &mut s); let s = s.trim().to_string(); println!("{}", s); @@ -42,19 +42,19 @@ fn format_xml(e: &Node, level: usize, output: &mut String) { output.push_str(&format!( "{:indent$}{}\n", "", - &format_start_element(&e), + &format_start_element(e), indent = level * 2 )); for child in e.get_children() { - format_xml(&child, level + 1, output) + format_xml(child, level + 1, output) } if !e.get_children().is_empty() { output.push_str(&format!( "{:indent$}{}\n", "", - &format_end_element(&e), + &format_end_element(e), indent = level * 2 )); } @@ -63,7 +63,7 @@ fn format_xml(e: &Node, level: usize, output: &mut String) { output.push_str(&format!( "{:indent$}{}\n", "", - &format_cdata(&e, level), + &format_cdata(e, level), indent = level * 2 )); } @@ -74,7 +74,7 @@ fn format_cdata(e: &Cdata, level: usize) -> String { let indent = format!("{:indent$}", "", indent = level * 2); let mut s = String::new(); s.push_str(""); s } diff --git a/src/lib.rs b/src/lib.rs index 4687016..87f32af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,16 +70,24 @@ mod tests { use std::path::PathBuf; #[test] - fn test_parse() { + fn test_parse() -> std::io::Result<()> { let mut examples = PathBuf::from(env!("CARGO_MANIFEST_DIR")); examples.push("examples"); - for entry in std::fs::read_dir(examples).unwrap() { - let entry = entry.unwrap(); - let mut f = File::open(entry.path()).unwrap(); + for entry in std::fs::read_dir(&examples)? { + let entry = entry?; + println!("Processing file: {}", entry.path().display()); + let mut f = File::open(entry.path())?; let mut buf = Vec::new(); - f.read_to_end(&mut buf).unwrap(); - parse(&buf).unwrap_or_else(|_| panic!("{} failed to parse", entry.path().display())); + f.read_to_end(&mut buf)?; + let result = parse(&buf); + assert!( + result.is_ok(), + "Failed to parse file: {}", + entry.path().display() + ); } + + Ok(()) } }