source/FulfilledPartialKindState.cpp (81 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #include <mariana-trench/FulfilledPartialKindState.h> #include <optional> namespace marianatrench { std::optional<Taint> FulfilledPartialKindState::fulfill_kind( const PartialKind* kind, const MultiSourceMultiSinkRule* rule, const FeatureMayAlwaysSet& features, MethodContext* context, const Taint& sink) { const auto* counterpart = get_fulfilled_counterpart(kind, rule); if (counterpart) { // If both partial sinks for the callsite have been fulfilled, the rule // is satisfied. Make this a triggered sink and create the sink flow // (FrameSet) for the issue. Include the features from both flows (using // .add, NOT .join). const auto* triggered_kind = context->kinds.get_triggered(kind, rule); auto sink_features = get_features(counterpart, rule); sink_features.add(features); auto issue_sink = sink.transform_kind_with_features( [&](const Kind* sink_kind) { // The given taint should only contain the given partial kind. // Transform it into the triggered kind. mt_assert(sink_kind == kind); return std::vector<const Kind*>{triggered_kind}; }, [&](const Kind* /* new_sink_kind */) { return sink_features; }); erase(counterpart, rule); return issue_sink; } add_fulfilled_kind(kind, rule, features); return std::nullopt; } const PartialKind* MT_NULLABLE FulfilledPartialKindState::get_fulfilled_counterpart( const PartialKind* unfulfilled_kind, const MultiSourceMultiSinkRule* rule) const { for (const auto& [kind, rules_map] : map_) { if (unfulfilled_kind->is_counterpart(kind) && rules_map.find(rule) != rules_map.end()) { return kind; } } return nullptr; } FeatureMayAlwaysSet FulfilledPartialKindState::get_features( const PartialKind* kind, const MultiSourceMultiSinkRule* rule) const { return map_.at(kind).at(rule); } std::vector<const Kind*> FulfilledPartialKindState::make_triggered_counterparts( MethodContext* context, const PartialKind* unfulfilled_kind) const { std::vector<const Kind*> result; for (const auto& [kind, rules_map] : map_) { if (unfulfilled_kind->is_counterpart(kind)) { for (const auto& [rule, _features] : rules_map) { result.emplace_back( context->kinds.get_triggered(unfulfilled_kind, rule)); } } } // Empty if the unfulfilled kind does not have a counterpart that is // fulfilled. return result; } void FulfilledPartialKindState::add_fulfilled_kind( const PartialKind* kind, const MultiSourceMultiSinkRule* rule, const FeatureMayAlwaysSet& features) { auto rules_map = map_.find(kind); if (rules_map == map_.end()) { map_.emplace(kind, RuleMap{{rule, features}}); return; } rules_map->second.emplace(rule, features); } void FulfilledPartialKindState::erase( const PartialKind* kind, const MultiSourceMultiSinkRule* rule) { auto rules_map = map_.find(kind); if (rules_map == map_.end()) { return; } rules_map->second.erase(rule); if (rules_map->second.empty()) { map_.erase(kind); } } } // namespace marianatrench