From 211402ae9ddf7b9bfeeb2fb30b1b3320de384664 Mon Sep 17 00:00:00 2001 From: Jean-Marie Mineau Date: Fri, 1 Dec 2023 12:38:54 +0100 Subject: [PATCH] add type to generated dex file --- androscalpel/src/annotation.rs | 19 ++++- androscalpel/src/class.rs | 41 ++++++++++- androscalpel/src/code.rs | 13 +++- androscalpel/src/dex_id.rs | 69 +++++++++++++----- androscalpel/src/dex_writer.rs | 92 ++++++++++++++---------- androscalpel/src/field.rs | 17 ++++- androscalpel/src/method.rs | 23 +++++- androscalpel/src/method_handle.rs | 80 ++++++++++++++++++--- androscalpel/src/scalar.rs | 58 +++------------ androscalpel/src/value.rs | 44 +++++++++--- androscalpel_serializer/src/items/mod.rs | 4 +- 11 files changed, 328 insertions(+), 132 deletions(-) diff --git a/androscalpel/src/annotation.rs b/androscalpel/src/annotation.rs index 4e2bf82..15f3e59 100644 --- a/androscalpel/src/annotation.rs +++ b/androscalpel/src/annotation.rs @@ -62,10 +62,15 @@ impl DexAnnotationItem { format!("AnnotationItem(visibility: {visibility}, {annotation})") } - /// Return all strings references in the annotation. + /// Return all strings referenced in the annotation. pub fn get_all_strings(&self) -> HashSet { self.annotation.get_all_strings() } + + /// Return all types referenced in the annotation. + pub fn get_all_types(&self) -> HashSet { + self.annotation.get_all_types() + } } /// An annotation. @@ -103,7 +108,7 @@ impl DexAnnotation { format!("Annotation({type_}, {elts})") } - /// Return all strings references in the annotation. + /// Return all strings referenced in the annotation. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); strings.extend(self.type_.get_all_strings()); @@ -113,4 +118,14 @@ impl DexAnnotation { } strings } + + /// Return all types referenced in the annotation. + pub fn get_all_types(&self) -> HashSet { + let mut types = HashSet::new(); + types.insert(self.type_.clone()); + for value in self.elements.values() { + types.extend(value.get_all_types()); + } + types + } } diff --git a/androscalpel/src/class.rs b/androscalpel/src/class.rs index 6469aff..8f870c2 100644 --- a/androscalpel/src/class.rs +++ b/androscalpel/src/class.rs @@ -126,7 +126,7 @@ impl Class { format!("Class({name})") } - /// Return all strings references in the class. + /// Return all strings referenced in the class. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); strings.extend(self.descriptor.get_all_strings()); @@ -151,8 +151,43 @@ impl Class { strings.extend(id.get_all_strings()); strings.extend(method.get_all_strings()); } - //pub virtual_methods: HashMap, - //pub annotations: Vec, + for (id, method) in &self.virtual_methods { + strings.extend(id.get_all_strings()); + strings.extend(method.get_all_strings()); + } + for annot in &self.annotations { + strings.extend(annot.get_all_strings()); + } strings } + + /// Return all types referenced in the class. + pub fn get_all_types(&self) -> HashSet { + let mut types = HashSet::new(); + types.insert(self.descriptor.clone()); + if let Some(superclass) = &self.superclass { + types.insert(superclass.clone()); + } + types.extend(self.interfaces.clone()); + for (id, field) in &self.static_fields { + types.extend(id.get_all_types()); + types.extend(field.get_all_types()); + } + for (id, field) in &self.instance_fields { + types.extend(id.get_all_types()); + types.extend(field.get_all_types()); + } + for (id, method) in &self.direct_methods { + types.extend(id.get_all_types()); + types.extend(method.get_all_types()); + } + for (id, method) in &self.virtual_methods { + types.extend(id.get_all_types()); + types.extend(method.get_all_types()); + } + for annot in &self.annotations { + types.extend(annot.get_all_types()); + } + types + } } diff --git a/androscalpel/src/code.rs b/androscalpel/src/code.rs index 8aea4fb..1582e6e 100644 --- a/androscalpel/src/code.rs +++ b/androscalpel/src/code.rs @@ -63,7 +63,7 @@ impl Code { "Code()".into() } - /// Return all strings references in the codes. + /// Return all strings referenced in the codes. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); for (list, _) in &self.handlers { @@ -73,4 +73,15 @@ impl Code { } strings } + + /// Return all types referenced in the codes. + pub fn get_all_types(&self) -> HashSet { + let mut types = HashSet::new(); + for (list, _) in &self.handlers { + for (ty, _) in list { + types.insert(ty.clone()); + } + } + types + } } diff --git a/androscalpel/src/dex_id.rs b/androscalpel/src/dex_id.rs index dd7bf8e..bd3b076 100644 --- a/androscalpel/src/dex_id.rs +++ b/androscalpel/src/dex_id.rs @@ -1,5 +1,6 @@ //! The class identifying dex structure. +use std::cmp::{Ord, PartialOrd}; use std::collections::hash_map::DefaultHasher; use std::collections::HashSet; use std::hash::{Hash, Hasher}; @@ -70,6 +71,25 @@ impl IdMethodType { self.hash(&mut hasher); hasher.finish() } + + /// Return all strings referenced in the Id. + pub fn get_all_strings(&self) -> HashSet { + let mut strings = HashSet::new(); + strings.insert(self.shorty.clone()); + strings.extend(self.return_type.get_all_strings()); + for ty in &self.parameters { + strings.extend(ty.get_all_strings()); + } + strings + } + + /// Return all types referenced in the Id. + pub fn get_all_types(&self) -> HashSet { + let mut types = HashSet::new(); + types.insert(self.return_type.clone()); + types.extend(self.parameters.clone()); + types + } } impl IdMethodType { @@ -83,17 +103,6 @@ impl IdMethodType { } shorty.into() } - - /// Return all strings references in the Id. - pub fn get_all_strings(&self) -> HashSet { - let mut strings = HashSet::new(); - strings.insert(self.shorty.clone()); - strings.extend(self.return_type.get_all_strings()); - for ty in &self.parameters { - strings.extend(ty.get_all_strings()); - } - strings - } } /// A type. @@ -102,7 +111,7 @@ impl IdMethodType { // Not a clean rust enum because we want to be compatible with python, and maybe support strange // malware edge case? #[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct IdType(pub(crate) DexString); #[pymethods] impl IdType { @@ -349,13 +358,20 @@ impl IdType { self == other } - /// Return all strings references in the Id. + /// Return all strings referenced in the Id. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); strings.insert(self.0.clone()); strings } + /// Return all types referenced in the Id. + pub fn get_all_types(&self) -> HashSet { + let mut types = HashSet::new(); + types.insert(self.clone()); + types + } + // TODO: TESTS } @@ -414,7 +430,7 @@ impl IdField { hasher.finish() } - /// Return all strings references in the Id. + /// Return all strings referenced in the Id. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); strings.insert(self.name.clone()); @@ -422,6 +438,14 @@ impl IdField { strings.extend(self.class_.get_all_strings()); strings } + + /// Return all types referenced in the Id. + pub fn get_all_types(&self) -> HashSet { + let mut types = HashSet::new(); + types.insert(self.type_.clone()); + types.insert(self.class_.clone()); + types + } } /// The Id of a method. @@ -483,7 +507,7 @@ impl IdMethod { hasher.finish() } - /// Return all strings references in the Id. + /// Return all strings referenced in the Id. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); strings.insert(self.name.clone()); @@ -491,6 +515,14 @@ impl IdMethod { strings.extend(self.class_.get_all_strings()); strings } + + /// Return all types referenced in the Id. + pub fn get_all_types(&self) -> HashSet { + let mut types = HashSet::new(); + types.extend(self.proto.get_all_types()); + types.insert(self.class_.clone()); + types + } } #[pyclass] @@ -515,8 +547,13 @@ impl IdEnum { format!("DexEnum({})", self.__str__()) } - /// Return all strings references in the Id. + /// Return all strings referenced in the Id. pub fn get_all_strings(&self) -> HashSet { self.0.get_all_strings() } + + /// Return all types referenced in the Id. + pub fn get_all_types(&self) -> HashSet { + self.0.get_all_types() + } } diff --git a/androscalpel/src/dex_writer.rs b/androscalpel/src/dex_writer.rs index 05da33c..2514947 100644 --- a/androscalpel/src/dex_writer.rs +++ b/androscalpel/src/dex_writer.rs @@ -3,6 +3,8 @@ use std::collections::HashMap; use std::io::{Cursor, Write}; +//use anyhow::bail; + use crate::Result; use crate::*; use androscalpel_serializer::*; @@ -11,7 +13,7 @@ use androscalpel_serializer::*; pub struct DexWriter { header: HeaderItem, strings: HashMap, - _types_ids: HashMap, + type_ids: HashMap, _proto_ids: HashMap, _field_ids: HashMap, _method_ids: HashMap, @@ -57,7 +59,7 @@ impl Default for DexWriter { data_off: 0, }, strings: HashMap::new(), - _types_ids: HashMap::new(), + type_ids: HashMap::new(), _proto_ids: HashMap::new(), _field_ids: HashMap::new(), _method_ids: HashMap::new(), @@ -71,10 +73,33 @@ impl DexWriter { } pub fn add_class(&mut self, class: &Class) -> Result<()> { - // TODO: check size max - for string in class.get_all_strings() { + let new_strings = class.get_all_strings(); + /* this means more strings than bytes in the file, prbl no gonna append first + let mut futur_string_set = new_strings.clone(); + futur_string_set.extend(self.strings.keys().cloned()); + if futur_string_set.len() >= u32::MAX as usize { + // TODO return structured error to handle this case by generating multiple dex files + bail!("To many strings for one dex file"); + } + */ + + let new_types = class.get_all_types(); + /* this means more types than bytes in the file, prbl no gonna append + * and len(type) <= len(string) anyway + let mut future_type_set = new_types.clone(); + future_type_set.extend(self.type_ids.keys().cloned()); + if future_type_set.len() >= u32::MAX as usize { + // TODO return structured error to handle this case by generating multiple dex files + bail!("To many types for one dex file"); + } + */ + + for string in new_strings { self.strings.insert(string, 0); } + for ty in new_types { + self.type_ids.insert(ty, 0); + } Ok(()) } @@ -87,31 +112,8 @@ impl DexWriter { fn write_dex_file(&mut self, writer: &mut dyn Write) -> Result<()> { let mut section_manager = SectionManager::default(); section_manager.incr_section_size(Section::HeaderItem, 0x70); - // TODO: - // map_list: - // - [x] header_item - // - [x] string_id_item - // - [ ] type_id_item - // - [ ] proto_id_item - // - [ ] field_id_item - // - [ ] method_id_item - // - [ ] class_def_item - // - [ ] call_site_id_item - // - [ ] method_handle_item - // - [ ] map_list - // - [ ] type_list - // - [ ] annotation_set_ref_list - // - [ ] annotation_set_item - // - [ ] class_data_item - // - [ ] code_item - // - [ ] string_data_item - // - [ ] debug_info_item - // - [ ] annotation_item - // - [ ] encoded_array_item - // - [ ] annotations_directory_item - // - [ ] hiddenapi_class_data_item - // Use section_manager for seting the right size/offset afterward + // Sort Strings and generate StringDataItem let mut string_ids_list: Vec = self.strings.keys().cloned().collect(); string_ids_list.sort(); for (idx, string) in string_ids_list.iter().enumerate() { @@ -126,6 +128,19 @@ impl DexWriter { .map(|string| string.into()) .collect(); + // Sort types and generate TypeIdItem + let mut type_ids_list: Vec = self.type_ids.keys().cloned().collect(); + type_ids_list.sort(); + for (idx, ty) in type_ids_list.iter().enumerate() { + self.type_ids.entry(ty.clone()).and_modify(|val| *val = idx); + section_manager.add_elt(Section::TypeIdItem, None); + } + let type_ids_list: Vec = (0..type_ids_list.len()) + .map(|idx| TypeIdItem { + descriptor_idx: idx as u32, + }) + .collect(); + // Populate map_list let map_item_size = MapItem { type_: MapItemType::HeaderItem, @@ -181,7 +196,9 @@ impl DexWriter { str_id.serialize(writer)?; string_off += string.size() as u32; } - // TODO: TypeIdItem + for ty in type_ids_list { + ty.serialize(writer)?; + } // TODO: ProtoIdItem, // TODO: FieldIdItem, // TODO: MethodIdItem, @@ -196,7 +213,6 @@ impl DexWriter { // TODO: AnnotationSetItem, // TODO: ClassDataItem, // TODO: CodeItem, - // TODO: StringDataItem, for string in string_ids_list { string.serialize(writer)?; } @@ -206,6 +222,7 @@ impl DexWriter { // TODO: EncodedArrayItem, // TODO: AnnotationsDirectoryItem, // TODO: HiddenapiClassDataItem, + Ok(()) } } @@ -324,10 +341,12 @@ impl Section { ) } } else { - fixed_size.or(default_size).expect(&format!( - "Element of {:?} don't have a fixed size, you need to provide one", - self - )) + fixed_size.or(default_size).unwrap_or_else(|| { + panic!( + "Element of {:?} don't have a fixed size, you need to provide one", + self + ) + }) } } @@ -359,10 +378,7 @@ impl Section { } fn is_data(&self) -> bool { - match self { - Self::Data => true, - _ => false, - } + matches!(self, Self::Data) } } diff --git a/androscalpel/src/field.rs b/androscalpel/src/field.rs index 3098a09..2236103 100644 --- a/androscalpel/src/field.rs +++ b/androscalpel/src/field.rs @@ -4,7 +4,7 @@ use std::collections::HashSet; use pyo3::prelude::*; -use crate::{DexAnnotationItem, DexString, DexValue, IdField}; +use crate::{DexAnnotationItem, DexString, DexValue, IdField, IdType}; /// Represent a field. #[pyclass] @@ -119,7 +119,7 @@ impl Field { Ok(()) } - /// Return all strings references in the field. + /// Return all strings referenced in the field. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); @@ -132,4 +132,17 @@ impl Field { } strings } + + /// Return all types referenced in the field. + pub fn get_all_types(&self) -> HashSet { + let mut types = HashSet::new(); + types.extend(self.descriptor.get_all_types()); + if let Some(value) = &self.value { + types.extend(value.get_all_types()); + } + for annot in &self.annotations { + types.extend(annot.get_all_types()); + } + types + } } diff --git a/androscalpel/src/method.rs b/androscalpel/src/method.rs index 47b34dd..4f2da4d 100644 --- a/androscalpel/src/method.rs +++ b/androscalpel/src/method.rs @@ -4,7 +4,7 @@ use std::collections::HashSet; use pyo3::prelude::*; -use crate::{Code, DexAnnotationItem, DexString, IdMethod}; +use crate::{Code, DexAnnotationItem, DexString, IdMethod, IdType}; /// Represent a method. #[pyclass] @@ -106,7 +106,7 @@ impl Method { format!("Method({dscr})") } - /// Return all strings references in the method. + /// Return all strings referenced in the method. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); strings.extend(self.descriptor.get_all_strings()); @@ -123,4 +123,23 @@ impl Method { } strings } + + /// Return all types referenced in the method. + pub fn get_all_types(&self) -> HashSet { + let mut types = HashSet::new(); + types.extend(self.descriptor.get_all_types()); + for annot in &self.annotations { + types.extend(annot.get_all_types()); + } + for param_annots in &self.parameters_annotations { + for annot in param_annots { + types.extend(annot.get_all_types()); + } + } + if let Some(code) = &self.code { + types.extend(code.get_all_types()); + } + + types + } } diff --git a/androscalpel/src/method_handle.rs b/androscalpel/src/method_handle.rs index ef86100..a292dd9 100644 --- a/androscalpel/src/method_handle.rs +++ b/androscalpel/src/method_handle.rs @@ -45,10 +45,15 @@ impl StaticPut { format!("StaticPut({})", self.0.__str__()) } - /// Return all strings references in the handle. + /// Return all strings referenced in the handle. pub fn get_all_strings(&self) -> HashSet { self.0.get_all_strings() } + + /// Return all types referenced in the handle. + pub fn get_all_types(&self) -> HashSet { + self.0.get_all_types() + } } #[pyclass] #[derive(Debug, Clone, PartialEq, Eq)] @@ -73,10 +78,15 @@ impl StaticGet { format!("StaticGet({})", self.0.__str__()) } - /// Return all strings references in the handle. + /// Return all strings referenced in the handle. pub fn get_all_strings(&self) -> HashSet { self.0.get_all_strings() } + + /// Return all types referenced in the handle. + pub fn get_all_types(&self) -> HashSet { + self.0.get_all_types() + } } #[pyclass] #[derive(Debug, Clone, PartialEq, Eq)] @@ -101,10 +111,15 @@ impl InstancePut { format!("InstancePut({})", self.0.__str__()) } - /// Return all strings references in the handle. + /// Return all strings referenced in the handle. pub fn get_all_strings(&self) -> HashSet { self.0.get_all_strings() } + + /// Return all types referenced in the handle. + pub fn get_all_types(&self) -> HashSet { + self.0.get_all_types() + } } #[pyclass] #[derive(Debug, Clone, PartialEq, Eq)] @@ -129,10 +144,15 @@ impl InstanceGet { format!("InstanceGet({})", self.0.__str__()) } - /// Return all strings references in the handle. + /// Return all strings referenced in the handle. pub fn get_all_strings(&self) -> HashSet { self.0.get_all_strings() } + + /// Return all types referenced in the handle. + pub fn get_all_types(&self) -> HashSet { + self.0.get_all_types() + } } #[pyclass] @@ -158,10 +178,15 @@ impl InvokeStatic { format!("InvokeStatic({})", self.0.__str__()) } - /// Return all strings references in the handle. + /// Return all strings referenced in the handle. pub fn get_all_strings(&self) -> HashSet { self.0.get_all_strings() } + + /// Return all types referenced in the handle. + pub fn get_all_types(&self) -> HashSet { + self.0.get_all_types() + } } #[pyclass] @@ -187,10 +212,15 @@ impl InvokeInstance { format!("InvokeInstance({})", self.0.__str__()) } - /// Return all strings references in the handle. + /// Return all strings referenced in the handle. pub fn get_all_strings(&self) -> HashSet { self.0.get_all_strings() } + + /// Return all types referenced in the handle. + pub fn get_all_types(&self) -> HashSet { + self.0.get_all_types() + } } #[pyclass] @@ -216,10 +246,15 @@ impl InvokeConstructor { format!("InvokeConstructor({})", self.0.__str__()) } - /// Return all strings references in the handle. + /// Return all strings referenced in the handle. pub fn get_all_strings(&self) -> HashSet { self.0.get_all_strings() } + + /// Return all types referenced in the handle. + pub fn get_all_types(&self) -> HashSet { + self.0.get_all_types() + } } #[pyclass] @@ -245,10 +280,15 @@ impl InvokeDirect { format!("InvokeDirect({})", self.0.__str__()) } - /// Return all strings references in the handle. + /// Return all strings referenced in the handle. pub fn get_all_strings(&self) -> HashSet { self.0.get_all_strings() } + + /// Return all types referenced in the handle. + pub fn get_all_types(&self) -> HashSet { + self.0.get_all_types() + } } #[pyclass] @@ -274,10 +314,15 @@ impl InvokeInterface { format!("InvokeInterface({})", self.0.__str__()) } - /// Return all strings references in the handle. + /// Return all strings referenced in the handle. pub fn get_all_strings(&self) -> HashSet { self.0.get_all_strings() } + + /// Return all types referenced in the handle. + pub fn get_all_types(&self) -> HashSet { + self.0.get_all_types() + } } impl<'source> FromPyObject<'source> for MethodHandle { @@ -341,7 +386,7 @@ impl MethodHandle { } } - /// Return all strings references in the Handle. + /// Return all strings referenced in the Handle. pub fn get_all_strings(&self) -> HashSet { match self { Self::StaticPut(val) => val.get_all_strings(), @@ -355,4 +400,19 @@ impl MethodHandle { Self::InvokeInterface(val) => val.get_all_strings(), } } + + /// Return all types referenced in the Handle. + pub fn get_all_types(&self) -> HashSet { + match self { + Self::StaticPut(val) => val.get_all_types(), + Self::StaticGet(val) => val.get_all_types(), + Self::InstancePut(val) => val.get_all_types(), + Self::InstanceGet(val) => val.get_all_types(), + Self::InvokeStatic(val) => val.get_all_types(), + Self::InvokeInstance(val) => val.get_all_types(), + Self::InvokeConstructor(val) => val.get_all_types(), + Self::InvokeDirect(val) => val.get_all_types(), + Self::InvokeInterface(val) => val.get_all_types(), + } + } } diff --git a/androscalpel/src/scalar.rs b/androscalpel/src/scalar.rs index 0099832..8ed7295 100644 --- a/androscalpel/src/scalar.rs +++ b/androscalpel/src/scalar.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; -use crate::{DexString, DexValue}; +use crate::{DexString, DexValue, IdType}; use pyo3::prelude::*; #[pyclass] @@ -26,11 +26,6 @@ impl DexByte { pub fn __repr__(&self) -> String { format!("DexByte({})", self.0) } - - /// Return all strings references in the value. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } } #[pyclass] @@ -54,11 +49,6 @@ impl DexShort { pub fn __repr__(&self) -> String { format!("DexShort({})", self.0) } - - /// Return all strings references in the value. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } } #[pyclass] @@ -82,11 +72,6 @@ impl DexChar { pub fn __repr__(&self) -> String { format!("DexChar({})", self.0) } - - /// Return all strings references in the value. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } } #[pyclass] @@ -110,11 +95,6 @@ impl DexInt { pub fn __repr__(&self) -> String { format!("DexInt({})", self.0) } - - /// Return all strings references in the value. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } } #[pyclass] @@ -138,11 +118,6 @@ impl DexLong { pub fn __repr__(&self) -> String { format!("DexLong({})", self.0) } - - /// Return all strings references in the value. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } } #[pyclass] @@ -166,11 +141,6 @@ impl DexFloat { pub fn __repr__(&self) -> String { format!("DexFloat({})", self.0) } - - /// Return all strings references in the value. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } } #[pyclass] @@ -194,11 +164,6 @@ impl DexDouble { pub fn __repr__(&self) -> String { format!("DexDouble({})", self.0) } - - /// Return all strings references in the value. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } } /* DexString is already define in lib.rs, TODO: move the version in lib.rs here @@ -243,11 +208,6 @@ impl DexNull { pub fn __repr__(&self) -> String { "DexNull".into() } - - /// Return all strings references in the value. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } } #[pyclass] @@ -271,11 +231,6 @@ impl DexBoolean { pub fn __repr__(&self) -> String { format!("DexBoolean({})", self.0) } - - /// Return all strings references in the value. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } } #[pyclass] @@ -307,7 +262,7 @@ impl DexArray { "DexArray(...)".into() } - /// Return all strings references in the value. + /// Return all strings referenced in the value. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); for val in &self.0 { @@ -315,4 +270,13 @@ impl DexArray { } strings } + + /// Return all type referenced in the value. + pub fn get_all_types(&self) -> HashSet { + let mut types = HashSet::new(); + for val in &self.0 { + types.extend(val.get_all_types()); + } + types + } } diff --git a/androscalpel/src/value.rs b/androscalpel/src/value.rs index 9fc9d56..0b33046 100644 --- a/androscalpel/src/value.rs +++ b/androscalpel/src/value.rs @@ -101,16 +101,16 @@ impl DexValue { } } - /// Return all strings references in the value. + /// Return all strings referenced in the value. pub fn get_all_strings(&self) -> HashSet { match self { - DexValue::Byte(val) => val.get_all_strings(), - DexValue::Short(val) => val.get_all_strings(), - DexValue::Char(val) => val.get_all_strings(), - DexValue::Int(val) => val.get_all_strings(), - DexValue::Long(val) => val.get_all_strings(), - DexValue::Float(val) => val.get_all_strings(), - DexValue::Double(val) => val.get_all_strings(), + DexValue::Byte(_) => HashSet::new(), + DexValue::Short(_) => HashSet::new(), + DexValue::Char(_) => HashSet::new(), + DexValue::Int(_) => HashSet::new(), + DexValue::Long(_) => HashSet::new(), + DexValue::Float(_) => HashSet::new(), + DexValue::Double(_) => HashSet::new(), DexValue::MethodType(val) => val.get_all_strings(), DexValue::MethodHandle(val) => val.get_all_strings(), DexValue::String(val) => val.get_all_strings(), @@ -120,8 +120,32 @@ impl DexValue { DexValue::Enum(val) => val.get_all_strings(), DexValue::Array(val) => val.get_all_strings(), DexValue::Annotation(val) => val.get_all_strings(), - DexValue::Null(val) => val.get_all_strings(), - DexValue::Boolean(val) => val.get_all_strings(), + DexValue::Null(_) => HashSet::new(), + DexValue::Boolean(_) => HashSet::new(), + } + } + + /// Return all types referenced in the value. + pub fn get_all_types(&self) -> HashSet { + match self { + DexValue::Byte(_) => HashSet::new(), + DexValue::Short(_) => HashSet::new(), + DexValue::Char(_) => HashSet::new(), + DexValue::Int(_) => HashSet::new(), + DexValue::Long(_) => HashSet::new(), + DexValue::Float(_) => HashSet::new(), + DexValue::Double(_) => HashSet::new(), + DexValue::MethodType(val) => val.get_all_types(), + DexValue::MethodHandle(val) => val.get_all_types(), + DexValue::String(_) => HashSet::new(), + DexValue::Type(val) => val.get_all_types(), + DexValue::Field(val) => val.get_all_types(), + DexValue::Method(val) => val.get_all_types(), + DexValue::Enum(val) => val.get_all_types(), + DexValue::Array(val) => val.get_all_types(), + DexValue::Annotation(val) => val.get_all_types(), + DexValue::Null(_) => HashSet::new(), + DexValue::Boolean(_) => HashSet::new(), } } } diff --git a/androscalpel_serializer/src/items/mod.rs b/androscalpel_serializer/src/items/mod.rs index 551caac..82fb4cf 100644 --- a/androscalpel_serializer/src/items/mod.rs +++ b/androscalpel_serializer/src/items/mod.rs @@ -1,5 +1,7 @@ //! The items structures. +use std::cmp::{Ord, PartialOrd}; + use crate as androscalpel_serializer; use crate::{EncodedArray, Serializable}; @@ -27,7 +29,7 @@ pub use crate::StringDataItem; /// /// alignment: 4 bytes -#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct TypeIdItem { /// Index of a [`StringIdItem`] in `string_ids`. pub descriptor_idx: u32,