From 4ae8aacbf6dd87ad70ae8128a866061a75c30f51 Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Tue, 8 Dec 2020 23:05:37 +0100 Subject: refactor version_chunk parser. Make it explicit what container and object tags we're expecting. Even though we're not using that information, the parser will expect all elements to be in place, and fail if they are not. --- src/main.rs | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/main.rs b/src/main.rs index 964635a..a694739 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,8 +20,9 @@ mod cubase_project; use cubase_project::*; use nom::{ + branch::alt, bytes::complete::*, - combinator::{map, rest}, + combinator::{map, rest, value}, error::ParseError, multi::{length_data, length_value, many1}, number::complete::*, @@ -47,6 +48,18 @@ fn cmstring(input: &[u8]) -> IResult<&[u8], &str> { map(strdata, |s| std::str::from_utf8(s).unwrap())(input) } +fn cmtag<'a>(t: &'a str) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], (NodeType, u16)> { + map( + tuple(( + node_type, + length_value( + be_u32, tuple((tag(t), tag(b"\0"))) + ), + be_u16) + ), + |(nt, (_, _), v)| (nt, v)) +} + /** * The data chunks in the file is split into what seems like a structure of containers and leaf * nodes. Where the containers don't contain any data of themselves, but leaf nodes may contain @@ -55,13 +68,21 @@ fn cmstring(input: &[u8]) -> IResult<&[u8], &str> { * Each node regardless of type has a name, and a 16 bit number which meaning I'm not sure about. * Leaf nodes also has a data payload prefixed by a 32 bit length (be). */ -#[derive(Debug)] +#[derive(Clone, Debug)] enum NodeType { Container, Object, } +fn node_type<'a>(input: &'a [u8]) -> IResult<&'a [u8], NodeType> { + alt(( + value(NodeType::Container, tag(b"\xff\xff\xff\xfe")), + value(NodeType::Object, tag(b"\xff\xff\xff\xff")) + ))(input) +} + + #[derive(Debug)] struct Node<'a> { node_type: NodeType, @@ -202,17 +223,9 @@ fn cpr_file_header<'a>(input: &'a [u8]) -> IResult<&'a [u8], u32> { fn version_chunk<'a>(input: &'a [u8]) -> IResult<&'a [u8], PAppVersion> { - let (odata, c) = container_node(input)?; - println!("[*] {:?}", c); - - let (r2, o) = object_node(odata)?; - println!("[*] {:?}", o); - assert_eq!(r2.len(), 0); - - let (r2, v) = p_app_version(o.payload.unwrap())?; - assert_eq!(r2.len(), 0); - - Ok((r2, v)) + preceded( + tuple((cmtag("CmObject"), cmtag("PAppVersion"))), + length_value(be_u32, p_app_version))(input) } -- cgit v1.2.3