void LiteralAnalyser::checkWidth(int availableWidth, const Limit* L, const Expr* Right, const char* tname) { APSInt Result = checkLiterals(Right); assert(Result.isSigned() && "TEMP FOR NOW"); int64_t value = Result.getSExtValue(); bool overflow = false; if (Result.isNegative()) { const int64_t limit = L->minVal; if (value < limit) overflow = true; } else { if (availableWidth == 64) { // NOTE: assume for now value always fits in uint64 } else { const int64_t limit = (int64_t)L->maxVal; if (value > limit) overflow = true; } } //fprintf(stderr, "VAL=%lld width=%d signed=%d\n", value, availableWidth, Result.isSigned()); if (overflow) { SmallString<20> ss; Result.toString(ss, 10, true); Diags.Report(Right->getLocStart(), diag::err_literal_outofbounds) << tname << L->minStr << L->maxStr << ss << Right->getSourceRange(); } }
void ExprEngine:: VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); QualType T = Ex->getTypeOfArgument(); if (Ex->getKind() == UETT_SizeOf) { if (!T->isIncompleteType() && !T->isConstantSizeType()) { assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); // FIXME: Add support for VLA type arguments and VLA expressions. // When that happens, we should probably refactor VLASizeChecker's code. return; } else if (T->getAs<ObjCObjectType>()) { // Some code tries to take the sizeof an ObjCObjectType, relying that // the compiler has laid out its representation. Just report Unknown // for these. return; } } APSInt Value = Ex->EvaluateKnownConstInt(getContext()); CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue()); ProgramStateRef state = Pred->getState(); state = state->BindExpr(Ex, Pred->getLocationContext(), svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType())); Bldr.generateNode(Ex, Pred, state); }
/// Decode a numeric leaf value that is known to be a uint64_t. Error llvm::codeview::consume_numeric(ArrayRef<uint8_t> &Data, uint64_t &Num) { APSInt N; if (auto EC = consume(Data, N)) return EC; if (N.isSigned() || !N.isIntN(64)) return make_error<CodeViewError>(cv_error_code::corrupt_record, "Data is not a numeric value!"); Num = N.getLimitedValue(); return Error::success(); }
void ExprEngine:: VisitOffsetOfExpr(const OffsetOfExpr *OOE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder B(Pred, Dst, *currBldrCtx); APSInt IV; if (OOE->EvaluateAsInt(IV, getContext())) { assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType())); assert(OOE->getType()->isIntegerType()); assert(IV.isSigned() == OOE->getType()->isSignedIntegerOrEnumerationType()); SVal X = svalBuilder.makeIntVal(IV); B.generateNode(OOE, Pred, Pred->getState()->BindExpr(OOE, Pred->getLocationContext(), X)); } // FIXME: Handle the case where __builtin_offsetof is not a constant. }
APSInt LiteralAnalyser::truncateLiteral(QualType TLeft, const Expr* Right, APSInt Orig) { int availableWidth = 0; // TODO needs cleanup (first check if conversions are ok, then check literal values?) if (!calcWidth(TLeft, Right, &availableWidth)) return APSInt(0); return Orig.trunc(availableWidth); }
void ExprEngine:: VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst) { // FIXME: Prechecks eventually go in ::Visit(). ExplodedNodeSet CheckedSet; getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, Ex, *this); ExplodedNodeSet EvalSet; StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); QualType T = Ex->getTypeOfArgument(); for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); I != E; ++I) { if (Ex->getKind() == UETT_SizeOf) { if (!T->isIncompleteType() && !T->isConstantSizeType()) { assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); // FIXME: Add support for VLA type arguments and VLA expressions. // When that happens, we should probably refactor VLASizeChecker's code. continue; } else if (T->getAs<ObjCObjectType>()) { // Some code tries to take the sizeof an ObjCObjectType, relying that // the compiler has laid out its representation. Just report Unknown // for these. continue; } } APSInt Value = Ex->EvaluateKnownConstInt(getContext()); CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue()); ProgramStateRef state = (*I)->getState(); state = state->BindExpr(Ex, (*I)->getLocationContext(), svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType())); Bldr.generateNode(Ex, *I, state); } getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this); }
APSInt LiteralAnalyser::checkArraySubscript(const Expr* Right) { const ArraySubscriptExpr* AS = cast<ArraySubscriptExpr>(Right); assert(AS); assert(isa<BitOffsetExpr>(AS->getIndex()) && "TODO only bitoffsets for now"); APSInt base = checkLiterals(AS->getBase()); const BitOffsetExpr* BO = cast<BitOffsetExpr>(AS->getIndex()); APSInt low = checkLiterals(BO->getRHS()); unsigned width = BO->getWidth(); // calculate result = ((base >> low) & bitmask(width)); uint64_t result = base.getZExtValue(); result >>= low.getZExtValue(); result &= Utils::bitmask(width); APSInt Result(64, false); Result = result; return Result; }
void ScalarTraits<APSInt>::output(const APSInt &S, void *, llvm::raw_ostream &OS) { S.print(OS, S.isSigned()); }
void ScalarTraits<APSInt>::output(const APSInt &S, void *, llvm::raw_ostream &OS) { S.print(OS, true); }
APSInt LiteralAnalyser::checkLiterals(const Expr* Right) { if (Right->getCTC() == CTC_NONE) return APSInt(64, false); APSInt result(64, false); switch (Right->getKind()) { case EXPR_INTEGER_LITERAL: return checkIntegerLiterals(Right); case EXPR_FLOAT_LITERAL: case EXPR_BOOL_LITERAL: break; case EXPR_CHAR_LITERAL: { const CharacterLiteral* C = cast<CharacterLiteral>(Right); result = APInt(64, C->getValue(), true); break; } case EXPR_STRING_LITERAL: break; case EXPR_NIL: break; case EXPR_IDENTIFIER: return checkDecl(cast<IdentifierExpr>(Right)->getDecl()); case EXPR_TYPE: case EXPR_CALL: case EXPR_INITLIST: break; case EXPR_DESIGNATOR_INIT: assert(0 && "TODO"); break; case EXPR_BINOP: return checkBinaryLiterals(Right); case EXPR_CONDOP: break; case EXPR_UNARYOP: return checkUnaryLiterals(Right); case EXPR_BUILTIN: { const BuiltinExpr* B = cast<BuiltinExpr>(Right); return B->getValue(); } case EXPR_ARRAYSUBSCRIPT: return checkArraySubscript(Right); case EXPR_MEMBER: { // Q: is this correct for Struct.Member? const MemberExpr* M = cast<MemberExpr>(Right); return checkDecl(M->getDecl()); } case EXPR_PAREN: { const ParenExpr* P = cast<ParenExpr>(Right); return checkLiterals(P->getExpr()); } case EXPR_BITOFFSET: assert(0 && "TODO"); break; case EXPR_CAST: { // a cast may change the value without warning const ExplicitCastExpr* E = cast<ExplicitCastExpr>(Right); APSInt Result = checkLiterals(E->getInner()); SmallString<20> ss; Result.toString(ss, 10, true); fprintf(stderr, "Original %s\n", ss.c_str()); return truncateLiteral(E->getDestType(), Right, Result); } } return result; }