bool Transfer::analyze_invoke()

in source/Transfer.cpp [880:933]


bool Transfer::analyze_invoke(
    MethodContext* context,
    const IRInstruction* instruction,
    AnalysisEnvironment* environment) {
  log_instruction(context, instruction);

  auto callee = get_callee(context, environment, instruction);

  const AnalysisEnvironment previous_environment = *environment;
  TaintTree result_taint;
  check_flows(context, &previous_environment, instruction, callee);
  apply_propagations(
      context,
      &previous_environment,
      environment,
      instruction,
      callee,
      result_taint);
  apply_generations(context, environment, instruction, callee, result_taint);

  if (callee.resolved_base_method &&
      callee.resolved_base_method->returns_void()) {
    LOG_OR_DUMP(context, 4, "Resetting the result register");
    environment->assign(k_result_register, MemoryLocationsDomain::bottom());
  } else if (
      auto* memory_location =
          try_inline_invoke(context, environment, instruction, callee)) {
    LOG_OR_DUMP(
        context, 4, "Setting result register to {}", show(memory_location));
    environment->assign(k_result_register, memory_location);
  } else {
    // Check if the method can alias existing memory location
    memory_location =
        try_alias_this_location(context, environment, callee, instruction);

    // Assume the method call returns a new memory location,
    // that does not alias with anything.
    if (memory_location == nullptr) {
      memory_location = context->memory_factory.make_location(instruction);
    }

    LOG_OR_DUMP(
        context, 4, "Setting result register to {}", show(memory_location));
    environment->assign(k_result_register, memory_location);

    LOG_OR_DUMP(
        context, 4, "Tainting {} with {}", show(memory_location), result_taint);
    environment->write(memory_location, result_taint, UpdateKind::Weak);
  }

  analyze_artificial_calls(context, instruction, environment);

  return false;
}