This commit explicitly specifies the matching mode (C library function, any non-method function, or C++ method) for the `CallDescription`s constructed in various checkers where this transition was easy and straightforward. This change won't cause major functional changes, but isn't NFC because it ensures that e.g. call descriptions for a non-method function won't accidentally match a method that has the same name. Separate commits will perform (or have already performed) this change in other checkers. My goal is to ensure that the call description mode is always explicitly specified and eliminate (or strongly restrict) the vague "may be either a method or a simple function" mode that's the current default.
68 lines
2.5 KiB
C++
68 lines
2.5 KiB
C++
//== PutenvWithAutoChecker.cpp --------------------------------- -*- C++ -*--=//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines PutenvWithAutoChecker which finds calls of ``putenv``
|
|
// function with automatic variable as the argument.
|
|
// https://wiki.sei.cmu.edu/confluence/x/6NYxBQ
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "../AllocationState.h"
|
|
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
|
|
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
|
#include "clang/StaticAnalyzer/Core/Checker.h"
|
|
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
|
|
|
|
using namespace clang;
|
|
using namespace ento;
|
|
|
|
namespace {
|
|
class PutenvWithAutoChecker : public Checker<check::PostCall> {
|
|
private:
|
|
BugType BT{this, "'putenv' function should not be called with auto variables",
|
|
categories::SecurityError};
|
|
const CallDescription Putenv{CDM::CLibrary, {"putenv"}, 1};
|
|
|
|
public:
|
|
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
|
|
};
|
|
} // namespace
|
|
|
|
void PutenvWithAutoChecker::checkPostCall(const CallEvent &Call,
|
|
CheckerContext &C) const {
|
|
if (!Putenv.matches(Call))
|
|
return;
|
|
|
|
SVal ArgV = Call.getArgSVal(0);
|
|
const Expr *ArgExpr = Call.getArgExpr(0);
|
|
const MemSpaceRegion *MSR = ArgV.getAsRegion()->getMemorySpace();
|
|
|
|
if (!isa<StackSpaceRegion>(MSR))
|
|
return;
|
|
|
|
StringRef ErrorMsg = "The 'putenv' function should not be called with "
|
|
"arguments that have automatic storage";
|
|
ExplodedNode *N = C.generateErrorNode();
|
|
auto Report = std::make_unique<PathSensitiveBugReport>(BT, ErrorMsg, N);
|
|
|
|
// Track the argument.
|
|
bugreporter::trackExpressionValue(Report->getErrorNode(), ArgExpr, *Report);
|
|
|
|
C.emitReport(std::move(Report));
|
|
}
|
|
|
|
void ento::registerPutenvWithAuto(CheckerManager &Mgr) {
|
|
Mgr.registerChecker<PutenvWithAutoChecker>();
|
|
}
|
|
|
|
bool ento::shouldRegisterPutenvWithAuto(const CheckerManager &) { return true; }
|