add encoded scalar values

This commit is contained in:
Jean-Marie Mineau 2023-08-24 18:51:06 +02:00
parent 49d6094d6f
commit 6020b173a0
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
4 changed files with 713 additions and 0 deletions

View file

@ -0,0 +1,18 @@
use crate::{ReadSeek, Result, Serializable};
use std::io::Write;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EncodedAnnotation;
impl Serializable for EncodedAnnotation {
fn serialize(&self, _output: &mut dyn Write) -> Result<()> {
todo!()
}
fn deserialize(_input: &mut dyn ReadSeek) -> Result<Self> {
todo!()
}
fn size(&self) -> usize {
todo!()
}
}

View file

@ -0,0 +1,18 @@
use crate::{ReadSeek, Result, Serializable};
use std::io::Write;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EncodedArray;
impl Serializable for EncodedArray {
fn serialize(&self, _output: &mut dyn Write) -> Result<()> {
todo!()
}
fn deserialize(_input: &mut dyn ReadSeek) -> Result<Self> {
todo!()
}
fn size(&self) -> usize {
todo!()
}
}

View file

@ -1,7 +1,13 @@
pub mod annotation;
pub mod array;
pub mod constant;
pub mod core;
pub mod value;
pub use androscalpel_serializer_derive::*;
pub use crate::core::*;
pub use annotation::*;
pub use array::*;
pub use constant::*;
pub use value::*;

View file

@ -0,0 +1,671 @@
//! The encoded value format: https://source.android.com/docs/core/runtime/dex-format#encoding
use crate::{EncodedAnnotation, EncodedArray, Error, ReadSeek, Result, Serializable};
use std::io::Write;
// TODO: TESTS!!!
/// An encoded value of arbitrary hierachically structured data:
/// https://source.android.com/docs/core/runtime/dex-format#encoding
#[derive(Debug, Clone)]
pub enum EncodedValue {
Byte(i8),
Short(i16),
Char(u16),
Int(i32),
Long(i64),
Float(f32),
Double(f64),
MethodType(u32),
MethodHandle(u32),
String(u32),
Type(u32),
Field(u32),
Method(u32),
Enum(u32),
Array(EncodedArray),
Annotation(EncodedAnnotation),
Null,
Boolean(bool),
}
/// The id of a type used by a value.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
struct ValueType(u8);
const VALUE_BYTE: ValueType = ValueType(0x00);
const VALUE_SHORT: ValueType = ValueType(0x02);
const VALUE_CHAR: ValueType = ValueType(0x03);
const VALUE_INT: ValueType = ValueType(0x04);
const VALUE_LONG: ValueType = ValueType(0x06);
const VALUE_FLOAT: ValueType = ValueType(0x10);
const VALUE_DOUBLE: ValueType = ValueType(0x11);
const VALUE_METHOD_TYPE: ValueType = ValueType(0x15);
const VALUE_METHOD_HANDLE: ValueType = ValueType(0x16);
const VALUE_STRING: ValueType = ValueType(0x17);
const VALUE_TYPE: ValueType = ValueType(0x18);
const VALUE_FIELD: ValueType = ValueType(0x19);
const VALUE_METHOD: ValueType = ValueType(0x1a);
const VALUE_ENUM: ValueType = ValueType(0x1b);
const VALUE_ARRAY: ValueType = ValueType(0x1c);
const VALUE_ANNOTATION: ValueType = ValueType(0x1d);
const VALUE_NULL: ValueType = ValueType(0x1e);
const VALUE_BOOLEAN: ValueType = ValueType(0x1f);
impl PartialEq for EncodedValue {
fn eq(&self, item: &Self) -> bool {
match (self, item) {
(Self::Byte(val1), Self::Byte(val2)) => val1 == val2,
(Self::Short(val1), Self::Short(val2)) => val1 == val2,
(Self::Char(val1), Self::Char(val2)) => val1 == val2,
(Self::Int(val1), Self::Int(val2)) => val1 == val2,
(Self::Long(val1), Self::Long(val2)) => val1 == val2,
(Self::Float(val1), Self::Float(val2)) => val1.to_be_bytes() == val2.to_be_bytes(),
(Self::Double(val1), Self::Double(val2)) => val1.to_be_bytes() == val2.to_be_bytes(),
(Self::MethodType(val1), Self::MethodType(val2)) => val1 == val2,
(Self::MethodHandle(val1), Self::MethodHandle(val2)) => val1 == val2,
(Self::String(val1), Self::String(val2)) => val1 == val2,
(Self::Type(val1), Self::Type(val2)) => val1 == val2,
(Self::Field(val1), Self::Field(val2)) => val1 == val2,
(Self::Method(val1), Self::Method(val2)) => val1 == val2,
(Self::Enum(val1), Self::Enum(val2)) => val1 == val2,
(Self::Array(val1), Self::Array(val2)) => val1 == val2,
(Self::Annotation(val1), Self::Annotation(val2)) => val1 == val2,
(Self::Null, Self::Null) => true,
(Self::Boolean(val1), Self::Boolean(val2)) => val1 == val2,
_ => false,
}
}
}
impl Eq for EncodedValue {}
impl Serializable for EncodedValue {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
match self {
Self::Byte(byte) => {
let bytes = byte.to_be_bytes();
output.write_all(&[VALUE_BYTE.0]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Byte to output: {err}"
))
})?;
output.write_all(&bytes).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Byte to output: {err}"
))
})?;
Ok(())
}
Self::Short(val) => {
let size = self.size();
let bytes: [u8; 2] = val.to_be_bytes();
output
.write_all(&[((size as u8 - 2) << 5) | VALUE_SHORT.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Short to output: {err}"
))
})?;
output.write_all(&bytes[(2 - size + 1)..]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Short to output: {err}"
))
})?;
Ok(())
}
Self::Char(val) => {
let size = self.size();
let bytes: [u8; 2] = val.to_be_bytes();
output
.write_all(&[((size as u8 - 2) << 5) | VALUE_CHAR.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Char to output: {err}"
))
})?;
output.write_all(&bytes[(2 - size + 1)..]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Char to output: {err}"
))
})?;
Ok(())
}
Self::Int(val) => {
let size = self.size();
let bytes: [u8; 4] = val.to_be_bytes();
output
.write_all(&[((size as u8 - 2) << 5) | VALUE_INT.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Int to output: {err}"
))
})?;
output.write_all(&bytes[(2 - size + 1)..]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Int to output: {err}"
))
})?;
Ok(())
}
Self::Long(val) => {
let size = self.size();
let bytes: [u8; 8] = val.to_be_bytes();
output
.write_all(&[((size as u8 - 2) << 5) | VALUE_LONG.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Long to output: {err}"
))
})?;
output.write_all(&bytes[(2 - size + 1)..]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Long to output: {err}"
))
})?;
Ok(())
}
Self::Float(val) => {
let size = self.size();
let bytes = val.to_be_bytes();
output
.write_all(&[((size as u8 - 2) << 5) | VALUE_FLOAT.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Float to output: {err}"
))
})?;
output.write_all(&bytes[..(size - 1)]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Float to output: {err}"
))
})?;
Ok(())
}
Self::Double(val) => {
let size = self.size();
let bytes = val.to_be_bytes();
output
.write_all(&[((size as u8 - 2) << 5) | VALUE_DOUBLE.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Double to output: {err}"
))
})?;
output.write_all(&bytes[..(size - 1)]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Double to output: {err}"
))
})?;
Ok(())
}
Self::MethodType(idx) => Idx(*idx, VALUE_METHOD_TYPE).serialize(output),
Self::MethodHandle(idx) => Idx(*idx, VALUE_METHOD_HANDLE).serialize(output),
Self::String(idx) => Idx(*idx, VALUE_STRING).serialize(output),
Self::Type(idx) => Idx(*idx, VALUE_TYPE).serialize(output),
Self::Field(idx) => Idx(*idx, VALUE_FIELD).serialize(output),
Self::Method(idx) => Idx(*idx, VALUE_METHOD).serialize(output),
Self::Enum(idx) => Idx(*idx, VALUE_ENUM).serialize(output),
Self::Array(arr) => {
output.write_all(&[VALUE_ARRAY.0]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Array to output: {err}"
))
})?;
arr.serialize(output)
}
Self::Annotation(ann) => {
output.write_all(&[VALUE_ANNOTATION.0]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Annotation to output: {err}"
))
})?;
ann.serialize(output)
}
Self::Null => {
output.write_all(&[VALUE_NULL.0]).map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Null to output: {err}"
))
})?;
Ok(())
}
Self::Boolean(b) => {
let val = if *b { 1 } else { 0 };
output
.write_all(&[(val << 5) | VALUE_BOOLEAN.0])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Bool to output: {err}"
))
})?;
Ok(())
}
}
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let mut buffer = [0u8; 1];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue from the input".into(),
)
})?;
let [byte] = buffer;
let arg = (byte & 0b1110_0000) >> 5;
match ValueType(byte & 0b0011_1111) {
VALUE_BYTE => {
if arg != 0 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 for VALUE_BYTE"
)))
} else {
let mut buffer = [0u8; 1];
input.read_exact(&mut buffer).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Byte) from the input"
.into(),
)
})?;
Ok(Self::Byte(i8::from_be_bytes(buffer)))
}
}
VALUE_SHORT => {
if arg >= 2 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 or 1 for VALUE_SHORT"
)))
} else {
let mut buffer = [0x00u8; 2];
let size = (arg + 1) as usize;
let first_byte = 2 - size;
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Short) from the input"
.into(),
)
})?;
// Sign extention
if (buffer[first_byte] & 0b1000_0000) != 0 {
for b in buffer.iter_mut().take(first_byte - 1) {
*b = 0xff;
}
}
Ok(Self::Short(i16::from_be_bytes(buffer)))
}
}
VALUE_CHAR => {
if arg >= 2 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 or 1 for VALUE_CHAR"
)))
} else {
let mut buffer = [0x00u8; 2];
let size = (arg + 1) as usize;
let first_byte = 2 - size;
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Char) from the input"
.into(),
)
})?;
Ok(Self::Char(u16::from_be_bytes(buffer)))
}
}
VALUE_INT => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_INT"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
let first_byte = 4 - size;
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Int) from the input"
.into(),
)
})?;
// Sign extention
if (buffer[first_byte] & 0b1000_0000) != 0 {
for b in buffer.iter_mut().take(first_byte - 1) {
*b = 0xff;
}
}
Ok(Self::Int(i32::from_be_bytes(buffer)))
}
}
VALUE_LONG => {
if arg >= 8 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 to 7 for VALUE_LONG"
)))
} else {
let mut buffer = [0x00u8; 8];
let size = (arg + 1) as usize;
let first_byte = 8 - size;
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Long) from the input"
.into(),
)
})?;
// Sign extention
if (buffer[first_byte] & 0b1000_0000) != 0 {
for b in buffer.iter_mut().take(first_byte - 1) {
*b = 0xff;
}
}
Ok(Self::Long(i64::from_be_bytes(buffer)))
}
}
VALUE_FLOAT => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_FLOAT"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Float) from the input"
.into(),
)
})?;
Ok(Self::Float(f32::from_be_bytes(buffer)))
}
}
VALUE_DOUBLE => {
if arg >= 8 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 to 7 for VALUE_DOUBLE"
)))
} else {
let mut buffer = [0x00u8; 8];
let size = (arg + 1) as usize;
input.read_exact(&mut buffer[..size]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Double) from the input"
.into(),
)
})?;
Ok(Self::Double(f64::from_be_bytes(buffer)))
}
}
VALUE_METHOD_TYPE => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_METHOD_TYPE"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
let first_byte = 4 - size;
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (MethodType) from the input"
.into(),
)
})?;
Ok(Self::MethodType(u32::from_be_bytes(buffer)))
}
}
VALUE_METHOD_HANDLE => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_METHOD_HANDLE"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
let first_byte = 4 - size;
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (MethodHandle) from the input"
.into(),
)
})?;
Ok(Self::MethodHandle(u32::from_be_bytes(buffer)))
}
}
VALUE_STRING => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_STRING"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
let first_byte = 4 - size;
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (String) from the input"
.into(),
)
})?;
Ok(Self::String(u32::from_be_bytes(buffer)))
}
}
VALUE_TYPE => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_TYPE"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
let first_byte = 4 - size;
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Type) from the input"
.into(),
)
})?;
Ok(Self::Type(u32::from_be_bytes(buffer)))
}
}
VALUE_FIELD => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_FIELD"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
let first_byte = 4 - size;
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Field) from the input"
.into(),
)
})?;
Ok(Self::Field(u32::from_be_bytes(buffer)))
}
}
VALUE_METHOD => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_METHOD"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
let first_byte = 4 - size;
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Method) from the input"
.into(),
)
})?;
Ok(Self::Method(u32::from_be_bytes(buffer)))
}
}
VALUE_ENUM => {
if arg >= 4 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0, 1, 2 or 3 for VALUE_ENUM"
)))
} else {
let mut buffer = [0x00u8; 4];
let size = (arg + 1) as usize;
let first_byte = 4 - size;
input.read_exact(&mut buffer[first_byte..]).map_err(|_| {
Error::InputTooSmall(
"Failed to read all bytes for the EncodedValue (Enum) from the input"
.into(),
)
})?;
Ok(Self::Enum(u32::from_be_bytes(buffer)))
}
}
VALUE_ARRAY => {
if arg != 0 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 for VALUE_ARRAY"
)))
} else {
Ok(Self::Array(EncodedArray::deserialize(input)?))
}
}
VALUE_ANNOTATION => {
if arg != 0 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 for VALUE_ANNOTATION"
)))
} else {
Ok(Self::Array(EncodedArray::deserialize(input)?))
}
}
VALUE_NULL => {
if arg != 0 {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 for VALUE_NULL"
)))
} else {
Ok(Self::Null)
}
}
VALUE_BOOLEAN => {
if arg == 0 {
Ok(Self::Boolean(false))
} else if arg == 1 {
Ok(Self::Boolean(true))
} else {
Err(Error::DeserializationError(format!(
"Unexpected value argument 0x{arg:02x}: expected 0 or 1 for VALUE_BOOLEAN"
)))
}
}
ValueType(vt) => Err(Error::DeserializationError(format!(
"Unknown Value Type: 0x{vt:02x}"
))),
}
}
fn size(&self) -> usize {
match self {
Self::Byte(_) => 2,
Self::Short(val) => 1 + if *val <= 0x7f && *val >= -0x80 { 1 } else { 2 },
Self::Char(val) => 1 + if *val <= 0xff { 1 } else { 2 },
Self::Int(val) => {
1 + if *val <= 0x7f && *val >= -0x80 {
1
} else if *val <= 0x7f_ff && *val >= -0x80_00 {
2
} else if *val <= 0x7f_ff_ff && *val >= -0x80_00_00 {
3
} else {
4
}
}
Self::Long(val) => {
1 + if *val <= 0x7f && *val >= -0x80 {
1
} else if *val <= 0x7f_ff && *val >= -0x80_00 {
2
} else if *val <= 0x7f_ff_ff && *val >= -0x80_00_00 {
3
} else if *val <= 0x7f_ff_ff_ff && *val >= -0x80_00_00_00 {
4
} else if *val <= 0x7f_ff_ff_ff_ff && *val >= -0x80_00_00_00_00 {
5
} else if *val <= 0x7f_ff_ff_ff_ff_ff && *val >= -0x80_00_00_00_00_00 {
6
} else if *val <= 0x7f_ff_ff_ff_ff_ff_ff && *val >= -0x80_00_00_00_00_00 {
7
} else {
8
}
}
Self::Float(val) => {
let trailing_zeros = val
.to_be_bytes()
.iter()
.rev()
.take_while(|b| **b == 0)
.count();
1 + 4 - trailing_zeros
}
Self::Double(val) => {
let trailing_zeros = val
.to_be_bytes()
.iter()
.rev()
.take_while(|b| **b == 0)
.count();
1 + 8 - trailing_zeros
}
Self::MethodType(idx) => Idx(*idx, VALUE_TYPE).size(),
Self::MethodHandle(idx) => Idx(*idx, VALUE_METHOD_HANDLE).size(),
Self::String(idx) => Idx(*idx, VALUE_STRING).size(),
Self::Type(idx) => Idx(*idx, VALUE_TYPE).size(),
Self::Field(idx) => Idx(*idx, VALUE_FIELD).size(),
Self::Method(idx) => Idx(*idx, VALUE_METHOD).size(),
Self::Enum(idx) => Idx(*idx, VALUE_ENUM).size(),
Self::Array(arr) => 1 + arr.size(),
Self::Annotation(ann) => 1 + ann.size(),
Self::Null => 1,
Self::Boolean(_) => 1,
}
}
}
/// Utility type to encode/decode an Idx.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
struct Idx(u32, ValueType);
impl Serializable for Idx {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
let Idx(idx, ValueType(vt)) = self;
let size = self.size() - 2;
let bytes: [u8; 4] = idx.to_be_bytes();
let vec = &bytes[(4 - size + 1)..];
output
.write_all(&[((size as u8) << 5) | vt])
.map_err(|err| {
Error::SerializationError(format!(
"Failed to write serialized Idx to output: {err}"
))
})?;
output.write_all(vec).map_err(|err| {
Error::SerializationError(format!("Failed to write serialized Idx to output: {err}"))
})?;
Ok(())
}
/// unimplemented, not used because the ValueType must be known before deserializing the idx.
fn deserialize(_input: &mut dyn ReadSeek) -> Result<Self> {
unimplemented!()
}
fn size(&self) -> usize {
let Idx(idx, _) = *self;
1 + if idx <= 0xff {
1
} else if idx <= 0xffff {
2
} else if idx <= 0xffffff {
3
} else {
4
}
}
}