void check_flows()

in source/Transfer.cpp [630:682]


void check_flows(
    MethodContext* context,
    const Taint& sources,
    const Taint& sinks,
    const Position* position,
    const FeatureMayAlwaysSet& extra_features,
    FulfilledPartialKindState* MT_NULLABLE fulfilled_partial_sinks) {
  if (sources.is_bottom() || sinks.is_bottom()) {
    return;
  }

  auto sources_by_kind = sources.partition_by_kind();
  auto sinks_by_kind = sinks.partition_by_kind();
  for (const auto& [source_kind, source_taint] : sources_by_kind) {
    if (source_kind == Kinds::artificial_source()) {
      continue;
    }

    for (const auto& [sink_kind, sink_taint] : sinks_by_kind) {
      // Check if this satisfies any rule. If so, create the issue.
      const auto& rules = context->rules.rules(source_kind, sink_kind);
      for (const auto* rule : rules) {
        create_issue(
            context, source_taint, sink_taint, rule, position, extra_features);
      }

      // Check if this satisfies any partial (multi-source/sink) rule.
      if (fulfilled_partial_sinks) {
        const auto* MT_NULLABLE partial_sink = sink_kind->as<PartialKind>();
        if (partial_sink) {
          const auto& partial_rules =
              context->rules.partial_rules(source_kind, partial_sink);
          for (const auto* partial_rule : partial_rules) {
            check_multi_source_multi_sink_rules(
                context,
                source_kind,
                source_taint,
                sink_kind,
                sink_taint,
                *fulfilled_partial_sinks,
                partial_rule,
                position,
                extra_features);
          }
        }
      }
    }
  }

  if (!fulfilled_partial_sinks) {
    create_sinks(context, sources, sinks, extra_features);
  }
}