| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- //===----------------------------------------------------------------------===//
- //
- // Defines a checker for proper use of Recycler Write Barrier functionality
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/ADT/StringSwitch.h"
- #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
- #include "clang/StaticAnalyzer/Core/Checker.h"
- #include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
- #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
- #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
- #include <cassert>
- using namespace clang;
- using namespace ento;
- class RecyclerChecker
- : public Checker<check::PostStmt<CXXNewExpr> > {
- std::unique_ptr<BugType> InvalidAllocatorBugType;
- public:
- RecyclerChecker();
- void checkPostStmt(const CXXNewExpr *newExpr, CheckerContext& ctx) const;
- };
- static BugType* createRecyclerCheckerError(StringRef name) {
- return new BugType(
- new CheckerBase(),
- name, "Recycler Checker Error");
- }
- static bool isCastToRecycler(const CXXStaticCastExpr* castNode)
- {
- // Not a cast
- if (castNode == nullptr)
- {
- return false;
- }
- QualType targetType = castNode->getTypeAsWritten();
- if (const IdentifierInfo* info = targetType.getBaseTypeIdentifier())
- {
- //printf("Cast to %s\n", info->getName().str().c_str());
- return info->getName().equals("Recycler");
- }
- else
- {
- printf("Can't get base type identifier");
- return false;
- }
- }
- RecyclerChecker::RecyclerChecker()
- {
- InvalidAllocatorBugType.reset(createRecyclerCheckerError("Invalid type"));
- }
- void RecyclerChecker::checkPostStmt(const CXXNewExpr* newExpr, CheckerContext& ctx) const
- {
- if (newExpr->getNumPlacementArgs() > 1)
- {
- const Expr* firstArgNode = newExpr->getPlacementArg(0);
- // Check if the first argument to new is a static cast
- // AllocatorNew in Chakra always does a static_cast to the AllocatorType
- CXXStaticCastExpr* castNode = nullptr;
- if (firstArgNode != nullptr &&
- (castNode = const_cast<CXXStaticCastExpr*>(dyn_cast<CXXStaticCastExpr>(firstArgNode))))
- {
- //printf("Expr is %s\n", firstArgNode->getStmtClassName());
- if (isCastToRecycler(castNode))
- {
- //printf("Recycler allocation found\n");
- const Expr* secondArgNode = newExpr->getPlacementArg(1);
- // Chakra has two types of allocating functions- throwing and non-throwing
- // However, recycler allocations are always throwing, so the second parameter
- // should be the address of the allocator function
- auto unaryNode = cast<UnaryOperator>(secondArgNode);
- if (unaryNode != nullptr && unaryNode->getOpcode() == UnaryOperatorKind::UO_AddrOf)
- {
- Expr* subExpr = unaryNode->getSubExpr();
- if (DeclRefExpr* declRef = cast<DeclRefExpr>(subExpr))
- {
- auto declNameInfo = declRef->getNameInfo();
- printf("AllocFunc: %s\n", declNameInfo.getName().getAsString().c_str());
- if (const IdentifierInfo* info = newExpr->getAllocatedType().getBaseTypeIdentifier())
- {
- printf("Type: %s\n", info->getName().str().c_str());
- }
- else
- {
- printf("Can't get base type identifier\n");
- }
- }
- else
- {
- printf("Expected DeclRefExpr:\n");
- subExpr->dump();
- }
- }
- else
- {
- printf("Expected unary node:\n");
- secondArgNode->dump();
- }
- //printf("-------------------\n");
- }
- /*
- else
- {
- printf("Not a cast node? 0x%x\n", castNode);
- firstArgNode->dump();
- printf("\n");
- }
- */
- }
- }
- }
- static void initRecyclerChecker(CheckerManager &mgr) {
- mgr.registerChecker<RecyclerChecker>();
- }
- extern "C" void clang_registerCheckers(CheckerRegistry ®istry) {
- registry.addChecker(initRecyclerChecker, "chakra.RecyclerChecker",
- "Check Recycler allocator usage");
- }
- extern "C" const char clang_analyzerAPIVersionString[] =
- CLANG_ANALYZER_API_VERSION_STRING;
|