1//===- UnsafeBufferUsageExtractor.cpp -------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "SSAFAnalysesCommon.h"
10#include "clang/AST/ASTConsumer.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/AST/DynamicRecursiveASTVisitor.h"
13#include "clang/Analysis/Analyses/UnsafeBufferUsage.h"
14#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
15#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
16#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
17#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
18#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
19#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/STLFunctionalExtras.h"
21#include "llvm/Support/ErrorHandling.h"
22#include <memory>
23
24using namespace clang;
25using namespace ssaf;
26
27namespace clang::ssaf {
28class UnsafeBufferUsageTUSummaryExtractor : public TUSummaryExtractor {
29public:
30 UnsafeBufferUsageTUSummaryExtractor(TUSummaryBuilder &Builder)
31 : TUSummaryExtractor(Builder) {}
32
33 /// \return a non-null unique pointer to a UnsafeBufferUsageEntitySummary
34 std::unique_ptr<UnsafeBufferUsageEntitySummary>
35 extractEntitySummary(const std::vector<const NamedDecl *> &ContributorDecls,
36 ASTContext &Ctx);
37 void HandleTranslationUnit(ASTContext &Ctx) override;
38};
39} // namespace clang::ssaf
40
41std::unique_ptr<UnsafeBufferUsageEntitySummary>
42clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::extractEntitySummary(
43 const std::vector<const NamedDecl *> &ContributorDecls, ASTContext &Ctx) {
44 std::set<const Expr *> UnsafePointers;
45 auto MatchAction = [&UnsafePointers, &Ctx](const DynTypedNode &Node) {
46 matchUnsafePointers(N: Node, Ctx, UnsafePointers);
47 };
48
49 for (const auto *Contrib : ContributorDecls)
50 findMatchesIn(Contributor: Contrib, MatchActionRef: MatchAction);
51
52 EntityPointerLevelSet Results;
53
54 for (const Expr *Ptr : UnsafePointers) {
55 Expected<EntityPointerLevelSet> Translation =
56 translateEntityPointerLevel(E: Ptr, Ctx, Extractor&: *this);
57
58 if (Translation) {
59 // Filter out those temporary invalid EntityPointerLevels associated
60 // with `&E` pointers. They need no transformation of entities:
61 auto FilteredTranslation = llvm::make_filter_range(
62 Range&: *Translation, Pred: [](const EntityPointerLevel &E) -> bool {
63 return E.getPointerLevel() > 0;
64 });
65 Results.insert(first: FilteredTranslation.begin(), last: FilteredTranslation.end());
66 continue;
67 }
68 logWarningFromError(Err: Translation.takeError());
69 }
70
71 return std::make_unique<UnsafeBufferUsageEntitySummary>(
72 args: UnsafeBufferUsageEntitySummary(std::move(Results)));
73}
74
75void clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::HandleTranslationUnit(
76 ASTContext &Ctx) {
77 extractAndAddSummaries(
78 Extractor&: *this, Builder&: SummaryBuilder, Ctx,
79 ExtractFn: [&](const std::vector<const NamedDecl *> &Decls) {
80 return extractEntitySummary(ContributorDecls: Decls, Ctx);
81 },
82 ExtractorName: "UnsafeBufferUsage");
83}
84namespace clang::ssaf {
85// NOLINTNEXTLINE(misc-use-internal-linkage)
86volatile int UnsafeBufferUsageExtractorAnchorSource = 0;
87} // namespace clang::ssaf
88
89static clang::ssaf::TUSummaryExtractorRegistry::Add<
90 UnsafeBufferUsageTUSummaryExtractor>
91 RegisterExtractor(UnsafeBufferUsageEntitySummary::Name,
92 "Extract unsafe buffer pointers");
93