catch when nb method ids > 2^16
This commit is contained in:
parent
0b430fe187
commit
ed8c584647
3 changed files with 89 additions and 32 deletions
|
|
@ -185,8 +185,6 @@ impl DexWriter {
|
||||||
.filter(|ty| self.type_ids.get(ty).is_none())
|
.filter(|ty| self.type_ids.get(ty).is_none())
|
||||||
.count();
|
.count();
|
||||||
if new_nb_types >= u16::MAX as usize {
|
if new_nb_types >= u16::MAX as usize {
|
||||||
// type_ids are not always u16, so this may not be a hard limit,
|
|
||||||
// but it's easier to enforce it to avoid strange bugs.
|
|
||||||
// TODO return structured error to handle this case by generating multiple dex files
|
// TODO return structured error to handle this case by generating multiple dex files
|
||||||
bail!("To many types for one dex file");
|
bail!("To many types for one dex file");
|
||||||
}
|
}
|
||||||
|
|
@ -203,8 +201,26 @@ impl DexWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_field_ids = class.get_all_field_ids();
|
let new_field_ids = class.get_all_field_ids();
|
||||||
|
let new_nb_field_ids = self.field_ids.len()
|
||||||
|
+ new_field_ids
|
||||||
|
.iter()
|
||||||
|
.filter(|field| self.field_ids.get(field).is_none())
|
||||||
|
.count();
|
||||||
|
if new_nb_field_ids >= u16::MAX as usize {
|
||||||
|
// TODO return structured error to handle this case by generating multiple dex files
|
||||||
|
bail!("To many field ids for one dex file");
|
||||||
|
}
|
||||||
|
|
||||||
let new_method_ids = class.get_all_method_ids();
|
let new_method_ids = class.get_all_method_ids();
|
||||||
|
let new_nb_method_ids = self.method_ids.len()
|
||||||
|
+ new_method_ids
|
||||||
|
.iter()
|
||||||
|
.filter(|meth| self.method_ids.get(meth).is_none())
|
||||||
|
.count();
|
||||||
|
if new_nb_method_ids >= u16::MAX as usize {
|
||||||
|
// TODO return structured error to handle this case by generating multiple dex files
|
||||||
|
bail!("To many method ids for one dex file");
|
||||||
|
}
|
||||||
|
|
||||||
for string in new_strings {
|
for string in new_strings {
|
||||||
self.strings.insert(string, 0);
|
self.strings.insert(string, 0);
|
||||||
|
|
@ -1161,7 +1177,12 @@ impl DexWriter {
|
||||||
meth.class_.__repr__(),
|
meth.class_.__repr__(),
|
||||||
method_id.__repr__()
|
method_id.__repr__()
|
||||||
))?;
|
))?;
|
||||||
let ins = ins.get_raw_ins(*meth_idx);
|
debug_assert!(
|
||||||
|
*meth_idx <= u16::MAX as usize,
|
||||||
|
"methode id too big for invoke instruction"
|
||||||
|
);
|
||||||
|
let meth_idx = *meth_idx as u16;
|
||||||
|
let ins = ins.get_raw_ins(meth_idx);
|
||||||
addr += ins.size() / 2;
|
addr += ins.size() / 2;
|
||||||
insns.push(ins);
|
insns.push(ins);
|
||||||
}
|
}
|
||||||
|
|
@ -1173,7 +1194,12 @@ impl DexWriter {
|
||||||
meth.class_.__repr__(),
|
meth.class_.__repr__(),
|
||||||
method_id.__repr__()
|
method_id.__repr__()
|
||||||
))?;
|
))?;
|
||||||
let ins = ins.get_raw_ins(*meth_idx);
|
debug_assert!(
|
||||||
|
*meth_idx <= u16::MAX as usize,
|
||||||
|
"methode id too big for invoke instruction"
|
||||||
|
);
|
||||||
|
let meth_idx = *meth_idx as u16;
|
||||||
|
let ins = ins.get_raw_ins(meth_idx);
|
||||||
addr += ins.size() / 2;
|
addr += ins.size() / 2;
|
||||||
insns.push(ins);
|
insns.push(ins);
|
||||||
}
|
}
|
||||||
|
|
@ -1185,7 +1211,12 @@ impl DexWriter {
|
||||||
meth.class_.__repr__(),
|
meth.class_.__repr__(),
|
||||||
method_id.__repr__()
|
method_id.__repr__()
|
||||||
))?;
|
))?;
|
||||||
let ins = ins.get_raw_ins(*meth_idx);
|
debug_assert!(
|
||||||
|
*meth_idx <= u16::MAX as usize,
|
||||||
|
"methode id too big for invoke instruction"
|
||||||
|
);
|
||||||
|
let meth_idx = *meth_idx as u16;
|
||||||
|
let ins = ins.get_raw_ins(meth_idx);
|
||||||
addr += ins.size() / 2;
|
addr += ins.size() / 2;
|
||||||
insns.push(ins);
|
insns.push(ins);
|
||||||
}
|
}
|
||||||
|
|
@ -1197,7 +1228,12 @@ impl DexWriter {
|
||||||
meth.class_.__repr__(),
|
meth.class_.__repr__(),
|
||||||
method_id.__repr__()
|
method_id.__repr__()
|
||||||
))?;
|
))?;
|
||||||
let ins = ins.get_raw_ins(*meth_idx);
|
debug_assert!(
|
||||||
|
*meth_idx <= u16::MAX as usize,
|
||||||
|
"methode id too big for invoke instruction"
|
||||||
|
);
|
||||||
|
let meth_idx = *meth_idx as u16;
|
||||||
|
let ins = ins.get_raw_ins(meth_idx);
|
||||||
addr += ins.size() / 2;
|
addr += ins.size() / 2;
|
||||||
insns.push(ins);
|
insns.push(ins);
|
||||||
}
|
}
|
||||||
|
|
@ -1209,7 +1245,12 @@ impl DexWriter {
|
||||||
meth.class_.__repr__(),
|
meth.class_.__repr__(),
|
||||||
method_id.__repr__()
|
method_id.__repr__()
|
||||||
))?;
|
))?;
|
||||||
let ins = ins.get_raw_ins(*meth_idx);
|
debug_assert!(
|
||||||
|
*meth_idx <= u16::MAX as usize,
|
||||||
|
"methode id too big for invoke instruction"
|
||||||
|
);
|
||||||
|
let meth_idx = *meth_idx as u16;
|
||||||
|
let ins = ins.get_raw_ins(meth_idx);
|
||||||
addr += ins.size() / 2;
|
addr += ins.size() / 2;
|
||||||
insns.push(ins);
|
insns.push(ins);
|
||||||
}
|
}
|
||||||
|
|
@ -1226,7 +1267,17 @@ impl DexWriter {
|
||||||
ins.proto.__repr__(),
|
ins.proto.__repr__(),
|
||||||
method_id.__repr__()
|
method_id.__repr__()
|
||||||
))?;
|
))?;
|
||||||
let ins = ins.get_raw_ins(*meth_idx, *proto_idx);
|
debug_assert!(
|
||||||
|
*meth_idx <= u16::MAX as usize,
|
||||||
|
"methode id too big for invoke instruction"
|
||||||
|
);
|
||||||
|
debug_assert!(
|
||||||
|
*proto_idx <= u16::MAX as usize,
|
||||||
|
"proto id too big for invoke instruction"
|
||||||
|
);
|
||||||
|
let meth_idx = *meth_idx as u16;
|
||||||
|
let proto_idx = *proto_idx as u16;
|
||||||
|
let ins = ins.get_raw_ins(meth_idx, proto_idx);
|
||||||
addr += ins.size() / 2;
|
addr += ins.size() / 2;
|
||||||
insns.push(ins);
|
insns.push(ins);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14863,7 +14863,7 @@ impl InvokeVirtual {
|
||||||
/// Return the raw instruction ([`InsFormat`]).
|
/// Return the raw instruction ([`InsFormat`]).
|
||||||
///
|
///
|
||||||
/// `method_idx` is the index of the refered method.
|
/// `method_idx` is the index of the refered method.
|
||||||
pub fn get_raw_ins(&self, meth_idx: usize) -> InsFormat {
|
pub fn get_raw_ins(&self, meth_idx: u16) -> InsFormat {
|
||||||
let mut last = None;
|
let mut last = None;
|
||||||
let mut first = None;
|
let mut first = None;
|
||||||
let mut consec = true;
|
let mut consec = true;
|
||||||
|
|
@ -14916,7 +14916,7 @@ impl InvokeVirtual {
|
||||||
op: 0x74,
|
op: 0x74,
|
||||||
a,
|
a,
|
||||||
vc,
|
vc,
|
||||||
b: meth_idx as u16,
|
b: meth_idx,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not supposed to happend with a sanitized invoke
|
// Not supposed to happend with a sanitized invoke
|
||||||
|
|
@ -15083,7 +15083,7 @@ impl InvokeSuper {
|
||||||
/// Return the raw instruction ([`InsFormat`]).
|
/// Return the raw instruction ([`InsFormat`]).
|
||||||
///
|
///
|
||||||
/// `method_idx` is the index of the refered method.
|
/// `method_idx` is the index of the refered method.
|
||||||
pub fn get_raw_ins(&self, meth_idx: usize) -> InsFormat {
|
pub fn get_raw_ins(&self, meth_idx: u16) -> InsFormat {
|
||||||
let mut last = None;
|
let mut last = None;
|
||||||
let mut first = None;
|
let mut first = None;
|
||||||
let mut consec = true;
|
let mut consec = true;
|
||||||
|
|
@ -15127,7 +15127,7 @@ impl InvokeSuper {
|
||||||
vd,
|
vd,
|
||||||
vf,
|
vf,
|
||||||
vg,
|
vg,
|
||||||
b: meth_idx as u16,
|
b: meth_idx,
|
||||||
}
|
}
|
||||||
} else if consec && len <= 255 {
|
} else if consec && len <= 255 {
|
||||||
let a = self.args.len() as u8;
|
let a = self.args.len() as u8;
|
||||||
|
|
@ -15136,7 +15136,7 @@ impl InvokeSuper {
|
||||||
op: 0x75,
|
op: 0x75,
|
||||||
a,
|
a,
|
||||||
vc,
|
vc,
|
||||||
b: meth_idx as u16,
|
b: meth_idx,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not supposed to happend with a sanitized invoke
|
// Not supposed to happend with a sanitized invoke
|
||||||
|
|
@ -15303,7 +15303,7 @@ impl InvokeDirect {
|
||||||
/// Return the raw instruction ([`InsFormat`]).
|
/// Return the raw instruction ([`InsFormat`]).
|
||||||
///
|
///
|
||||||
/// `method_idx` is the index of the refered method.
|
/// `method_idx` is the index of the refered method.
|
||||||
pub fn get_raw_ins(&self, meth_idx: usize) -> InsFormat {
|
pub fn get_raw_ins(&self, meth_idx: u16) -> InsFormat {
|
||||||
let mut last = None;
|
let mut last = None;
|
||||||
let mut first = None;
|
let mut first = None;
|
||||||
let mut consec = true;
|
let mut consec = true;
|
||||||
|
|
@ -15347,7 +15347,7 @@ impl InvokeDirect {
|
||||||
vd,
|
vd,
|
||||||
vf,
|
vf,
|
||||||
vg,
|
vg,
|
||||||
b: meth_idx as u16,
|
b: meth_idx,
|
||||||
}
|
}
|
||||||
} else if consec && len <= 255 {
|
} else if consec && len <= 255 {
|
||||||
let a = self.args.len() as u8;
|
let a = self.args.len() as u8;
|
||||||
|
|
@ -15356,7 +15356,7 @@ impl InvokeDirect {
|
||||||
op: 0x76,
|
op: 0x76,
|
||||||
a,
|
a,
|
||||||
vc,
|
vc,
|
||||||
b: meth_idx as u16,
|
b: meth_idx,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not supposed to happend with a sanitized invoke
|
// Not supposed to happend with a sanitized invoke
|
||||||
|
|
@ -15523,7 +15523,7 @@ impl InvokeStatic {
|
||||||
/// Return the raw instruction ([`InsFormat`]).
|
/// Return the raw instruction ([`InsFormat`]).
|
||||||
///
|
///
|
||||||
/// `method_idx` is the index of the refered method.
|
/// `method_idx` is the index of the refered method.
|
||||||
pub fn get_raw_ins(&self, meth_idx: usize) -> InsFormat {
|
pub fn get_raw_ins(&self, meth_idx: u16) -> InsFormat {
|
||||||
let mut last = None;
|
let mut last = None;
|
||||||
let mut first = None;
|
let mut first = None;
|
||||||
let mut consec = true;
|
let mut consec = true;
|
||||||
|
|
@ -15567,7 +15567,7 @@ impl InvokeStatic {
|
||||||
vd,
|
vd,
|
||||||
vf,
|
vf,
|
||||||
vg,
|
vg,
|
||||||
b: meth_idx as u16,
|
b: meth_idx,
|
||||||
}
|
}
|
||||||
} else if consec && len <= 255 {
|
} else if consec && len <= 255 {
|
||||||
let a = self.args.len() as u8;
|
let a = self.args.len() as u8;
|
||||||
|
|
@ -15576,7 +15576,7 @@ impl InvokeStatic {
|
||||||
op: 0x77,
|
op: 0x77,
|
||||||
a,
|
a,
|
||||||
vc,
|
vc,
|
||||||
b: meth_idx as u16,
|
b: meth_idx,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not supposed to happend with a sanitized invoke
|
// Not supposed to happend with a sanitized invoke
|
||||||
|
|
@ -15743,7 +15743,7 @@ impl InvokeInterface {
|
||||||
/// Return the raw instruction ([`InsFormat`]).
|
/// Return the raw instruction ([`InsFormat`]).
|
||||||
///
|
///
|
||||||
/// `method_idx` is the index of the refered method.
|
/// `method_idx` is the index of the refered method.
|
||||||
pub fn get_raw_ins(&self, meth_idx: usize) -> InsFormat {
|
pub fn get_raw_ins(&self, meth_idx: u16) -> InsFormat {
|
||||||
let mut last = None;
|
let mut last = None;
|
||||||
let mut first = None;
|
let mut first = None;
|
||||||
let mut consec = true;
|
let mut consec = true;
|
||||||
|
|
@ -15787,7 +15787,7 @@ impl InvokeInterface {
|
||||||
vd,
|
vd,
|
||||||
vf,
|
vf,
|
||||||
vg,
|
vg,
|
||||||
b: meth_idx as u16,
|
b: meth_idx,
|
||||||
}
|
}
|
||||||
} else if consec && len <= 255 {
|
} else if consec && len <= 255 {
|
||||||
let a = self.args.len() as u8;
|
let a = self.args.len() as u8;
|
||||||
|
|
@ -15796,7 +15796,7 @@ impl InvokeInterface {
|
||||||
op: 0x78,
|
op: 0x78,
|
||||||
a,
|
a,
|
||||||
vc,
|
vc,
|
||||||
b: meth_idx as u16,
|
b: meth_idx,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not supposed to happend with a sanitized invoke
|
// Not supposed to happend with a sanitized invoke
|
||||||
|
|
@ -28356,7 +28356,7 @@ impl InvokePolymorphic {
|
||||||
///
|
///
|
||||||
/// - `method_idx` is the index of the refered method.
|
/// - `method_idx` is the index of the refered method.
|
||||||
/// - `proto_idx` is the index of the protoype used.
|
/// - `proto_idx` is the index of the protoype used.
|
||||||
pub fn get_raw_ins(&self, meth_idx: usize, proto_idx: usize) -> InsFormat {
|
pub fn get_raw_ins(&self, meth_idx: u16, proto_idx: u16) -> InsFormat {
|
||||||
let mut last = None;
|
let mut last = None;
|
||||||
let mut first = None;
|
let mut first = None;
|
||||||
let mut consec = true;
|
let mut consec = true;
|
||||||
|
|
@ -28400,8 +28400,8 @@ impl InvokePolymorphic {
|
||||||
vd,
|
vd,
|
||||||
vf,
|
vf,
|
||||||
vg,
|
vg,
|
||||||
b: meth_idx as u16,
|
b: meth_idx,
|
||||||
h: proto_idx as u16,
|
h: proto_idx,
|
||||||
}
|
}
|
||||||
} else if consec && len <= 255 {
|
} else if consec && len <= 255 {
|
||||||
let a = self.args.len() as u8;
|
let a = self.args.len() as u8;
|
||||||
|
|
@ -28410,8 +28410,8 @@ impl InvokePolymorphic {
|
||||||
op: 0xfb,
|
op: 0xfb,
|
||||||
a,
|
a,
|
||||||
vc,
|
vc,
|
||||||
b: meth_idx as u16,
|
b: meth_idx,
|
||||||
h: proto_idx as u16,
|
h: proto_idx,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Not supposed to happend with a sanitized invoke
|
// Not supposed to happend with a sanitized invoke
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ import logging
|
||||||
|
|
||||||
FORMAT = "[%(levelname)s] %(name)s %(filename)s:%(lineno)d: %(message)s"
|
FORMAT = "[%(levelname)s] %(name)s %(filename)s:%(lineno)d: %(message)s"
|
||||||
logging.basicConfig(format=FORMAT)
|
logging.basicConfig(format=FORMAT)
|
||||||
logging.getLogger().setLevel(logging.DEBUG)
|
# logging.getLogger().setLevel(logging.DEBUG)
|
||||||
|
logging.getLogger().setLevel(logging.WARNING)
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import zipfile as z
|
import zipfile as z
|
||||||
|
|
@ -207,8 +208,8 @@ def cmp_other(a, b, req=0):
|
||||||
len(f) < 2 or f[:2] != "__"
|
len(f) < 2 or f[:2] != "__"
|
||||||
):
|
):
|
||||||
eq = getattr(a, f) == getattr(b, f)
|
eq = getattr(a, f) == getattr(b, f)
|
||||||
|
print(f"{f'{ident}{f}: ':<150}{nice_bool(eq)}")
|
||||||
if not eq:
|
if not eq:
|
||||||
print(f"{f'{ident}{f}: ':<150}{nice_bool(eq)}")
|
|
||||||
if "descriptor" in dir(a):
|
if "descriptor" in dir(a):
|
||||||
global last_id
|
global last_id
|
||||||
last_id = a.descriptor
|
last_id = a.descriptor
|
||||||
|
|
@ -227,8 +228,8 @@ def cmp_dict(a, b, req=0):
|
||||||
eq = a[key] == b[key]
|
eq = a[key] == b[key]
|
||||||
tot += 1
|
tot += 1
|
||||||
if not eq:
|
if not eq:
|
||||||
nb_failed += 1
|
|
||||||
print(f"{f'{ident}{str(key)}: ':<150}{nice_bool(eq)}")
|
print(f"{f'{ident}{str(key)}: ':<150}{nice_bool(eq)}")
|
||||||
|
nb_failed += 1
|
||||||
global last_id
|
global last_id
|
||||||
last_id = key
|
last_id = key
|
||||||
cmp(a[key], b[key], req + 1)
|
cmp(a[key], b[key], req + 1)
|
||||||
|
|
@ -243,8 +244,8 @@ def cmp_list(a, b, req=0):
|
||||||
print(f"{ident}len(a) != len(b)")
|
print(f"{ident}len(a) != len(b)")
|
||||||
for i in range(min(la, lb)):
|
for i in range(min(la, lb)):
|
||||||
eq = a[i] == b[i]
|
eq = a[i] == b[i]
|
||||||
|
print(f"{f'{ident}{str(i)}: ':<150}{nice_bool(eq)}")
|
||||||
if not eq:
|
if not eq:
|
||||||
print(f"{f'{ident}{str(i)}: ':<150}{nice_bool(eq)}")
|
|
||||||
print(f"{ident}: {str(a[i])} != {str(b[i])}")
|
print(f"{ident}: {str(a[i])} != {str(b[i])}")
|
||||||
cmp(a[i], b[i], req + 1)
|
cmp(a[i], b[i], req + 1)
|
||||||
|
|
||||||
|
|
@ -252,7 +253,9 @@ def cmp_list(a, b, req=0):
|
||||||
instrumented_apk = Apk()
|
instrumented_apk = Apk()
|
||||||
instrumented_apk.add_dex_file(dex_raw[0])
|
instrumented_apk.add_dex_file(dex_raw[0])
|
||||||
|
|
||||||
cmp(instrumented_apk, dyn_load_apk)
|
print("wtf?")
|
||||||
|
|
||||||
|
# cmp(instrumented_apk, dyn_load_apk)
|
||||||
|
|
||||||
MAX_REQ = 5
|
MAX_REQ = 5
|
||||||
|
|
||||||
|
|
@ -330,3 +333,6 @@ for ty in tys:
|
||||||
instrumented_apk.classes[ty],
|
instrumented_apk.classes[ty],
|
||||||
dyn_load_apk.classes[ty],
|
dyn_load_apk.classes[ty],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# direct: Landroidx/compose/foundation/layout/IntrinsicSize;->values()[Landroidx/compose/foundation/layout/IntrinsicSize;
|
||||||
|
# insns[3]: Landroidx/compose/foundation/layout/IntrinsicSize;->values()[Landroidx/compose/foundation/layout/IntrinsicSize;:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue