================ @@ -0,0 +1,187 @@ +//=== StoreToImmutableChecker.cpp - Store to immutable memory ---*- 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 StoreToImmutableChecker, a checker that detects writes +// to immutable memory regions. This implements part of SEI CERT Rule ENV30-C. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ParentMap.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/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" + +using namespace clang; +using namespace ento; + +namespace { +class StoreToImmutableChecker : public Checker<check::Bind> { + const BugType BT{this, "Write to immutable memory", "CERT Environment (ENV)"}; + +public: + void checkBind(SVal Loc, SVal Val, const Stmt *S, CheckerContext &C) const; + +private: + bool isInitializationContext(const Stmt *S, CheckerContext &C) const; + bool isEffectivelyConstRegion(const MemRegion *MR, CheckerContext &C) const; +}; +} // end anonymous namespace + +bool StoreToImmutableChecker::isInitializationContext(const Stmt *S, + CheckerContext &C) const { + // Check if this is a DeclStmt (variable declaration) + if (isa<DeclStmt>(S)) + return true; + + // This part is specific for initialization of const lambdas pre-C++17. + // Lets look at the AST of the statement: + // ``` + // const auto lambda = [](){}; + // ``` + // + // The relevant part of the AST for this case prior to C++17 is: + // ... + // `-DeclStmt + // `-VarDecl + // `-ExprWithCleanups + // `-CXXConstructExpr + // ... + // In C++17 and later, the AST is different: + // ... + // `-DeclStmt + // `-VarDecl + // `-ImplicitCastExpr + // `-LambdaExpr + // |-CXXRecordDecl + // `-CXXConstructExpr + // ... + // And even beside this, the statement `S` that is given to the checkBind + // callback is the VarDecl in C++17 and later, and the CXXConstructExpr in + // C++14 and before. So in order to support the C++14 we need the following + // ugly hack to detect whether this construction is used to initialize a + // variable. + // + // FIXME: This should be eliminated once the API of checkBind would allow to + // distinguish between initialization and assignment, because this information + // is already available in the engine, it is just not passed to the checker + // API. + if (!isa<CXXConstructExpr>(S)) + return false; + + // We use elidable construction to detect initialization. + if (cast<CXXConstructExpr>(S)->isElidable()) + return true; + + return false; +} + +static bool isEffectivelyConstRegionAux(const MemRegion *MR, + CheckerContext &C) { + // Check if the region is in the global immutable space + const MemSpaceRegion *MS = MR->getMemorySpace(C.getState()); + if (isa<GlobalImmutableSpaceRegion>(MS)) + return true; + + // Check if this is a TypedRegion with a const-qualified type + if (const auto *TR = dyn_cast<TypedRegion>(MR)) { + QualType LocationType = TR->getDesugaredLocationType(C.getASTContext()); + if (LocationType->isPointerOrReferenceType()) + LocationType = LocationType->getPointeeType(); + if (LocationType.isConstQualified()) + return true; + } + + // Check if this is a SymbolicRegion with a const-qualified pointee type + if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) { + QualType PointeeType = SR->getPointeeStaticType(); + if (PointeeType.isConstQualified()) + return true; + } + + // NOTE: The only kind of region that is not checked by the above branches is + // AllocaRegion. We do not need to check AllocaRegion, as it models untyped + // memory, that is allocated on the stack. + + return false; +} + +bool StoreToImmutableChecker::isEffectivelyConstRegion( + const MemRegion *MR, CheckerContext &C) const { ---------------- gamesh411 wrote:
Added a similar test case that tests `SubRegions` in general, not just `ElementRegions`. https://github.com/llvm/llvm-project/pull/150417 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits