rusty_dex/dex/
types.rs

1//! DEX types
2//!
3//! Types that are used in the bytecode are stored as strings. The DEX header then contains a list
4//! of offset of these strings. This module decodes these offset to make them available later on.
5
6use std::io::{Seek, SeekFrom};
7
8use crate::dex::reader::DexReader;
9use crate::dex::strings::DexStrings;
10use crate::error::DexError;
11
12/// Internal representation of a DEX type item
13#[derive(Debug)]
14struct DexTypeItem {
15    offset: u32,
16    str_type: String,
17}
18
19/// List of types defined in the DEX file
20#[derive(Debug)]
21pub struct DexTypes{
22    pub items: Vec<String>
23}
24
25impl DexTypes {
26    /// Parse the types from a DEX reader
27    pub fn build(dex_reader: &mut DexReader,
28                 offset: u32,
29                 size: u32,
30                 strings_list: &DexStrings) -> Result<Self, DexError> {
31        dex_reader.bytes.seek(SeekFrom::Start(offset.into()))?;
32
33        let mut types = Vec::new();
34
35        for _ in 0..size {
36            let offset = dex_reader.read_u32()?;
37            let str_type = strings_list.strings.get(offset as usize).ok_or(DexError::InvalidStringIdx)?;
38            types.push(DexTypeItem {
39                offset,
40                str_type: str_type.to_string(),
41            });
42        }
43        types.sort_by(|a, b| a.offset.cmp(&b.offset));
44
45        let mut items = Vec::new();
46        for dex_type in types.into_iter() {
47            items.push(dex_type.str_type);
48        }
49        items.dedup();
50
51        Ok(DexTypes { items })
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn test_build_dex_types_empty() {
61        let dex_data = vec![
62            0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00, 0x00, 0x00,  // DEX magic
63            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // nothing
64            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // nothing
65            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // nothing
66            0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // endianness tag
67        ];
68
69        let mut dex_reader = DexReader::build(dex_data).unwrap();
70        let strings_list = DexStrings { strings: Vec::new() };
71
72        let dex_types = DexTypes::build(&mut dex_reader, 0, 0, &strings_list).unwrap();
73
74        assert_eq!(dex_types.items.len(), 0);
75    }
76
77    #[test]
78    fn test_build_dex_types() {
79        let dex_data = vec![
80            0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00, 0x00, 0x00,  // DEX magic
81            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // nothing
82            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // nothing
83            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // nothing
84            0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // endianness tag
85            0x00, 0x00, 0x00, 0x00,     // type 0 offset
86            0x01, 0x00, 0x00, 0x00,     // type 1 offset
87            0x02, 0x00, 0x00, 0x00,     // type 2 offset
88            0x03, 0x00, 0x00, 0x00,     // type 3 offset
89        ];
90
91        let mut dex_reader = DexReader::build(dex_data).unwrap();
92        let strings_list = DexStrings { strings: vec![
93                "Type0".to_string(),
94                "Type1".to_string(),
95                "Type2".to_string(),
96                "Type3".to_string(),
97            ]
98        };
99
100        let dex_types = DexTypes::build(&mut dex_reader, 50, 4, &strings_list).unwrap();
101
102        assert_eq!(dex_types.items.len(), 4);
103        assert_eq!(dex_types.items[0], "Type0");
104        assert_eq!(dex_types.items[1], "Type1");
105        assert_eq!(dex_types.items[2], "Type2");
106        assert_eq!(dex_types.items[3], "Type3");
107    }
108
109    #[test]
110    fn test_build_dex_types_duplicates() {
111        let dex_data = vec![
112            0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00, 0x00, 0x00,  // DEX magic
113            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // nothing
114            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // nothing
115            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // nothing
116            0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // endianness tag
117            0x00, 0x00, 0x00, 0x00,     // type 0 offset
118            0x01, 0x00, 0x00, 0x00,     // type 1 offset
119            0x02, 0x00, 0x00, 0x00,     // type 1 duplicate offset
120        ];
121
122        let mut dex_reader = DexReader::build(dex_data).unwrap();
123        let strings_list = DexStrings { strings: vec![
124                "Type0".to_string(),
125                "Type1".to_string(),
126                "Type1".to_string(),
127            ]
128        };
129
130        let dex_types = DexTypes::build(&mut dex_reader, 50, 2, &strings_list).unwrap();
131
132        assert_eq!(dex_types.items.len(), 2);
133        assert_eq!(dex_types.items[0], "Type0");
134        assert_eq!(dex_types.items[1], "Type1");
135    }
136}