174 lines · cpp
1//===- MemRegionDescriptiveNameTest.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "CheckerRegistration.h"10#include "clang/StaticAnalyzer/Core/Checker.h"11#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"12#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"13#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"14#include "gtest/gtest.h"15 16using namespace clang;17using namespace ento;18 19namespace {20 21class DescriptiveNameChecker : public Checker<check::PreCall> {22public:23 void checkPreCall(const CallEvent &Call, CheckerContext &C) const {24 if (!HandlerFn.matches(Call))25 return;26 27 const MemRegion *ArgReg = Call.getArgSVal(0).getAsRegion();28 assert(ArgReg && "expecting a location as the first argument");29 30 auto DescriptiveName = ArgReg->getDescriptiveName(/*UseQuotes=*/false);31 if (ExplodedNode *Node = C.generateNonFatalErrorNode(C.getState())) {32 auto Report =33 std::make_unique<PathSensitiveBugReport>(Bug, DescriptiveName, Node);34 C.emitReport(std::move(Report));35 }36 }37 38private:39 const BugType Bug{this, "DescriptiveNameBug"};40 const CallDescription HandlerFn = {41 CDM::SimpleFunc, {"reportDescriptiveName"}, 1};42};43 44void addDescriptiveNameChecker(AnalysisASTConsumer &AnalysisConsumer,45 AnalyzerOptions &AnOpts) {46 AnOpts.CheckersAndPackages = {{"DescriptiveNameChecker", true}};47 AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {48 Registry.addChecker<DescriptiveNameChecker>("DescriptiveNameChecker",49 "MockDescription");50 });51}52 53bool runChecker(StringRef Code, std::string &Output) {54 return runCheckerOnCode<addDescriptiveNameChecker>(Code.str(), Output,55 /*OnlyEmitWarnings=*/true);56}57 58TEST(MemRegionDescriptiveNameTest, ConcreteIntElementRegionIndex) {59 StringRef Code = R"cpp(60void reportDescriptiveName(int *p);61const unsigned int index = 1;62extern int array[3];63void top() {64 reportDescriptiveName(&array[index]);65})cpp";66 67 std::string Output;68 ASSERT_TRUE(runChecker(Code, Output));69 EXPECT_EQ(Output, "DescriptiveNameChecker: array[1]\n");70}71 72TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndex) {73 StringRef Code = R"cpp(74void reportDescriptiveName(int *p);75extern unsigned int index;76extern int array[3];77void top() {78 reportDescriptiveName(&array[index]);79})cpp";80 81 std::string Output;82 ASSERT_TRUE(runChecker(Code, Output));83 EXPECT_EQ(Output, "DescriptiveNameChecker: array[index]\n");84}85 86TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexSymbolValFails) {87 StringRef Code = R"cpp(88void reportDescriptiveName(int *p);89extern int* ptr;90extern int array[3];91void top() {92 reportDescriptiveName(&array[(long long)ptr]);93})cpp";94 95 std::string Output;96 ASSERT_TRUE(runChecker(Code, Output));97 EXPECT_EQ(Output, "DescriptiveNameChecker: \n");98}99 100TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexOrigRegionFails) {101 StringRef Code = R"cpp(102void reportDescriptiveName(int *p);103extern int getInt(void);104extern int array[3];105void top() {106 reportDescriptiveName(&array[getInt()]);107})cpp";108 109 std::string Output;110 ASSERT_TRUE(runChecker(Code, Output));111 EXPECT_EQ(Output, "DescriptiveNameChecker: \n");112}113 114TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexDescrNameFails) {115 StringRef Code = R"cpp(116void reportDescriptiveName(int *p);117extern int *ptr;118extern int array[3];119void top() {120 reportDescriptiveName(&array[*ptr]);121})cpp";122 123 std::string Output;124 ASSERT_TRUE(runChecker(Code, Output));125 EXPECT_EQ(Output, "DescriptiveNameChecker: \n");126}127 128TEST(MemRegionDescriptiveNameTest,129 SymbolicElementRegionIndexIncorrectSymbolName) {130 StringRef Code = R"cpp(131void reportDescriptiveName(int *p);132extern int x, y;133extern int array[3];134void top() {135 y = x;136 reportDescriptiveName(&array[y]);137})cpp";138 139 std::string Output;140 ASSERT_TRUE(runChecker(Code, Output));141 // FIXME: Should return array[y], but returns array[x] (OriginRegion).142 EXPECT_EQ(Output, "DescriptiveNameChecker: array[x]\n");143}144 145TEST(MemRegionDescriptiveNameTest, FieldRegWithSuperElementReg) {146 StringRef Code = R"cpp(147void reportDescriptiveName(int *p);148struct val_struct { int val; };149extern struct val_struct val_struct_array[3];150void top() {151 reportDescriptiveName(&val_struct_array[0].val);152})cpp";153 154 std::string Output;155 ASSERT_TRUE(runChecker(Code, Output));156 EXPECT_EQ(Output, "DescriptiveNameChecker: val_struct_array[0].val\n");157}158 159TEST(MemRegionDescriptiveNameTest, FieldRegWithSuperMultidimElementReg) {160 StringRef Code = R"cpp(161void reportDescriptiveName(int *p);162struct val_struct { int val; };163extern struct val_struct val_struct_array[3][4];164void top() {165 reportDescriptiveName(&val_struct_array[1][2].val);166})cpp";167 168 std::string Output;169 ASSERT_TRUE(runChecker(Code, Output));170 EXPECT_EQ(Output, "DescriptiveNameChecker: val_struct_array[1][2].val\n");171}172 173} // namespace174