add type to generated dex file

This commit is contained in:
Jean-Marie Mineau 2023-12-01 12:38:54 +01:00
parent df9149c068
commit 211402ae9d
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
11 changed files with 328 additions and 132 deletions

View file

@ -62,10 +62,15 @@ impl DexAnnotationItem {
format!("AnnotationItem(visibility: {visibility}, {annotation})") 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
self.annotation.get_all_strings() self.annotation.get_all_strings()
} }
/// Return all types referenced in the annotation.
pub fn get_all_types(&self) -> HashSet<IdType> {
self.annotation.get_all_types()
}
} }
/// An annotation. /// An annotation.
@ -103,7 +108,7 @@ impl DexAnnotation {
format!("Annotation({type_}, {elts})") 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
let mut strings = HashSet::new(); let mut strings = HashSet::new();
strings.extend(self.type_.get_all_strings()); strings.extend(self.type_.get_all_strings());
@ -113,4 +118,14 @@ impl DexAnnotation {
} }
strings strings
} }
/// Return all types referenced in the annotation.
pub fn get_all_types(&self) -> HashSet<IdType> {
let mut types = HashSet::new();
types.insert(self.type_.clone());
for value in self.elements.values() {
types.extend(value.get_all_types());
}
types
}
} }

View file

@ -126,7 +126,7 @@ impl Class {
format!("Class({name})") format!("Class({name})")
} }
/// Return all strings references in the class. /// Return all strings referenced in the class.
pub fn get_all_strings(&self) -> HashSet<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
let mut strings = HashSet::new(); let mut strings = HashSet::new();
strings.extend(self.descriptor.get_all_strings()); strings.extend(self.descriptor.get_all_strings());
@ -151,8 +151,43 @@ impl Class {
strings.extend(id.get_all_strings()); strings.extend(id.get_all_strings());
strings.extend(method.get_all_strings()); strings.extend(method.get_all_strings());
} }
//pub virtual_methods: HashMap<IdMethod, Method>, for (id, method) in &self.virtual_methods {
//pub annotations: Vec<DexAnnotationItem>, strings.extend(id.get_all_strings());
strings.extend(method.get_all_strings());
}
for annot in &self.annotations {
strings.extend(annot.get_all_strings());
}
strings strings
} }
/// Return all types referenced in the class.
pub fn get_all_types(&self) -> HashSet<IdType> {
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
}
} }

View file

@ -63,7 +63,7 @@ impl Code {
"Code()".into() "Code()".into()
} }
/// Return all strings references in the codes. /// Return all strings referenced in the codes.
pub fn get_all_strings(&self) -> HashSet<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
let mut strings = HashSet::new(); let mut strings = HashSet::new();
for (list, _) in &self.handlers { for (list, _) in &self.handlers {
@ -73,4 +73,15 @@ impl Code {
} }
strings strings
} }
/// Return all types referenced in the codes.
pub fn get_all_types(&self) -> HashSet<IdType> {
let mut types = HashSet::new();
for (list, _) in &self.handlers {
for (ty, _) in list {
types.insert(ty.clone());
}
}
types
}
} }

View file

@ -1,5 +1,6 @@
//! The class identifying dex structure. //! The class identifying dex structure.
use std::cmp::{Ord, PartialOrd};
use std::collections::hash_map::DefaultHasher; use std::collections::hash_map::DefaultHasher;
use std::collections::HashSet; use std::collections::HashSet;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
@ -70,6 +71,25 @@ impl IdMethodType {
self.hash(&mut hasher); self.hash(&mut hasher);
hasher.finish() hasher.finish()
} }
/// Return all strings referenced in the Id.
pub fn get_all_strings(&self) -> HashSet<DexString> {
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<IdType> {
let mut types = HashSet::new();
types.insert(self.return_type.clone());
types.extend(self.parameters.clone());
types
}
} }
impl IdMethodType { impl IdMethodType {
@ -83,17 +103,6 @@ impl IdMethodType {
} }
shorty.into() shorty.into()
} }
/// Return all strings references in the Id.
pub fn get_all_strings(&self) -> HashSet<DexString> {
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. /// 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 // Not a clean rust enum because we want to be compatible with python, and maybe support strange
// malware edge case? // malware edge case?
#[pyclass] #[pyclass]
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct IdType(pub(crate) DexString); pub struct IdType(pub(crate) DexString);
#[pymethods] #[pymethods]
impl IdType { impl IdType {
@ -349,13 +358,20 @@ impl IdType {
self == other self == other
} }
/// Return all strings references in the Id. /// Return all strings referenced in the Id.
pub fn get_all_strings(&self) -> HashSet<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
let mut strings = HashSet::new(); let mut strings = HashSet::new();
strings.insert(self.0.clone()); strings.insert(self.0.clone());
strings strings
} }
/// Return all types referenced in the Id.
pub fn get_all_types(&self) -> HashSet<IdType> {
let mut types = HashSet::new();
types.insert(self.clone());
types
}
// TODO: TESTS // TODO: TESTS
} }
@ -414,7 +430,7 @@ impl IdField {
hasher.finish() hasher.finish()
} }
/// Return all strings references in the Id. /// Return all strings referenced in the Id.
pub fn get_all_strings(&self) -> HashSet<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
let mut strings = HashSet::new(); let mut strings = HashSet::new();
strings.insert(self.name.clone()); strings.insert(self.name.clone());
@ -422,6 +438,14 @@ impl IdField {
strings.extend(self.class_.get_all_strings()); strings.extend(self.class_.get_all_strings());
strings strings
} }
/// Return all types referenced in the Id.
pub fn get_all_types(&self) -> HashSet<IdType> {
let mut types = HashSet::new();
types.insert(self.type_.clone());
types.insert(self.class_.clone());
types
}
} }
/// The Id of a method. /// The Id of a method.
@ -483,7 +507,7 @@ impl IdMethod {
hasher.finish() hasher.finish()
} }
/// Return all strings references in the Id. /// Return all strings referenced in the Id.
pub fn get_all_strings(&self) -> HashSet<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
let mut strings = HashSet::new(); let mut strings = HashSet::new();
strings.insert(self.name.clone()); strings.insert(self.name.clone());
@ -491,6 +515,14 @@ impl IdMethod {
strings.extend(self.class_.get_all_strings()); strings.extend(self.class_.get_all_strings());
strings strings
} }
/// Return all types referenced in the Id.
pub fn get_all_types(&self) -> HashSet<IdType> {
let mut types = HashSet::new();
types.extend(self.proto.get_all_types());
types.insert(self.class_.clone());
types
}
} }
#[pyclass] #[pyclass]
@ -515,8 +547,13 @@ impl IdEnum {
format!("DexEnum({})", self.__str__()) 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
self.0.get_all_strings() self.0.get_all_strings()
} }
/// Return all types referenced in the Id.
pub fn get_all_types(&self) -> HashSet<IdType> {
self.0.get_all_types()
}
} }

View file

@ -3,6 +3,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::io::{Cursor, Write}; use std::io::{Cursor, Write};
//use anyhow::bail;
use crate::Result; use crate::Result;
use crate::*; use crate::*;
use androscalpel_serializer::*; use androscalpel_serializer::*;
@ -11,7 +13,7 @@ use androscalpel_serializer::*;
pub struct DexWriter { pub struct DexWriter {
header: HeaderItem, header: HeaderItem,
strings: HashMap<DexString, usize>, strings: HashMap<DexString, usize>,
_types_ids: HashMap<IdType, usize>, type_ids: HashMap<IdType, usize>,
_proto_ids: HashMap<IdMethodType, usize>, _proto_ids: HashMap<IdMethodType, usize>,
_field_ids: HashMap<IdField, usize>, _field_ids: HashMap<IdField, usize>,
_method_ids: HashMap<IdMethod, usize>, _method_ids: HashMap<IdMethod, usize>,
@ -57,7 +59,7 @@ impl Default for DexWriter {
data_off: 0, data_off: 0,
}, },
strings: HashMap::new(), strings: HashMap::new(),
_types_ids: HashMap::new(), type_ids: HashMap::new(),
_proto_ids: HashMap::new(), _proto_ids: HashMap::new(),
_field_ids: HashMap::new(), _field_ids: HashMap::new(),
_method_ids: HashMap::new(), _method_ids: HashMap::new(),
@ -71,10 +73,33 @@ impl DexWriter {
} }
pub fn add_class(&mut self, class: &Class) -> Result<()> { pub fn add_class(&mut self, class: &Class) -> Result<()> {
// TODO: check size max let new_strings = class.get_all_strings();
for string in 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); self.strings.insert(string, 0);
} }
for ty in new_types {
self.type_ids.insert(ty, 0);
}
Ok(()) Ok(())
} }
@ -87,31 +112,8 @@ impl DexWriter {
fn write_dex_file(&mut self, writer: &mut dyn Write) -> Result<()> { fn write_dex_file(&mut self, writer: &mut dyn Write) -> Result<()> {
let mut section_manager = SectionManager::default(); let mut section_manager = SectionManager::default();
section_manager.incr_section_size(Section::HeaderItem, 0x70); 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<DexString> = self.strings.keys().cloned().collect(); let mut string_ids_list: Vec<DexString> = self.strings.keys().cloned().collect();
string_ids_list.sort(); string_ids_list.sort();
for (idx, string) in string_ids_list.iter().enumerate() { for (idx, string) in string_ids_list.iter().enumerate() {
@ -126,6 +128,19 @@ impl DexWriter {
.map(|string| string.into()) .map(|string| string.into())
.collect(); .collect();
// Sort types and generate TypeIdItem
let mut type_ids_list: Vec<IdType> = 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<TypeIdItem> = (0..type_ids_list.len())
.map(|idx| TypeIdItem {
descriptor_idx: idx as u32,
})
.collect();
// Populate map_list // Populate map_list
let map_item_size = MapItem { let map_item_size = MapItem {
type_: MapItemType::HeaderItem, type_: MapItemType::HeaderItem,
@ -181,7 +196,9 @@ impl DexWriter {
str_id.serialize(writer)?; str_id.serialize(writer)?;
string_off += string.size() as u32; string_off += string.size() as u32;
} }
// TODO: TypeIdItem for ty in type_ids_list {
ty.serialize(writer)?;
}
// TODO: ProtoIdItem, // TODO: ProtoIdItem,
// TODO: FieldIdItem, // TODO: FieldIdItem,
// TODO: MethodIdItem, // TODO: MethodIdItem,
@ -196,7 +213,6 @@ impl DexWriter {
// TODO: AnnotationSetItem, // TODO: AnnotationSetItem,
// TODO: ClassDataItem, // TODO: ClassDataItem,
// TODO: CodeItem, // TODO: CodeItem,
// TODO: StringDataItem,
for string in string_ids_list { for string in string_ids_list {
string.serialize(writer)?; string.serialize(writer)?;
} }
@ -206,6 +222,7 @@ impl DexWriter {
// TODO: EncodedArrayItem, // TODO: EncodedArrayItem,
// TODO: AnnotationsDirectoryItem, // TODO: AnnotationsDirectoryItem,
// TODO: HiddenapiClassDataItem, // TODO: HiddenapiClassDataItem,
Ok(()) Ok(())
} }
} }
@ -324,10 +341,12 @@ impl Section {
) )
} }
} else { } else {
fixed_size.or(default_size).expect(&format!( fixed_size.or(default_size).unwrap_or_else(|| {
"Element of {:?} don't have a fixed size, you need to provide one", panic!(
self "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 { fn is_data(&self) -> bool {
match self { matches!(self, Self::Data)
Self::Data => true,
_ => false,
}
} }
} }

View file

@ -4,7 +4,7 @@ use std::collections::HashSet;
use pyo3::prelude::*; use pyo3::prelude::*;
use crate::{DexAnnotationItem, DexString, DexValue, IdField}; use crate::{DexAnnotationItem, DexString, DexValue, IdField, IdType};
/// Represent a field. /// Represent a field.
#[pyclass] #[pyclass]
@ -119,7 +119,7 @@ impl Field {
Ok(()) Ok(())
} }
/// Return all strings references in the field. /// Return all strings referenced in the field.
pub fn get_all_strings(&self) -> HashSet<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
let mut strings = HashSet::new(); let mut strings = HashSet::new();
@ -132,4 +132,17 @@ impl Field {
} }
strings strings
} }
/// Return all types referenced in the field.
pub fn get_all_types(&self) -> HashSet<IdType> {
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
}
} }

View file

@ -4,7 +4,7 @@ use std::collections::HashSet;
use pyo3::prelude::*; use pyo3::prelude::*;
use crate::{Code, DexAnnotationItem, DexString, IdMethod}; use crate::{Code, DexAnnotationItem, DexString, IdMethod, IdType};
/// Represent a method. /// Represent a method.
#[pyclass] #[pyclass]
@ -106,7 +106,7 @@ impl Method {
format!("Method({dscr})") format!("Method({dscr})")
} }
/// Return all strings references in the method. /// Return all strings referenced in the method.
pub fn get_all_strings(&self) -> HashSet<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
let mut strings = HashSet::new(); let mut strings = HashSet::new();
strings.extend(self.descriptor.get_all_strings()); strings.extend(self.descriptor.get_all_strings());
@ -123,4 +123,23 @@ impl Method {
} }
strings strings
} }
/// Return all types referenced in the method.
pub fn get_all_types(&self) -> HashSet<IdType> {
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
}
} }

View file

@ -45,10 +45,15 @@ impl StaticPut {
format!("StaticPut({})", self.0.__str__()) 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
self.0.get_all_strings() self.0.get_all_strings()
} }
/// Return all types referenced in the handle.
pub fn get_all_types(&self) -> HashSet<IdType> {
self.0.get_all_types()
}
} }
#[pyclass] #[pyclass]
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@ -73,10 +78,15 @@ impl StaticGet {
format!("StaticGet({})", self.0.__str__()) 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
self.0.get_all_strings() self.0.get_all_strings()
} }
/// Return all types referenced in the handle.
pub fn get_all_types(&self) -> HashSet<IdType> {
self.0.get_all_types()
}
} }
#[pyclass] #[pyclass]
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@ -101,10 +111,15 @@ impl InstancePut {
format!("InstancePut({})", self.0.__str__()) 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
self.0.get_all_strings() self.0.get_all_strings()
} }
/// Return all types referenced in the handle.
pub fn get_all_types(&self) -> HashSet<IdType> {
self.0.get_all_types()
}
} }
#[pyclass] #[pyclass]
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@ -129,10 +144,15 @@ impl InstanceGet {
format!("InstanceGet({})", self.0.__str__()) 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
self.0.get_all_strings() self.0.get_all_strings()
} }
/// Return all types referenced in the handle.
pub fn get_all_types(&self) -> HashSet<IdType> {
self.0.get_all_types()
}
} }
#[pyclass] #[pyclass]
@ -158,10 +178,15 @@ impl InvokeStatic {
format!("InvokeStatic({})", self.0.__str__()) 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
self.0.get_all_strings() self.0.get_all_strings()
} }
/// Return all types referenced in the handle.
pub fn get_all_types(&self) -> HashSet<IdType> {
self.0.get_all_types()
}
} }
#[pyclass] #[pyclass]
@ -187,10 +212,15 @@ impl InvokeInstance {
format!("InvokeInstance({})", self.0.__str__()) 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
self.0.get_all_strings() self.0.get_all_strings()
} }
/// Return all types referenced in the handle.
pub fn get_all_types(&self) -> HashSet<IdType> {
self.0.get_all_types()
}
} }
#[pyclass] #[pyclass]
@ -216,10 +246,15 @@ impl InvokeConstructor {
format!("InvokeConstructor({})", self.0.__str__()) 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
self.0.get_all_strings() self.0.get_all_strings()
} }
/// Return all types referenced in the handle.
pub fn get_all_types(&self) -> HashSet<IdType> {
self.0.get_all_types()
}
} }
#[pyclass] #[pyclass]
@ -245,10 +280,15 @@ impl InvokeDirect {
format!("InvokeDirect({})", self.0.__str__()) 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
self.0.get_all_strings() self.0.get_all_strings()
} }
/// Return all types referenced in the handle.
pub fn get_all_types(&self) -> HashSet<IdType> {
self.0.get_all_types()
}
} }
#[pyclass] #[pyclass]
@ -274,10 +314,15 @@ impl InvokeInterface {
format!("InvokeInterface({})", self.0.__str__()) 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
self.0.get_all_strings() self.0.get_all_strings()
} }
/// Return all types referenced in the handle.
pub fn get_all_types(&self) -> HashSet<IdType> {
self.0.get_all_types()
}
} }
impl<'source> FromPyObject<'source> for MethodHandle { 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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
match self { match self {
Self::StaticPut(val) => val.get_all_strings(), Self::StaticPut(val) => val.get_all_strings(),
@ -355,4 +400,19 @@ impl MethodHandle {
Self::InvokeInterface(val) => val.get_all_strings(), Self::InvokeInterface(val) => val.get_all_strings(),
} }
} }
/// Return all types referenced in the Handle.
pub fn get_all_types(&self) -> HashSet<IdType> {
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(),
}
}
} }

View file

@ -2,7 +2,7 @@
use std::collections::HashSet; use std::collections::HashSet;
use crate::{DexString, DexValue}; use crate::{DexString, DexValue, IdType};
use pyo3::prelude::*; use pyo3::prelude::*;
#[pyclass] #[pyclass]
@ -26,11 +26,6 @@ impl DexByte {
pub fn __repr__(&self) -> String { pub fn __repr__(&self) -> String {
format!("DexByte({})", self.0) format!("DexByte({})", self.0)
} }
/// Return all strings references in the value.
pub fn get_all_strings(&self) -> HashSet<DexString> {
HashSet::new()
}
} }
#[pyclass] #[pyclass]
@ -54,11 +49,6 @@ impl DexShort {
pub fn __repr__(&self) -> String { pub fn __repr__(&self) -> String {
format!("DexShort({})", self.0) format!("DexShort({})", self.0)
} }
/// Return all strings references in the value.
pub fn get_all_strings(&self) -> HashSet<DexString> {
HashSet::new()
}
} }
#[pyclass] #[pyclass]
@ -82,11 +72,6 @@ impl DexChar {
pub fn __repr__(&self) -> String { pub fn __repr__(&self) -> String {
format!("DexChar({})", self.0) format!("DexChar({})", self.0)
} }
/// Return all strings references in the value.
pub fn get_all_strings(&self) -> HashSet<DexString> {
HashSet::new()
}
} }
#[pyclass] #[pyclass]
@ -110,11 +95,6 @@ impl DexInt {
pub fn __repr__(&self) -> String { pub fn __repr__(&self) -> String {
format!("DexInt({})", self.0) format!("DexInt({})", self.0)
} }
/// Return all strings references in the value.
pub fn get_all_strings(&self) -> HashSet<DexString> {
HashSet::new()
}
} }
#[pyclass] #[pyclass]
@ -138,11 +118,6 @@ impl DexLong {
pub fn __repr__(&self) -> String { pub fn __repr__(&self) -> String {
format!("DexLong({})", self.0) format!("DexLong({})", self.0)
} }
/// Return all strings references in the value.
pub fn get_all_strings(&self) -> HashSet<DexString> {
HashSet::new()
}
} }
#[pyclass] #[pyclass]
@ -166,11 +141,6 @@ impl DexFloat {
pub fn __repr__(&self) -> String { pub fn __repr__(&self) -> String {
format!("DexFloat({})", self.0) format!("DexFloat({})", self.0)
} }
/// Return all strings references in the value.
pub fn get_all_strings(&self) -> HashSet<DexString> {
HashSet::new()
}
} }
#[pyclass] #[pyclass]
@ -194,11 +164,6 @@ impl DexDouble {
pub fn __repr__(&self) -> String { pub fn __repr__(&self) -> String {
format!("DexDouble({})", self.0) format!("DexDouble({})", self.0)
} }
/// Return all strings references in the value.
pub fn get_all_strings(&self) -> HashSet<DexString> {
HashSet::new()
}
} }
/* DexString is already define in lib.rs, TODO: move the version in lib.rs here /* 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 { pub fn __repr__(&self) -> String {
"DexNull".into() "DexNull".into()
} }
/// Return all strings references in the value.
pub fn get_all_strings(&self) -> HashSet<DexString> {
HashSet::new()
}
} }
#[pyclass] #[pyclass]
@ -271,11 +231,6 @@ impl DexBoolean {
pub fn __repr__(&self) -> String { pub fn __repr__(&self) -> String {
format!("DexBoolean({})", self.0) format!("DexBoolean({})", self.0)
} }
/// Return all strings references in the value.
pub fn get_all_strings(&self) -> HashSet<DexString> {
HashSet::new()
}
} }
#[pyclass] #[pyclass]
@ -307,7 +262,7 @@ impl DexArray {
"DexArray(...)".into() "DexArray(...)".into()
} }
/// Return all strings references in the value. /// Return all strings referenced in the value.
pub fn get_all_strings(&self) -> HashSet<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
let mut strings = HashSet::new(); let mut strings = HashSet::new();
for val in &self.0 { for val in &self.0 {
@ -315,4 +270,13 @@ impl DexArray {
} }
strings strings
} }
/// Return all type referenced in the value.
pub fn get_all_types(&self) -> HashSet<IdType> {
let mut types = HashSet::new();
for val in &self.0 {
types.extend(val.get_all_types());
}
types
}
} }

View file

@ -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<DexString> { pub fn get_all_strings(&self) -> HashSet<DexString> {
match self { match self {
DexValue::Byte(val) => val.get_all_strings(), DexValue::Byte(_) => HashSet::new(),
DexValue::Short(val) => val.get_all_strings(), DexValue::Short(_) => HashSet::new(),
DexValue::Char(val) => val.get_all_strings(), DexValue::Char(_) => HashSet::new(),
DexValue::Int(val) => val.get_all_strings(), DexValue::Int(_) => HashSet::new(),
DexValue::Long(val) => val.get_all_strings(), DexValue::Long(_) => HashSet::new(),
DexValue::Float(val) => val.get_all_strings(), DexValue::Float(_) => HashSet::new(),
DexValue::Double(val) => val.get_all_strings(), DexValue::Double(_) => HashSet::new(),
DexValue::MethodType(val) => val.get_all_strings(), DexValue::MethodType(val) => val.get_all_strings(),
DexValue::MethodHandle(val) => val.get_all_strings(), DexValue::MethodHandle(val) => val.get_all_strings(),
DexValue::String(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::Enum(val) => val.get_all_strings(),
DexValue::Array(val) => val.get_all_strings(), DexValue::Array(val) => val.get_all_strings(),
DexValue::Annotation(val) => val.get_all_strings(), DexValue::Annotation(val) => val.get_all_strings(),
DexValue::Null(val) => val.get_all_strings(), DexValue::Null(_) => HashSet::new(),
DexValue::Boolean(val) => val.get_all_strings(), DexValue::Boolean(_) => HashSet::new(),
}
}
/// Return all types referenced in the value.
pub fn get_all_types(&self) -> HashSet<IdType> {
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(),
} }
} }
} }

View file

@ -1,5 +1,7 @@
//! The items structures. //! The items structures.
use std::cmp::{Ord, PartialOrd};
use crate as androscalpel_serializer; use crate as androscalpel_serializer;
use crate::{EncodedArray, Serializable}; use crate::{EncodedArray, Serializable};
@ -27,7 +29,7 @@ pub use crate::StringDataItem;
/// <https://source.android.com/docs/core/runtime/dex-format#type-id-item> /// <https://source.android.com/docs/core/runtime/dex-format#type-id-item>
/// alignment: 4 bytes /// alignment: 4 bytes
#[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct TypeIdItem { pub struct TypeIdItem {
/// Index of a [`StringIdItem`] in `string_ids`. /// Index of a [`StringIdItem`] in `string_ids`.
pub descriptor_idx: u32, pub descriptor_idx: u32,