Skip to content

Commit e8ccad2

Browse files
authored
Merge pull request #18 from LLeavesG/fix/control-flow-boundary-identity
Preserve control-flow boundary identities across monitors, phis, and aliases
2 parents 61a5c8e + d52c4f3 commit e8ccad2

15 files changed

Lines changed: 1086 additions & 108 deletions

File tree

dexdec/src/analysis/java_backend/declaration_lowering.rs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,19 @@ impl<'a> JavaTypeLowering<'a> {
10211021
let signature = declaration.signature.as_ref();
10221022
let annotations = self.method_annotations(declaration)?;
10231023
let mut name_scope = crate::language::java::JavaNameScope::default();
1024+
let reserved_type_qualifiers = method
1025+
.body
1026+
.as_ref()
1027+
.into_iter()
1028+
.flat_map(super::java_model::method::JavaMethodBody::static_owner_types)
1029+
.map(|owner| self.names.resolve_type(&owner))
1030+
.collect::<Result<Vec<_>, _>>()?
1031+
.iter()
1032+
.filter_map(source_type_qualifier)
1033+
.collect::<std::collections::BTreeSet<_>>();
1034+
for qualifier in &reserved_type_qualifiers {
1035+
name_scope.reserve(qualifier.clone());
1036+
}
10241037
let parameter_naming = super::semantic_naming::ParameterNameRecovery::new(self.names);
10251038
let mut visible_parameter = 0usize;
10261039
let parameter_names = declaration
@@ -1166,12 +1179,17 @@ impl<'a> JavaTypeLowering<'a> {
11661179
source_type_bounds.clone(),
11671180
generic_throw_types.clone(),
11681181
outer_instances,
1169-
declaration
1170-
.kind
1171-
.is_class_initializer()
1172-
.then(|| owner.map(|owner| self.members.field_names(owner)))
1173-
.flatten()
1174-
.unwrap_or_default(),
1182+
{
1183+
let mut reserved = reserved_type_qualifiers.clone();
1184+
if declaration.kind.is_class_initializer() {
1185+
reserved.extend(
1186+
owner
1187+
.map(|owner| self.members.field_names(owner))
1188+
.unwrap_or_default(),
1189+
);
1190+
}
1191+
reserved
1192+
},
11751193
declaration.kind.is_class_initializer(),
11761194
self.observer.clone(),
11771195
)
@@ -1692,6 +1710,16 @@ fn type_kind(kind: JavaClassKind) -> JavaTypeDeclarationKind {
16921710
}
16931711
}
16941712

1713+
/// The first source component is the expression qualifier that a static
1714+
/// member access must keep visible. Reserving it prevents a local binding from
1715+
/// turning `Owner.field` into an access through an unrelated local variable.
1716+
fn source_type_qualifier(ty: &JavaType) -> Option<JavaIdentifier> {
1717+
let JavaType::Class(class) = ty else {
1718+
return None;
1719+
};
1720+
class.segments.first().map(|segment| segment.name.clone())
1721+
}
1722+
16951723
fn method_kind(kind: MethodModelKind) -> JavaMethodDeclarationKind {
16961724
match kind {
16971725
MethodModelKind::Method => JavaMethodDeclarationKind::Method,
@@ -1706,6 +1734,19 @@ mod tests {
17061734
use crate::ir::generic_types::GenericSignatures;
17071735
use crate::language::java::GenericTypeProjection;
17081736

1737+
#[test]
1738+
fn static_type_qualifier_is_reserved_from_local_names() {
1739+
let owner = JavaType::source_class("a");
1740+
let owner = source_type_qualifier(&owner).expect("owner qualifier");
1741+
let mut names = crate::language::java::JavaNameScope::default();
1742+
names.reserve(owner);
1743+
1744+
assert_eq!(
1745+
names.claim(JavaIdentifier::from_dex("a")),
1746+
JavaIdentifier::from_dex("a2")
1747+
);
1748+
}
1749+
17091750
#[test]
17101751
fn merged_throwable_rethrow_uses_generic_cast_but_catch_parameter_does_not() {
17111752
let throwable = JavaType::source_class("Throwable");

dexdec/src/analysis/java_backend/java_model/method.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,14 @@ impl JavaMethodBody {
150150
collector.fields
151151
}
152152

153+
pub(in crate::analysis::java_backend) fn static_owner_types(
154+
&self,
155+
) -> std::collections::BTreeSet<ArgType> {
156+
let mut collector = MemberReferenceCollector::default();
157+
crate::ir::SemanticVisitor::visit_node(&mut collector, self.semantic.body());
158+
collector.static_owners
159+
}
160+
153161
pub(in crate::analysis::java_backend) fn outer_instance_field(
154162
&self,
155163
) -> Option<(&crate::ir::FieldReference, &ArgType)> {
@@ -356,15 +364,25 @@ impl JavaMethodBody {
356364
struct MemberReferenceCollector {
357365
methods: std::collections::BTreeSet<crate::ir::MethodReference>,
358366
fields: std::collections::BTreeSet<crate::ir::FieldReference>,
367+
static_owners: std::collections::BTreeSet<ArgType>,
359368
}
360369

361370
impl crate::ir::SemanticVisitor for MemberReferenceCollector {
362371
fn enter_operation(&mut self, operation: &crate::ir::SemanticOperation) {
363372
match operation.payload.reference.as_ref() {
364373
Some(crate::ir::MemberReference::Method(method)) => {
374+
if operation.payload.invoke_type == Some(crate::ir::InvokeType::Static) {
375+
self.static_owners.insert(method.owner.clone());
376+
}
365377
self.methods.insert(method.clone());
366378
}
367379
Some(crate::ir::MemberReference::Field(field)) => {
380+
if matches!(
381+
operation.insn_type,
382+
crate::ir::InsnType::Sget | crate::ir::InsnType::Sput
383+
) {
384+
self.static_owners.insert(field.owner.clone());
385+
}
368386
self.fields.insert(field.clone());
369387
}
370388
None => {}

0 commit comments

Comments
 (0)