1#![allow(dead_code)]
2
3use std::io::{Seek, SeekFrom};
10use std::io::BufRead;
11use std::cmp::Ordering;
12
13use crate::dex::reader::DexReader;
14use crate::error::DexError;
15
16#[derive(Debug, PartialEq)]
18pub struct DexStringsItem {
19 utf16_size: u32,
20 offset: u32,
21 is_raw: bool, string: String
24}
25
26#[derive(Debug)]
28pub struct DexStrings {
29 pub strings: Vec<String>
30}
31
32impl DexStrings {
33 fn sort(a: &DexStringsItem, b: &DexStringsItem) -> Ordering {
35 a.offset.cmp(&b.offset)
45 }
46
47 pub fn build(dex_reader: &mut DexReader, offset: u32, size: u32) -> Result<Self, DexError> {
49 dex_reader.bytes.seek(SeekFrom::Start(offset.into()))?;
51
52 let mut strings = Vec::new();
53
54 for _ in 0..size {
55 let string_offset = dex_reader.read_u32()?;
56 let current_offset = dex_reader.bytes.position();
57
58 dex_reader.bytes.seek(SeekFrom::Start(string_offset.into()))?;
59
60 let (utf16_size, _) = dex_reader.read_uleb128()?;
61 if utf16_size > 0 {
62 let mut raw_string = Vec::with_capacity(utf16_size as usize);
63 dex_reader.bytes.read_until(0, &mut raw_string)?;
64 raw_string.pop();
65
66 let decoded = String::from_utf8_lossy(&raw_string).to_string();
70 strings.push(DexStringsItem {
81 utf16_size,
82 offset: string_offset,
83 is_raw: true,
84 string: decoded,
85 });
86 } else {
87 strings.push(DexStringsItem {
88 utf16_size,
89 offset: string_offset,
90 is_raw: false,
91 string: String::new(),
92 });
93 }
94
95 dex_reader.bytes.seek(SeekFrom::Start(current_offset))?;
96
97 }
98
99 strings.sort_by(DexStrings::sort);
100 let mut uniq_strings: Vec<String> = strings.into_iter()
101 .map(|x| x.string)
102 .collect();
103 uniq_strings.dedup();
104
105 Ok(DexStrings { strings: uniq_strings })
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
114 fn test_build_with_empty_strings() {
115 let data = vec![
116 0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
122 let mut dex_reader = DexReader::build(data).unwrap();
123 let dex_strings = DexStrings::build(&mut dex_reader, 44, 0).unwrap();
124
125 assert_eq!(dex_strings.strings.len(), 0);
126 }
127
128 #[test]
129 fn test_build_with_non_empty_strings() {
130 let data = vec![
131 0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00,
138 0x46, 0x00, 0x00, 0x00,
139 0x68, 0x00, 0x00, 0x00,
140
141 0x0C,
143 b'H', b'e', b'l', b'l', b'o', b'!', 0x00, 0x48,
145 b'T', b'h', b'i', b's', b' ', b'i', b's', b' ', b'a', b' ', b't', b'e', b's', b't', b'.', b' ', b'\"', b'A', b'B', b'C', b'D', b'\"', b' ', b'i', b'n', b' ', b'M', b'U', b'T', b'F', b'-', b'8', 0x00, 0x00,
147 ];
148
149 let mut dex_reader = DexReader::build(data).unwrap();
150 let dex_strings = DexStrings::build(&mut dex_reader, 50, 3).unwrap();
151
152 assert_eq!(dex_strings.strings.len(), 3);
153 assert_eq!(dex_strings.strings[0], String::from("Hello!"));
154 assert_eq!(dex_strings.strings[1], String::from("This is a test. \"ABCD\" in MUTF-8"));
155 assert_eq!(dex_strings.strings[2], String::from(""));
156 }
157
158 #[test]
159 fn test_build_with_invalid_string() {
160 let data = vec![
161 0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
168
169 0x02,
171 0xc3, 0x00 ];
173
174 let mut dex_reader = DexReader::build(data).unwrap();
175 let dex_strings = DexStrings::build(&mut dex_reader, 50, 1).unwrap();
176
177 assert_eq!(dex_strings.strings.len(), 1);
178 assert_eq!(dex_strings.strings[0], String::from("\u{FFFD}"));
180 }
181}