Model analyze()

in source/Interprocedural.cpp [107:169]


Model analyze(
    Context& global_context,
    const Registry& registry,
    const Model& old_model) {
  Timer timer;

  Model model = old_model;

  auto* method = model.method();
  if (!method) {
    return model;
  }

  auto method_context =
      std::make_unique<MethodContext>(global_context, registry, model);

  LOG_OR_DUMP(
      method_context, 3, "Analyzing `\033[33m{}\033[0m`...", method->show());

  auto* code = method->get_code();
  if (!code) {
    throw std::runtime_error(fmt::format(
        "Attempting to analyze method `{}` with no code!", method->show()));
  }
  if (!code->cfg_built()) {
    throw std::runtime_error(fmt::format(
        "Attempting to analyze method `{}` with no control flow graph!",
        method->show()));
  } else {
    LOG_OR_DUMP(
        method_context, 4, "Code:\n{}", show_control_flow_graph(code->cfg()));
  }

  auto fixpoint =
      FixpointIterator(code->cfg(), CombinedTransfer(method_context.get()));
  fixpoint.run(AnalysisEnvironment::initial());
  model.collapse_invalid_paths(global_context);
  model.approximate();

  LOG_OR_DUMP(
      method_context, 4, "Computed model for `{}`: {}", method->show(), model);

  global_context.statistics->log_time(method, timer);
  auto duration = timer.duration_in_seconds();
  if (duration > 10.0) {
    WARNING(1, "Analyzing `{}` took {:.2f}s!", method->show(), duration);
  }
  auto slow_method_bound =
      global_context.options->maximum_method_analysis_time();
  if (slow_method_bound && *slow_method_bound <= duration) {
    LOG(1,
        "Analyzing `{}` took {:.2f}s, setting default taint-in-taint-out.",
        method->show(),
        duration);
    model.add_mode(Model::Mode::AddViaObscureFeature, global_context);
    model.add_mode(Model::Mode::SkipAnalysis, global_context);
    model.add_mode(Model::Mode::NoJoinVirtualOverrides, global_context);
    model.add_mode(Model::Mode::TaintInTaintOut, global_context);
    model.add_mode(Model::Mode::TaintInTaintThis, global_context);
  }

  return model;
}