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