=?utf-8?q?Donát?= Nagy <donat.n...@ericsson.com>, =?utf-8?q?Donát?= Nagy <donat.n...@ericsson.com>, =?utf-8?q?Donát?= Nagy <donat.n...@ericsson.com> Message-ID: In-Reply-To: <llvm/llvm-project/pull/67572/cl...@github.com>
================ @@ -32,42 +32,72 @@ using namespace taint; namespace { class ArrayBoundCheckerV2 : public Checker<check::Location> { - mutable std::unique_ptr<BugType> BT; - mutable std::unique_ptr<BugType> TaintBT; + BugType BT{this, "Out-of-bound access"}; + BugType TaintBT{this, "Out-of-bound access", categories::TaintedData}; - enum OOB_Kind { OOB_Precedes, OOB_Excedes }; + enum OOB_Kind { OOB_Precedes, OOB_Exceeds, OOB_Taint }; - void reportOOB(CheckerContext &C, ProgramStateRef errorState, - OOB_Kind kind) const; - void reportTaintOOB(CheckerContext &C, ProgramStateRef errorState, - SVal TaintedSVal) const; + void reportOOB(CheckerContext &C, ProgramStateRef ErrorState, OOB_Kind Kind, + SVal TaintedSVal = UnknownVal()) const; static bool isFromCtypeMacro(const Stmt *S, ASTContext &AC); public: void checkLocation(SVal l, bool isLoad, const Stmt *S, CheckerContext &C) const; }; +} // anonymous namespace -// FIXME: Eventually replace RegionRawOffset with this class. -class RegionRawOffsetV2 { -private: - const SubRegion *baseRegion; - NonLoc byteOffset; +/// For a given Location that can be represented as a symbolic expression +/// Arr[Idx] (or perhaps Arr[Idx1][Idx2] etc.), return the parent memory block +/// Arr and the distance of Location from the beginning of Arr (expressed in a +/// NonLoc that specifies the number of CharUnits). Returns nullopt when these +/// cannot be determined. +std::optional<std::pair<const SubRegion *, NonLoc>> +computeOffset(ProgramStateRef State, SValBuilder &SVB, SVal Location) { + QualType T = SVB.getArrayIndexType(); + auto Calc = [&SVB, State, T](BinaryOperatorKind Op, NonLoc LHS, NonLoc RHS) { + // We will use this utility to add and multiply values. + return SVB.evalBinOpNN(State, Op, LHS, RHS, T).getAs<NonLoc>(); + }; -public: - RegionRawOffsetV2(const SubRegion *base, NonLoc offset) - : baseRegion(base), byteOffset(offset) { assert(base); } + const auto *Region = dyn_cast_or_null<SubRegion>(Location.getAsRegion()); + std::optional<NonLoc> Offset = std::nullopt; + + while (const auto *ERegion = dyn_cast_or_null<ElementRegion>(Region)) { + const auto Index = ERegion->getIndex().getAs<NonLoc>(); + if (!Index) + return std::nullopt; + + QualType ElemType = ERegion->getElementType(); + // If the element is an incomplete type, go no further. + if (ElemType->isIncompleteType()) ---------------- DonatNagyE wrote: The testsuite passed with `assert(!ElemType->isIncompleteType());` instead of the early return. I also analyzed some open source projects (ffmpeg, postgres, xerces) with that assertion and it wasn't triggered on them. However, I don't remove the early return in this commit because I don't want to risk a revert; but I added a FIXME that it should be removed in the future (and I'll probably do it soon in a stand-alone commit). https://github.com/llvm/llvm-project/pull/67572 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits