From 1bf328d44ed66267772b5df3ba4e96df15f1a589 Mon Sep 17 00:00:00 2001 From: Jean-Marie Mineau Date: Tue, 5 Sep 2023 17:52:21 +0200 Subject: [PATCH] wip --- androscalpel/src/field.rs | 171 +++++++++++++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 3 deletions(-) diff --git a/androscalpel/src/field.rs b/androscalpel/src/field.rs index b2750ff..29c8cc7 100644 --- a/androscalpel/src/field.rs +++ b/androscalpel/src/field.rs @@ -4,6 +4,7 @@ use pyo3::exceptions::PyTypeError; use pyo3::prelude::*; use crate::DexString; +use androscalpel_serializer::{StringDataItem, Uleb128}; /// Represent a field. #[pyclass] @@ -281,9 +282,9 @@ impl DexDouble { #[derive(Debug, Clone, PartialEq, Eq)] pub struct DexMethodType { /// Type formated as described by - shorty: DexString, - return_type: DexType, - parameters: Vec, + pub(crate) shorty: DexString, + pub(crate) return_type: DexType, + pub(crate) parameters: Vec, } #[pymethods] @@ -382,6 +383,74 @@ impl DexType { Self(ty) } + /// Return the void type (for return type) + #[staticmethod] + pub fn void() -> Self { + Self("V".into()) + } + + /// Return the boolean type + #[staticmethod] + pub fn boolean() -> Self { + Self("Z".into()) + } + /// Return the byte type + #[staticmethod] + pub fn byte() -> Self { + Self("B".into()) + } + + /// Return the short type + #[staticmethod] + pub fn short() -> Self { + Self("S".into()) + } + + /// Return the char type + #[staticmethod] + pub fn char() -> Self { + Self("C".into()) + } + + /// Return the int type + #[staticmethod] + pub fn int() -> Self { + Self("I".into()) + } + + /// Return the long type + #[staticmethod] + pub fn long() -> Self { + Self("J".into()) + } + + /// Return the float type + #[staticmethod] + pub fn float() -> Self { + Self("F".into()) + } + + /// Return the double type + #[staticmethod] + pub fn double() -> Self { + Self("D".into()) + } + + /// Return the type for the class of fully qualified name `name` + #[staticmethod] + pub fn class(name: &str) -> Self { + Self(format!("L{name}").into()) + } + + /// Return the type for an array of the specify `type_` + #[staticmethod] + pub fn array(type_: &DexType) -> Self { + let mut ty = type_.clone(); + ty.0 .0.utf16_size.0 += 1; + ty.0 .0.data.insert(0, 0x5b); + ty + } + pub fn get_name(&self) -> DexString { self.0.clone() } @@ -394,6 +463,102 @@ impl DexType { let name: String = (&self.0).into(); format!("DexType({name})") } + + /// Check if the type is void (return type) + pub fn is_void(&self) -> bool { + self == &Self::void() + } + + /// Check if the type is boolean + pub fn is_boolean(&self) -> bool { + self == &Self::boolean() + } + + /// Check if the type is byte + pub fn is_byte(&self) -> bool { + self == &Self::byte() + } + + /// Check if the type is short + pub fn is_short(&self) -> bool { + self == &Self::short() + } + + /// Check if the type is char + pub fn is_char(&self) -> bool { + self == &Self::char() + } + + /// Check if the type is int + pub fn is_int(&self) -> bool { + self == &Self::int() + } + + /// Check if the type is long + pub fn is_long(&self) -> bool { + self == &Self::long() + } + + /// Check if the type is float + pub fn is_float(&self) -> bool { + self == &Self::float() + } + + /// Check if the type is double + pub fn is_double(&self) -> bool { + self == &Self::double() + } + + /// Check if the type is a class + pub fn is_class(&self) -> bool { + self.0.get_utf16_size() == 0 + && self.0.get_bytes().is_empty() + && self.0.get_bytes()[0] != 0x76 + // Check if first char is an L + } + + /// Check if the type is an array + pub fn is_array(&self) -> bool { + self.0.get_utf16_size() == 0 + && self.0.get_bytes().is_empty() + && self.0.get_bytes()[0] != 0x5b + // Check if first char is an [ + } + + /// If the type is a class, return the name of the class, + /// else None. + pub fn get_class_name(&self) -> Option { + if self.is_class() { + Some( + StringDataItem { + utf16_size: Uleb128(self.0.get_utf16_size() - 1), + data: self.0.get_bytes()[1..].to_vec(), + } + .into(), + ) + } else { + None + } + } + + /// If the type is a array, return the type of the elements, + /// else None. + pub fn get_element_type(&self) -> Option { + if self.is_array() { + Some(Self( + StringDataItem { + utf16_size: Uleb128(self.0.get_utf16_size() - 1), + data: self.0.get_bytes()[1..].to_vec(), + } + .into(), + )) + } else { + None + } + } + + // TODO: TESTS + // TODO: move to another mod } #[pyclass]