in source/FrameSet.cpp [458:534]
FrameSet FrameSet::propagate_crtex_frames(
const Method* callee,
const AccessPath& callee_port,
const Position* call_position,
int maximum_source_sink_distance,
Context& context,
const std::vector<const DexType * MT_NULLABLE>& source_register_types,
std::vector<std::reference_wrapper<const Frame>> frames) const {
FrameSet result;
for (const Frame& frame : frames) {
std::vector<const Feature*> via_type_of_features_added;
auto propagated = propagate_frames(
callee,
callee_port,
call_position,
maximum_source_sink_distance,
context,
source_register_types,
{}, // TODO: Support via-value-of for crtex frames
{std::cref(frame)},
via_type_of_features_added);
if (propagated.is_bottom()) {
continue;
}
auto canonical_names = frame.canonical_names();
if (!canonical_names.is_value() || canonical_names.elements().empty()) {
WARNING(
2,
"Encountered crtex frame without canonical names. Frame: `{}`",
frame);
continue;
}
CanonicalNameSetAbstractDomain instantiated_names;
for (const auto& canonical_name : canonical_names.elements()) {
auto instantiated_name = canonical_name.instantiate(
propagated.callee(), via_type_of_features_added);
if (!instantiated_name) {
continue;
}
instantiated_names.add(*instantiated_name);
}
auto canonical_callee_port =
propagated.callee_port().canonicalize_for_method(propagated.callee());
// All fields should be propagated like other frames, except the crtex
// fields. Ideally, origins should contain the canonical names as well,
// but canonical names are strings and cannot be stored in MethodSet.
// Frame is not propagated if none of the canonical names instantiated
// successfully.
if (instantiated_names.is_value() &&
!instantiated_names.elements().empty()) {
result.add(Frame(
kind_,
canonical_callee_port,
propagated.callee(),
propagated.field_callee(),
propagated.call_position(),
/* distance (always leaves for crtex frames) */ 0,
propagated.origins(),
propagated.field_origins(),
propagated.inferred_features(),
propagated.locally_inferred_features(),
propagated.user_features(),
propagated.via_type_of_ports(),
propagated.via_value_of_ports(),
propagated.local_positions(),
/* canonical_names */ instantiated_names));
}
}
return result;
}