CastValueChecker.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. //===- CastValueChecker - Model implementation of custom RTTIs --*- C++ -*-===//
  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. // This defines CastValueChecker which models casts of custom RTTIs.
  10. //
  11. // TODO list:
  12. // - It only allows one succesful cast between two types however in the wild
  13. // the object could be casted to multiple types.
  14. // - It needs to check the most likely type information from the dynamic type
  15. // map to increase precision of dynamic casting.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #include "clang/AST/DeclTemplate.h"
  19. #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
  20. #include "clang/StaticAnalyzer/Core/Checker.h"
  21. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  22. #include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
  23. #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
  24. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  25. #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"
  26. #include "llvm/ADT/Optional.h"
  27. #include <utility>
  28. using namespace clang;
  29. using namespace ento;
  30. namespace {
  31. class CastValueChecker : public Checker<check::DeadSymbols, eval::Call> {
  32. enum class CallKind { Function, Method, InstanceOf };
  33. using CastCheck =
  34. std::function<void(const CastValueChecker *, const CallEvent &Call,
  35. DefinedOrUnknownSVal, CheckerContext &)>;
  36. public:
  37. // We have five cases to evaluate a cast:
  38. // 1) The parameter is non-null, the return value is non-null.
  39. // 2) The parameter is non-null, the return value is null.
  40. // 3) The parameter is null, the return value is null.
  41. // cast: 1; dyn_cast: 1, 2; cast_or_null: 1, 3; dyn_cast_or_null: 1, 2, 3.
  42. //
  43. // 4) castAs: Has no parameter, the return value is non-null.
  44. // 5) getAs: Has no parameter, the return value is null or non-null.
  45. //
  46. // We have two cases to check the parameter is an instance of the given type.
  47. // 1) isa: The parameter is non-null, returns boolean.
  48. // 2) isa_and_nonnull: The parameter is null or non-null, returns boolean.
  49. bool evalCall(const CallEvent &Call, CheckerContext &C) const;
  50. void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
  51. private:
  52. // These are known in the LLVM project. The pairs are in the following form:
  53. // {{{namespace, call}, argument-count}, {callback, kind}}
  54. const CallDescriptionMap<std::pair<CastCheck, CallKind>> CDM = {
  55. {{{"llvm", "cast"}, 1},
  56. {&CastValueChecker::evalCast, CallKind::Function}},
  57. {{{"llvm", "dyn_cast"}, 1},
  58. {&CastValueChecker::evalDynCast, CallKind::Function}},
  59. {{{"llvm", "cast_or_null"}, 1},
  60. {&CastValueChecker::evalCastOrNull, CallKind::Function}},
  61. {{{"llvm", "dyn_cast_or_null"}, 1},
  62. {&CastValueChecker::evalDynCastOrNull, CallKind::Function}},
  63. {{{"clang", "castAs"}, 0},
  64. {&CastValueChecker::evalCastAs, CallKind::Method}},
  65. {{{"clang", "getAs"}, 0},
  66. {&CastValueChecker::evalGetAs, CallKind::Method}},
  67. {{{"llvm", "isa"}, 1},
  68. {&CastValueChecker::evalIsa, CallKind::InstanceOf}},
  69. {{{"llvm", "isa_and_nonnull"}, 1},
  70. {&CastValueChecker::evalIsaAndNonNull, CallKind::InstanceOf}}};
  71. void evalCast(const CallEvent &Call, DefinedOrUnknownSVal DV,
  72. CheckerContext &C) const;
  73. void evalDynCast(const CallEvent &Call, DefinedOrUnknownSVal DV,
  74. CheckerContext &C) const;
  75. void evalCastOrNull(const CallEvent &Call, DefinedOrUnknownSVal DV,
  76. CheckerContext &C) const;
  77. void evalDynCastOrNull(const CallEvent &Call, DefinedOrUnknownSVal DV,
  78. CheckerContext &C) const;
  79. void evalCastAs(const CallEvent &Call, DefinedOrUnknownSVal DV,
  80. CheckerContext &C) const;
  81. void evalGetAs(const CallEvent &Call, DefinedOrUnknownSVal DV,
  82. CheckerContext &C) const;
  83. void evalIsa(const CallEvent &Call, DefinedOrUnknownSVal DV,
  84. CheckerContext &C) const;
  85. void evalIsaAndNonNull(const CallEvent &Call, DefinedOrUnknownSVal DV,
  86. CheckerContext &C) const;
  87. };
  88. } // namespace
  89. static bool isInfeasibleCast(const DynamicCastInfo *CastInfo,
  90. bool CastSucceeds) {
  91. if (!CastInfo)
  92. return false;
  93. return CastSucceeds ? CastInfo->fails() : CastInfo->succeeds();
  94. }
  95. static const NoteTag *getNoteTag(CheckerContext &C,
  96. const DynamicCastInfo *CastInfo,
  97. QualType CastToTy, const Expr *Object,
  98. bool CastSucceeds, bool IsKnownCast) {
  99. std::string CastToName =
  100. CastInfo ? CastInfo->to()->getAsCXXRecordDecl()->getNameAsString()
  101. : CastToTy.getAsString();
  102. Object = Object->IgnoreParenImpCasts();
  103. return C.getNoteTag(
  104. [=]() -> std::string {
  105. SmallString<128> Msg;
  106. llvm::raw_svector_ostream Out(Msg);
  107. if (!IsKnownCast)
  108. Out << "Assuming ";
  109. if (const auto *DRE = dyn_cast<DeclRefExpr>(Object)) {
  110. Out << '\'' << DRE->getDecl()->getDeclName() << '\'';
  111. } else if (const auto *ME = dyn_cast<MemberExpr>(Object)) {
  112. Out << (IsKnownCast ? "Field '" : "field '")
  113. << ME->getMemberDecl()->getDeclName() << '\'';
  114. } else {
  115. Out << (IsKnownCast ? "The object" : "the object");
  116. }
  117. Out << ' ' << (CastSucceeds ? "is a" : "is not a") << " '" << CastToName
  118. << '\'';
  119. return std::string(Out.str());
  120. },
  121. /*IsPrunable=*/true);
  122. }
  123. static const NoteTag *getNoteTag(CheckerContext &C,
  124. SmallVector<QualType, 4> CastToTyVec,
  125. const Expr *Object,
  126. bool IsKnownCast) {
  127. Object = Object->IgnoreParenImpCasts();
  128. return C.getNoteTag(
  129. [=]() -> std::string {
  130. SmallString<128> Msg;
  131. llvm::raw_svector_ostream Out(Msg);
  132. if (!IsKnownCast)
  133. Out << "Assuming ";
  134. if (const auto *DRE = dyn_cast<DeclRefExpr>(Object)) {
  135. Out << '\'' << DRE->getDecl()->getNameAsString() << '\'';
  136. } else if (const auto *ME = dyn_cast<MemberExpr>(Object)) {
  137. Out << (IsKnownCast ? "Field '" : "field '")
  138. << ME->getMemberDecl()->getNameAsString() << '\'';
  139. } else {
  140. Out << (IsKnownCast ? "The object" : "the object");
  141. }
  142. Out << " is";
  143. bool First = true;
  144. for (QualType CastToTy: CastToTyVec) {
  145. std::string CastToName =
  146. CastToTy->getAsCXXRecordDecl()
  147. ? CastToTy->getAsCXXRecordDecl()->getNameAsString()
  148. : CastToTy.getAsString();
  149. Out << ' ' << ((CastToTyVec.size() == 1) ? "not" :
  150. (First ? "neither" : "nor")) << " a '" << CastToName
  151. << '\'';
  152. First = false;
  153. }
  154. return std::string(Out.str());
  155. },
  156. /*IsPrunable=*/true);
  157. }
  158. //===----------------------------------------------------------------------===//
  159. // Main logic to evaluate a cast.
  160. //===----------------------------------------------------------------------===//
  161. static QualType alignReferenceTypes(QualType toAlign, QualType alignTowards,
  162. ASTContext &ACtx) {
  163. if (alignTowards->isLValueReferenceType() &&
  164. alignTowards.isConstQualified()) {
  165. toAlign.addConst();
  166. return ACtx.getLValueReferenceType(toAlign);
  167. } else if (alignTowards->isLValueReferenceType())
  168. return ACtx.getLValueReferenceType(toAlign);
  169. else if (alignTowards->isRValueReferenceType())
  170. return ACtx.getRValueReferenceType(toAlign);
  171. llvm_unreachable("Must align towards a reference type!");
  172. }
  173. static void addCastTransition(const CallEvent &Call, DefinedOrUnknownSVal DV,
  174. CheckerContext &C, bool IsNonNullParam,
  175. bool IsNonNullReturn,
  176. bool IsCheckedCast = false) {
  177. ProgramStateRef State = C.getState()->assume(DV, IsNonNullParam);
  178. if (!State)
  179. return;
  180. const Expr *Object;
  181. QualType CastFromTy;
  182. QualType CastToTy = Call.getResultType();
  183. if (Call.getNumArgs() > 0) {
  184. Object = Call.getArgExpr(0);
  185. CastFromTy = Call.parameters()[0]->getType();
  186. } else {
  187. Object = cast<CXXInstanceCall>(&Call)->getCXXThisExpr();
  188. CastFromTy = Object->getType();
  189. if (CastToTy->isPointerType()) {
  190. if (!CastFromTy->isPointerType())
  191. return;
  192. } else {
  193. if (!CastFromTy->isReferenceType())
  194. return;
  195. CastFromTy = alignReferenceTypes(CastFromTy, CastToTy, C.getASTContext());
  196. }
  197. }
  198. const MemRegion *MR = DV.getAsRegion();
  199. const DynamicCastInfo *CastInfo =
  200. getDynamicCastInfo(State, MR, CastFromTy, CastToTy);
  201. // We assume that every checked cast succeeds.
  202. bool CastSucceeds = IsCheckedCast || CastFromTy == CastToTy;
  203. if (!CastSucceeds) {
  204. if (CastInfo)
  205. CastSucceeds = IsNonNullReturn && CastInfo->succeeds();
  206. else
  207. CastSucceeds = IsNonNullReturn;
  208. }
  209. // Check for infeasible casts.
  210. if (isInfeasibleCast(CastInfo, CastSucceeds)) {
  211. C.generateSink(State, C.getPredecessor());
  212. return;
  213. }
  214. // Store the type and the cast information.
  215. bool IsKnownCast = CastInfo || IsCheckedCast || CastFromTy == CastToTy;
  216. if (!IsKnownCast || IsCheckedCast)
  217. State = setDynamicTypeAndCastInfo(State, MR, CastFromTy, CastToTy,
  218. CastSucceeds);
  219. SVal V = CastSucceeds ? C.getSValBuilder().evalCast(DV, CastToTy, CastFromTy)
  220. : C.getSValBuilder().makeNull();
  221. C.addTransition(
  222. State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), V, false),
  223. getNoteTag(C, CastInfo, CastToTy, Object, CastSucceeds, IsKnownCast));
  224. }
  225. static void addInstanceOfTransition(const CallEvent &Call,
  226. DefinedOrUnknownSVal DV,
  227. ProgramStateRef State, CheckerContext &C,
  228. bool IsInstanceOf) {
  229. const FunctionDecl *FD = Call.getDecl()->getAsFunction();
  230. QualType CastFromTy = Call.parameters()[0]->getType();
  231. SmallVector<QualType, 4> CastToTyVec;
  232. for (unsigned idx = 0; idx < FD->getTemplateSpecializationArgs()->size() - 1;
  233. ++idx) {
  234. TemplateArgument CastToTempArg =
  235. FD->getTemplateSpecializationArgs()->get(idx);
  236. switch (CastToTempArg.getKind()) {
  237. default:
  238. return;
  239. case TemplateArgument::Type:
  240. CastToTyVec.push_back(CastToTempArg.getAsType());
  241. break;
  242. case TemplateArgument::Pack:
  243. for (TemplateArgument ArgInPack: CastToTempArg.pack_elements())
  244. CastToTyVec.push_back(ArgInPack.getAsType());
  245. break;
  246. }
  247. }
  248. const MemRegion *MR = DV.getAsRegion();
  249. if (MR && CastFromTy->isReferenceType())
  250. MR = State->getSVal(DV.castAs<Loc>()).getAsRegion();
  251. bool Success = false;
  252. bool IsAnyKnown = false;
  253. for (QualType CastToTy: CastToTyVec) {
  254. if (CastFromTy->isPointerType())
  255. CastToTy = C.getASTContext().getPointerType(CastToTy);
  256. else if (CastFromTy->isReferenceType())
  257. CastToTy = alignReferenceTypes(CastToTy, CastFromTy, C.getASTContext());
  258. else
  259. return;
  260. const DynamicCastInfo *CastInfo =
  261. getDynamicCastInfo(State, MR, CastFromTy, CastToTy);
  262. bool CastSucceeds;
  263. if (CastInfo)
  264. CastSucceeds = IsInstanceOf && CastInfo->succeeds();
  265. else
  266. CastSucceeds = IsInstanceOf || CastFromTy == CastToTy;
  267. // Store the type and the cast information.
  268. bool IsKnownCast = CastInfo || CastFromTy == CastToTy;
  269. IsAnyKnown = IsAnyKnown || IsKnownCast;
  270. ProgramStateRef NewState = State;
  271. if (!IsKnownCast)
  272. NewState = setDynamicTypeAndCastInfo(State, MR, CastFromTy, CastToTy,
  273. IsInstanceOf);
  274. if (CastSucceeds) {
  275. Success = true;
  276. C.addTransition(
  277. NewState->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
  278. C.getSValBuilder().makeTruthVal(true)),
  279. getNoteTag(C, CastInfo, CastToTy, Call.getArgExpr(0), true,
  280. IsKnownCast));
  281. if (IsKnownCast)
  282. return;
  283. } else if (CastInfo && CastInfo->succeeds()) {
  284. C.generateSink(NewState, C.getPredecessor());
  285. return;
  286. }
  287. }
  288. if (!Success) {
  289. C.addTransition(
  290. State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
  291. C.getSValBuilder().makeTruthVal(false)),
  292. getNoteTag(C, CastToTyVec, Call.getArgExpr(0), IsAnyKnown));
  293. }
  294. }
  295. //===----------------------------------------------------------------------===//
  296. // Evaluating cast, dyn_cast, cast_or_null, dyn_cast_or_null.
  297. //===----------------------------------------------------------------------===//
  298. static void evalNonNullParamNonNullReturn(const CallEvent &Call,
  299. DefinedOrUnknownSVal DV,
  300. CheckerContext &C,
  301. bool IsCheckedCast = false) {
  302. addCastTransition(Call, DV, C, /*IsNonNullParam=*/true,
  303. /*IsNonNullReturn=*/true, IsCheckedCast);
  304. }
  305. static void evalNonNullParamNullReturn(const CallEvent &Call,
  306. DefinedOrUnknownSVal DV,
  307. CheckerContext &C) {
  308. addCastTransition(Call, DV, C, /*IsNonNullParam=*/true,
  309. /*IsNonNullReturn=*/false);
  310. }
  311. static void evalNullParamNullReturn(const CallEvent &Call,
  312. DefinedOrUnknownSVal DV,
  313. CheckerContext &C) {
  314. if (ProgramStateRef State = C.getState()->assume(DV, false))
  315. C.addTransition(State->BindExpr(Call.getOriginExpr(),
  316. C.getLocationContext(),
  317. C.getSValBuilder().makeNull(), false),
  318. C.getNoteTag("Assuming null pointer is passed into cast",
  319. /*IsPrunable=*/true));
  320. }
  321. void CastValueChecker::evalCast(const CallEvent &Call, DefinedOrUnknownSVal DV,
  322. CheckerContext &C) const {
  323. evalNonNullParamNonNullReturn(Call, DV, C, /*IsCheckedCast=*/true);
  324. }
  325. void CastValueChecker::evalDynCast(const CallEvent &Call,
  326. DefinedOrUnknownSVal DV,
  327. CheckerContext &C) const {
  328. evalNonNullParamNonNullReturn(Call, DV, C);
  329. evalNonNullParamNullReturn(Call, DV, C);
  330. }
  331. void CastValueChecker::evalCastOrNull(const CallEvent &Call,
  332. DefinedOrUnknownSVal DV,
  333. CheckerContext &C) const {
  334. evalNonNullParamNonNullReturn(Call, DV, C);
  335. evalNullParamNullReturn(Call, DV, C);
  336. }
  337. void CastValueChecker::evalDynCastOrNull(const CallEvent &Call,
  338. DefinedOrUnknownSVal DV,
  339. CheckerContext &C) const {
  340. evalNonNullParamNonNullReturn(Call, DV, C);
  341. evalNonNullParamNullReturn(Call, DV, C);
  342. evalNullParamNullReturn(Call, DV, C);
  343. }
  344. //===----------------------------------------------------------------------===//
  345. // Evaluating castAs, getAs.
  346. //===----------------------------------------------------------------------===//
  347. static void evalZeroParamNonNullReturn(const CallEvent &Call,
  348. DefinedOrUnknownSVal DV,
  349. CheckerContext &C,
  350. bool IsCheckedCast = false) {
  351. addCastTransition(Call, DV, C, /*IsNonNullParam=*/true,
  352. /*IsNonNullReturn=*/true, IsCheckedCast);
  353. }
  354. static void evalZeroParamNullReturn(const CallEvent &Call,
  355. DefinedOrUnknownSVal DV,
  356. CheckerContext &C) {
  357. addCastTransition(Call, DV, C, /*IsNonNullParam=*/true,
  358. /*IsNonNullReturn=*/false);
  359. }
  360. void CastValueChecker::evalCastAs(const CallEvent &Call,
  361. DefinedOrUnknownSVal DV,
  362. CheckerContext &C) const {
  363. evalZeroParamNonNullReturn(Call, DV, C, /*IsCheckedCast=*/true);
  364. }
  365. void CastValueChecker::evalGetAs(const CallEvent &Call, DefinedOrUnknownSVal DV,
  366. CheckerContext &C) const {
  367. evalZeroParamNonNullReturn(Call, DV, C);
  368. evalZeroParamNullReturn(Call, DV, C);
  369. }
  370. //===----------------------------------------------------------------------===//
  371. // Evaluating isa, isa_and_nonnull.
  372. //===----------------------------------------------------------------------===//
  373. void CastValueChecker::evalIsa(const CallEvent &Call, DefinedOrUnknownSVal DV,
  374. CheckerContext &C) const {
  375. ProgramStateRef NonNullState, NullState;
  376. std::tie(NonNullState, NullState) = C.getState()->assume(DV);
  377. if (NonNullState) {
  378. addInstanceOfTransition(Call, DV, NonNullState, C, /*IsInstanceOf=*/true);
  379. addInstanceOfTransition(Call, DV, NonNullState, C, /*IsInstanceOf=*/false);
  380. }
  381. if (NullState) {
  382. C.generateSink(NullState, C.getPredecessor());
  383. }
  384. }
  385. void CastValueChecker::evalIsaAndNonNull(const CallEvent &Call,
  386. DefinedOrUnknownSVal DV,
  387. CheckerContext &C) const {
  388. ProgramStateRef NonNullState, NullState;
  389. std::tie(NonNullState, NullState) = C.getState()->assume(DV);
  390. if (NonNullState) {
  391. addInstanceOfTransition(Call, DV, NonNullState, C, /*IsInstanceOf=*/true);
  392. addInstanceOfTransition(Call, DV, NonNullState, C, /*IsInstanceOf=*/false);
  393. }
  394. if (NullState) {
  395. addInstanceOfTransition(Call, DV, NullState, C, /*IsInstanceOf=*/false);
  396. }
  397. }
  398. //===----------------------------------------------------------------------===//
  399. // Main logic to evaluate a call.
  400. //===----------------------------------------------------------------------===//
  401. bool CastValueChecker::evalCall(const CallEvent &Call,
  402. CheckerContext &C) const {
  403. const auto *Lookup = CDM.lookup(Call);
  404. if (!Lookup)
  405. return false;
  406. const CastCheck &Check = Lookup->first;
  407. CallKind Kind = Lookup->second;
  408. Optional<DefinedOrUnknownSVal> DV;
  409. switch (Kind) {
  410. case CallKind::Function: {
  411. // We only model casts from pointers to pointers or from references
  412. // to references. Other casts are most likely specialized and we
  413. // cannot model them.
  414. QualType ParamT = Call.parameters()[0]->getType();
  415. QualType ResultT = Call.getResultType();
  416. if (!(ParamT->isPointerType() && ResultT->isPointerType()) &&
  417. !(ParamT->isReferenceType() && ResultT->isReferenceType())) {
  418. return false;
  419. }
  420. DV = Call.getArgSVal(0).getAs<DefinedOrUnknownSVal>();
  421. break;
  422. }
  423. case CallKind::InstanceOf: {
  424. // We need to obtain the only template argument to determinte the type.
  425. const FunctionDecl *FD = Call.getDecl()->getAsFunction();
  426. if (!FD || !FD->getTemplateSpecializationArgs())
  427. return false;
  428. DV = Call.getArgSVal(0).getAs<DefinedOrUnknownSVal>();
  429. break;
  430. }
  431. case CallKind::Method:
  432. const auto *InstanceCall = dyn_cast<CXXInstanceCall>(&Call);
  433. if (!InstanceCall)
  434. return false;
  435. DV = InstanceCall->getCXXThisVal().getAs<DefinedOrUnknownSVal>();
  436. break;
  437. }
  438. if (!DV)
  439. return false;
  440. Check(this, Call, *DV, C);
  441. return true;
  442. }
  443. void CastValueChecker::checkDeadSymbols(SymbolReaper &SR,
  444. CheckerContext &C) const {
  445. C.addTransition(removeDeadCasts(C.getState(), SR));
  446. }
  447. void ento::registerCastValueChecker(CheckerManager &Mgr) {
  448. Mgr.registerChecker<CastValueChecker>();
  449. }
  450. bool ento::shouldRegisterCastValueChecker(const CheckerManager &mgr) {
  451. return true;
  452. }