This commit is contained in:
Jean-Marie Mineau 2024-07-18 16:47:56 +02:00
parent 00009436c5
commit aad1fc862d
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
8 changed files with 208 additions and 204 deletions

View file

@ -7,7 +7,7 @@ use pyo3::prelude::*;
use crate::hashmap_vectorize;
use crate::{
dex_id::IdType, value::DexValue, DexString, IdField, IdMethod, IdMethodType, MethodHandle,
Result,
Result, Visitable, VisitableMut, Visitor, VisitorMut,
};
/// Annotation with a visibility
@ -217,3 +217,27 @@ impl DexAnnotation {
Ok(serde_json::from_str(json)?)
}
}
impl<V: Visitor> Visitable<V> for DexAnnotation {
fn default_visit(&self, v: &mut V) -> Result<()> {
v.visit_type(&self.type_)?;
for (id, val) in &self.elements {
v.visit_string(id)?;
v.visit_value(val)?;
}
Ok(())
}
}
impl<V: VisitorMut> VisitableMut<V> for DexAnnotation {
fn default_visit_mut(self, v: &mut V) -> Result<Self> {
let type_ = v.visit_type(self.type_)?;
let mut elements = HashMap::new();
for (id, val) in self.elements {
let id = v.visit_string(id)?;
let val = v.visit_value(val)?;
elements.insert(id, val);
}
Ok(Self { type_, elements })
}
}

View file

@ -265,7 +265,7 @@ impl Code {
let mut new_insns = vec![];
last_ins_was_a_label = false;
for ins in self.insns.into_iter() {
for ins in self.insns.iter().cloned() {
match ins {
Instruction::Goto { label } => {
last_ins_was_a_label = false;

View file

@ -511,9 +511,7 @@ impl DexWriter {
for ins in &code.insns {
match ins {
Instruction::FillArrayData {
data,
elt_width,
arr,
data, elt_width, ..
} => {
let payload = InsFormat::FormatFillArrayDataPayload {
elt_width: *elt_width,

View file

@ -3862,7 +3862,6 @@ impl Instruction {
Self::FloatToDouble { dest, val } => {
sanity_check_4_bit_reg!("float-to-double", dest, val)
}
Self::LongToInt { dest, val } => sanity_check_4_bit_reg!("long-to-int", dest, val),
Self::DoubleToInt { dest, val } => sanity_check_4_bit_reg!("double-to-int", dest, val),
Self::DoubleToLong { dest, val } => {
sanity_check_4_bit_reg!("double-to-long", dest, val)
@ -6609,3 +6608,30 @@ impl CallSite {
handles
}
}
impl<V: Visitor> Visitable<V> for CallSite {
fn default_visit(&self, v: &mut V) -> Result<()> {
v.visit_method_handle(&self.method_handle)?;
v.visit_string(&self.name)?;
v.visit_method_type(&self.type_)?;
for arg in &self.args {
v.visit_value(&arg)?;
}
Ok(())
}
}
impl<V: VisitorMut> VisitableMut<V> for CallSite {
fn default_visit_mut(self, v: &mut V) -> Result<Self> {
Ok(Self {
method_handle: v.visit_method_handle(self.method_handle)?,
name: v.visit_string(self.name)?,
type_: v.visit_method_type(self.type_)?,
args: self
.args
.into_iter()
.map(|arg| v.visit_value(arg))
.collect::<Result<_>>()?,
})
}
}

View file

@ -33,6 +33,7 @@ pub use dex_writer::*;
pub use field::*;
pub use hiddenapi::*;
pub use instructions as ins;
pub use instructions::*;
pub use method::*;
pub use method_handle::*;
pub use scalar::*;
@ -91,199 +92,6 @@ fn androscalpel(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
/// Dalvik opcode for Androscalpel.
fn androscalpel_ins(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<ins::CallSite>()?;
m.add_class::<ins::Nop>()?;
m.add_class::<ins::Move>()?;
m.add_class::<ins::MoveWide>()?;
m.add_class::<ins::MoveObject>()?;
m.add_class::<ins::MoveResult>()?;
m.add_class::<ins::MoveResultWide>()?;
m.add_class::<ins::MoveResultObject>()?;
m.add_class::<ins::MoveException>()?;
m.add_class::<ins::ReturnVoid>()?;
m.add_class::<ins::Return>()?;
m.add_class::<ins::ReturnWide>()?;
m.add_class::<ins::ReturnObject>()?;
m.add_class::<ins::Const>()?;
m.add_class::<ins::ConstWide>()?;
m.add_class::<ins::ConstString>()?;
m.add_class::<ins::ConstClass>()?;
m.add_class::<ins::MonitorEnter>()?;
m.add_class::<ins::MonitorExit>()?;
m.add_class::<ins::CheckCast>()?;
m.add_class::<ins::InstanceOf>()?;
m.add_class::<ins::ArrayLength>()?;
m.add_class::<ins::NewInstance>()?;
m.add_class::<ins::NewArray>()?;
m.add_class::<ins::FilledNewArray>()?;
m.add_class::<ins::FillArrayData>()?;
m.add_class::<ins::Throw>()?;
m.add_class::<ins::Goto>()?;
m.add_class::<ins::Switch>()?;
m.add_class::<ins::CmpLFloat>()?;
m.add_class::<ins::CmpGFloat>()?;
m.add_class::<ins::CmpLDouble>()?;
m.add_class::<ins::CmpGDouble>()?;
m.add_class::<ins::CmpLong>()?;
m.add_class::<ins::IfEq>()?;
m.add_class::<ins::IfNe>()?;
m.add_class::<ins::IfLt>()?;
m.add_class::<ins::IfGe>()?;
m.add_class::<ins::IfGt>()?;
m.add_class::<ins::IfLe>()?;
m.add_class::<ins::IfEqZ>()?;
m.add_class::<ins::IfNeZ>()?;
m.add_class::<ins::IfLtZ>()?;
m.add_class::<ins::IfGeZ>()?;
m.add_class::<ins::IfGtZ>()?;
m.add_class::<ins::IfLeZ>()?;
m.add_class::<ins::AGet>()?;
m.add_class::<ins::AGetWide>()?;
m.add_class::<ins::AGetObject>()?;
m.add_class::<ins::AGetBoolean>()?;
m.add_class::<ins::AGetByte>()?;
m.add_class::<ins::AGetChar>()?;
m.add_class::<ins::AGetShort>()?;
m.add_class::<ins::APut>()?;
m.add_class::<ins::APutWide>()?;
m.add_class::<ins::APutObject>()?;
m.add_class::<ins::APutBoolean>()?;
m.add_class::<ins::APutByte>()?;
m.add_class::<ins::APutChar>()?;
m.add_class::<ins::APutShort>()?;
m.add_class::<ins::IGet>()?;
m.add_class::<ins::IGetWide>()?;
m.add_class::<ins::IGetObject>()?;
m.add_class::<ins::IGetBoolean>()?;
m.add_class::<ins::IGetByte>()?;
m.add_class::<ins::IGetChar>()?;
m.add_class::<ins::IGetShort>()?;
m.add_class::<ins::IPut>()?;
m.add_class::<ins::IPutWide>()?;
m.add_class::<ins::IPutObject>()?;
m.add_class::<ins::IPutBoolean>()?;
m.add_class::<ins::IPutByte>()?;
m.add_class::<ins::IPutChar>()?;
m.add_class::<ins::IPutShort>()?;
m.add_class::<ins::SGet>()?;
m.add_class::<ins::SGetWide>()?;
m.add_class::<ins::SGetObject>()?;
m.add_class::<ins::SGetBoolean>()?;
m.add_class::<ins::SGetByte>()?;
m.add_class::<ins::SGetChar>()?;
m.add_class::<ins::SGetShort>()?;
m.add_class::<ins::SPut>()?;
m.add_class::<ins::SPutWide>()?;
m.add_class::<ins::SPutObject>()?;
m.add_class::<ins::SPutBoolean>()?;
m.add_class::<ins::SPutByte>()?;
m.add_class::<ins::SPutChar>()?;
m.add_class::<ins::SPutShort>()?;
m.add_class::<ins::InvokeVirtual>()?;
m.add_class::<ins::InvokeSuper>()?;
m.add_class::<ins::InvokeDirect>()?;
m.add_class::<ins::InvokeStatic>()?;
m.add_class::<ins::InvokeInterface>()?;
m.add_class::<ins::NegInt>()?;
m.add_class::<ins::NotInt>()?;
m.add_class::<ins::NegLong>()?;
m.add_class::<ins::NotLong>()?;
m.add_class::<ins::NegFloat>()?;
m.add_class::<ins::NegDouble>()?;
m.add_class::<ins::IntToLong>()?;
m.add_class::<ins::IntToFloat>()?;
m.add_class::<ins::IntToDouble>()?;
m.add_class::<ins::LongToInt>()?;
m.add_class::<ins::LongToFloat>()?;
m.add_class::<ins::LongToDouble>()?;
m.add_class::<ins::FloatToInt>()?;
m.add_class::<ins::FloatToLong>()?;
m.add_class::<ins::FloatToDouble>()?;
m.add_class::<ins::DoubleToInt>()?;
m.add_class::<ins::DoubleToLong>()?;
m.add_class::<ins::DoubleToFloat>()?;
m.add_class::<ins::IntToByte>()?;
m.add_class::<ins::IntToChar>()?;
m.add_class::<ins::IntToShort>()?;
m.add_class::<ins::AddInt>()?;
m.add_class::<ins::SubInt>()?;
m.add_class::<ins::MulInt>()?;
m.add_class::<ins::DivInt>()?;
m.add_class::<ins::RemInt>()?;
m.add_class::<ins::AndInt>()?;
m.add_class::<ins::OrInt>()?;
m.add_class::<ins::XorInt>()?;
m.add_class::<ins::ShlInt>()?;
m.add_class::<ins::ShrInt>()?;
m.add_class::<ins::UshrInt>()?;
m.add_class::<ins::AddLong>()?;
m.add_class::<ins::SubLong>()?;
m.add_class::<ins::MulLong>()?;
m.add_class::<ins::DivLong>()?;
m.add_class::<ins::RemLong>()?;
m.add_class::<ins::AndLong>()?;
m.add_class::<ins::OrLong>()?;
m.add_class::<ins::XorLong>()?;
m.add_class::<ins::ShlLong>()?;
m.add_class::<ins::ShrLong>()?;
m.add_class::<ins::UshrLong>()?;
m.add_class::<ins::AddFloat>()?;
m.add_class::<ins::SubFloat>()?;
m.add_class::<ins::MulFloat>()?;
m.add_class::<ins::DivFloat>()?;
m.add_class::<ins::RemFloat>()?;
m.add_class::<ins::AddDouble>()?;
m.add_class::<ins::SubDouble>()?;
m.add_class::<ins::MulDouble>()?;
m.add_class::<ins::DivDouble>()?;
m.add_class::<ins::RemDouble>()?;
m.add_class::<ins::AddInt2Addr>()?;
m.add_class::<ins::SubInt2Addr>()?;
m.add_class::<ins::MulInt2Addr>()?;
m.add_class::<ins::DivInt2Addr>()?;
m.add_class::<ins::RemInt2Addr>()?;
m.add_class::<ins::AndInt2Addr>()?;
m.add_class::<ins::OrInt2Addr>()?;
m.add_class::<ins::XorInt2Addr>()?;
m.add_class::<ins::ShlInt2Addr>()?;
m.add_class::<ins::ShrInt2Addr>()?;
m.add_class::<ins::UshrInt2Addr>()?;
m.add_class::<ins::AddLong2Addr>()?;
m.add_class::<ins::SubLong2Addr>()?;
m.add_class::<ins::MulLong2Addr>()?;
m.add_class::<ins::DivLong2Addr>()?;
m.add_class::<ins::RemLong2Addr>()?;
m.add_class::<ins::AndLong2Addr>()?;
m.add_class::<ins::OrLong2Addr>()?;
m.add_class::<ins::XorLong2Addr>()?;
m.add_class::<ins::ShlLong2Addr>()?;
m.add_class::<ins::ShrLong2Addr>()?;
m.add_class::<ins::UshrLong2Addr>()?;
m.add_class::<ins::AddFloat2Addr>()?;
m.add_class::<ins::SubFloat2Addr>()?;
m.add_class::<ins::MulFloat2Addr>()?;
m.add_class::<ins::DivFloat2Addr>()?;
m.add_class::<ins::RemFloat2Addr>()?;
m.add_class::<ins::AddDouble2Addr>()?;
m.add_class::<ins::SubDouble2Addr>()?;
m.add_class::<ins::MulDouble2Addr>()?;
m.add_class::<ins::DivDouble2Addr>()?;
m.add_class::<ins::RemDouble2Addr>()?;
m.add_class::<ins::AddIntLit>()?;
m.add_class::<ins::RsubIntLit>()?;
m.add_class::<ins::MulIntLit>()?;
m.add_class::<ins::DivIntLit>()?;
m.add_class::<ins::RemIntLit>()?;
m.add_class::<ins::AndIntLit>()?;
m.add_class::<ins::OrIntLit>()?;
m.add_class::<ins::XorIntLit>()?;
m.add_class::<ins::ShlIntLit>()?;
m.add_class::<ins::ShrIntLit>()?;
m.add_class::<ins::UshrIntLit>()?;
m.add_class::<ins::InvokePolymorphic>()?;
m.add_class::<ins::InvokeCustom>()?;
m.add_class::<ins::ConstMethodHandle>()?;
m.add_class::<ins::ConstMethodType>()?;
m.add_class::<ins::Try>()?;
m.add_class::<ins::Label>()?;
m.add_class::<ins::Instruction>()?;
Ok(())
}

View file

@ -4,7 +4,10 @@ use crate::Result;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use crate::{DexString, DexValue, IdField, IdMethod, IdMethodType, IdType, MethodHandle};
use crate::{
DexString, DexValue, IdField, IdMethod, IdMethodType, IdType, MethodHandle, Visitable,
VisitableMut, Visitor, VisitorMut,
};
use pyo3::prelude::*;
#[pyclass]
@ -417,3 +420,23 @@ impl DexArray {
methods
}
}
impl<V: Visitor> Visitable<V> for DexArray {
fn default_visit(&self, v: &mut V) -> Result<()> {
for val in &self.0 {
v.visit_value(&val)?;
}
Ok(())
}
}
impl<V: VisitorMut> VisitableMut<V> for DexArray {
fn default_visit_mut(self, v: &mut V) -> Result<Self> {
Ok(Self(
self.0
.into_iter()
.map(|val| v.visit_value(val))
.collect::<Result<_>>()?,
))
}
}

View file

@ -6,7 +6,10 @@ use std::collections::HashSet;
use pyo3::exceptions::PyTypeError;
use pyo3::prelude::*;
use crate::{dex_id::*, scalar::*, DexAnnotation, DexString, MethodHandle};
use crate::{
dex_id::*, scalar::*, DexAnnotation, DexString, MethodHandle, Result, Visitable, VisitableMut,
Visitor, VisitorMut,
};
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub enum DexValue {
@ -30,6 +33,56 @@ pub enum DexValue {
Boolean(DexBoolean),
}
impl<V: Visitor> Visitable<V> for DexValue {
fn default_visit(&self, v: &mut V) -> Result<()> {
match self {
Self::Byte(val) => v.visit_byte(val),
Self::Short(val) => v.visit_short(val),
Self::Char(val) => v.visit_char(val),
Self::Int(val) => v.visit_int(val),
Self::Long(val) => v.visit_long(val),
Self::Float(val) => v.visit_float(val),
Self::Double(val) => v.visit_double(val),
Self::MethodType(val) => v.visit_method_type(val),
Self::MethodHandle(val) => v.visit_method_handle(val),
Self::String(val) => v.visit_string(val),
Self::Type(val) => v.visit_type(val),
Self::Field(val) => v.visit_field_id(val),
Self::Method(val) => v.visit_method_id(val),
Self::Enum(val) => v.visit_enum_id(val),
Self::Array(val) => v.visit_array(val),
Self::Annotation(val) => v.visit_annotation(val),
Self::Null(val) => v.visit_null(val),
Self::Boolean(val) => v.visit_bool(val),
}
}
}
impl<V: VisitorMut> VisitableMut<V> for DexValue {
fn default_visit_mut(self, v: &mut V) -> Result<Self> {
match self {
Self::Byte(val) => Ok(Self::Byte(v.visit_byte(val)?)),
Self::Short(val) => Ok(Self::Short(v.visit_short(val)?)),
Self::Char(val) => Ok(Self::Char(v.visit_char(val)?)),
Self::Int(val) => Ok(Self::Int(v.visit_int(val)?)),
Self::Long(val) => Ok(Self::Long(v.visit_long(val)?)),
Self::Float(val) => Ok(Self::Float(v.visit_float(val)?)),
Self::Double(val) => Ok(Self::Double(v.visit_double(val)?)),
Self::MethodType(val) => Ok(Self::MethodType(v.visit_method_type(val)?)),
Self::MethodHandle(val) => Ok(Self::MethodHandle(v.visit_method_handle(val)?)),
Self::String(val) => Ok(Self::String(v.visit_string(val)?)),
Self::Type(val) => Ok(Self::Type(v.visit_type(val)?)),
Self::Field(val) => Ok(Self::Field(v.visit_field_id(val)?)),
Self::Method(val) => Ok(Self::Method(v.visit_method_id(val)?)),
Self::Enum(val) => Ok(Self::Enum(v.visit_enum_id(val)?)),
Self::Array(val) => Ok(Self::Array(v.visit_array(val)?)),
Self::Annotation(val) => Ok(Self::Annotation(v.visit_annotation(val)?)),
Self::Null(val) => Ok(Self::Null(v.visit_null(val)?)),
Self::Boolean(val) => Ok(Self::Boolean(v.visit_bool(val)?)),
}
}
}
impl<'source> FromPyObject<'source> for DexValue {
fn extract(ob: &'source PyAny) -> PyResult<Self> {
if let Ok(val) = DexByte::extract(ob) {

View file

@ -1,8 +1,8 @@
//! The visitor trait and common implementations.
use crate::{
ins::Instruction, CallSite, DexString, IdEnum, IdField, IdMethod, IdMethodType, IdType,
MethodHandle, Result,
ins::Instruction, scalar::*, CallSite, DexAnnotation, DexString, DexValue, IdEnum, IdField,
IdMethod, IdMethodType, IdType, MethodHandle, Result,
};
use std::collections::HashSet;
@ -34,6 +34,42 @@ pub trait Visitor: Sized {
fn visit_call_site(&mut self, site: &CallSite) -> Result<()> {
site.default_visit(self)
}
fn visit_value(&mut self, val: &DexValue) -> Result<()> {
val.default_visit(self)
}
fn visit_byte(&mut self, _: &DexByte) -> Result<()> {
Ok(())
}
fn visit_short(&mut self, _: &DexShort) -> Result<()> {
Ok(())
}
fn visit_char(&mut self, _: &DexChar) -> Result<()> {
Ok(())
}
fn visit_int(&mut self, _: &DexInt) -> Result<()> {
Ok(())
}
fn visit_long(&mut self, _: &DexLong) -> Result<()> {
Ok(())
}
fn visit_float(&mut self, _: &DexFloat) -> Result<()> {
Ok(())
}
fn visit_double(&mut self, _: &DexDouble) -> Result<()> {
Ok(())
}
fn visit_array(&mut self, val: &DexArray) -> Result<()> {
val.default_visit(self)
}
fn visit_annotation(&mut self, val: &DexAnnotation) -> Result<()> {
val.default_visit(self)
}
fn visit_null(&mut self, _: &DexNull) -> Result<()> {
Ok(())
}
fn visit_bool(&mut self, _: &DexBoolean) -> Result<()> {
Ok(())
}
}
pub trait VisitorMut: Sized {
@ -64,6 +100,42 @@ pub trait VisitorMut: Sized {
fn visit_call_site(&mut self, site: CallSite) -> Result<CallSite> {
site.default_visit_mut(self)
}
fn visit_value(&mut self, val: DexValue) -> Result<DexValue> {
val.default_visit_mut(self)
}
fn visit_byte(&mut self, val: DexByte) -> Result<DexByte> {
Ok(val)
}
fn visit_short(&mut self, val: DexShort) -> Result<DexShort> {
Ok(val)
}
fn visit_char(&mut self, val: DexChar) -> Result<DexChar> {
Ok(val)
}
fn visit_int(&mut self, val: DexInt) -> Result<DexInt> {
Ok(val)
}
fn visit_long(&mut self, val: DexLong) -> Result<DexLong> {
Ok(val)
}
fn visit_float(&mut self, val: DexFloat) -> Result<DexFloat> {
Ok(val)
}
fn visit_double(&mut self, val: DexDouble) -> Result<DexDouble> {
Ok(val)
}
fn visit_array(&mut self, val: DexArray) -> Result<DexArray> {
val.default_visit_mut(self)
}
fn visit_annotation(&mut self, val: DexAnnotation) -> Result<DexAnnotation> {
val.default_visit_mut(self)
}
fn visit_null(&mut self, val: DexNull) -> Result<DexNull> {
Ok(val)
}
fn visit_bool(&mut self, val: DexBoolean) -> Result<DexBoolean> {
Ok(val)
}
}
/// Trait for structures that can be visited.