in source/Transfer.cpp [953:1022]
bool Transfer::analyze_iput(
MethodContext* context,
const IRInstruction* instruction,
AnalysisEnvironment* environment) {
log_instruction(context, instruction);
mt_assert(instruction->srcs().size() == 2);
mt_assert(instruction->has_field());
auto taint = environment->read(/* register */ instruction->srcs()[0]);
auto* position = context->positions.get(
context->method(),
environment->last_position(),
Root(Root::Kind::Return),
instruction);
taint.map(
[position](Taint& sources) { sources.add_local_position(position); });
// Check if the taint above flows into a field sink
const auto* field =
context->call_graph.resolved_field_access(context->method(), instruction);
if (!field) {
WARNING_OR_DUMP(
context,
3,
"Unable to resolve access of field for iput {}",
show(instruction->get_field()));
} else {
auto field_model = field ? context->registry.get(field) : FieldModel();
auto sinks = field_model.sinks();
if (!sinks.empty() && !taint.is_bottom()) {
for (const auto& [port, sources] : taint.elements()) {
check_flows(
context,
sources,
sinks,
position,
/* extra_features */ FeatureMayAlwaysSet(),
/* fulfilled_partial_sinks */ nullptr);
}
}
}
// Store the taint in the memory location(s) representing the field
auto* field_name = instruction->get_field()->get_name();
auto target_memory_locations =
environment->memory_locations(/* register */ instruction->srcs()[1]);
bool is_singleton = target_memory_locations.elements().size() == 1;
for (auto* memory_location : target_memory_locations.elements()) {
auto field_memory_location = memory_location->make_field(field_name);
auto taint_copy = taint;
add_field_features(context, taint_copy, field_memory_location);
LOG_OR_DUMP(
context,
4,
"Tainting {} with {}",
show(field_memory_location),
taint_copy);
environment->write(
field_memory_location,
taint_copy,
is_singleton ? UpdateKind::Strong : UpdateKind::Weak);
}
analyze_artificial_calls(context, instruction, environment);
return false;
}