//--------------------------------------------------------- bool isPromotionCast(const CastExpr* CE) { QualType destType = CE->getType(); QualType srcType = CE->getSubExpr()->getType(); return (destType->isRealFloatingType() && srcType->isRealFloatingType()) || (destType->isSignedIntegerType() && srcType->isSignedIntegerType()) || (destType->isUnsignedIntegerType() && srcType->isUnsignedIntegerType()); }
/// Apply implicit constraints for bitwise OR- and AND-. /// For unsigned types, bitwise OR with a constant always returns /// a value greater-or-equal than the constant, and bitwise AND /// returns a value less-or-equal then the constant. /// /// Pattern matches the expression \p Sym against those rule, /// and applies the required constraints. /// \p Input Previously established expression range set static RangeSet applyBitwiseConstraints( BasicValueFactory &BV, RangeSet::Factory &F, RangeSet Input, const SymIntExpr* SIE) { QualType T = SIE->getType(); bool IsUnsigned = T->isUnsignedIntegerType(); const llvm::APSInt &RHS = SIE->getRHS(); const llvm::APSInt &Zero = BV.getAPSIntType(T).getZeroValue(); BinaryOperator::Opcode Operator = SIE->getOpcode(); // For unsigned types, the output of bitwise-or is bigger-or-equal than RHS. if (Operator == BO_Or && IsUnsigned) return Input.Intersect(BV, F, RHS, BV.getMaxValue(T)); // Bitwise-or with a non-zero constant is always non-zero. if (Operator == BO_Or && RHS != Zero) return assumeNonZero(BV, F, SIE, Input); // For unsigned types, or positive RHS, // bitwise-and output is always smaller-or-equal than RHS (assuming two's // complement representation of signed types). if (Operator == BO_And && (IsUnsigned || RHS >= Zero)) return Input.Intersect(BV, F, BV.getMinValue(T), RHS); return Input; }
// Handles casts of type CK_IntegralCast. // At the moment, this function will redirect to evalCast, except when the range // of the original value is known to be greater than the max of the target type. SVal SValBuilder::evalIntegralCast(ProgramStateRef state, SVal val, QualType castTy, QualType originalTy) { // No truncations if target type is big enough. if (getContext().getTypeSize(castTy) >= getContext().getTypeSize(originalTy)) return evalCast(val, castTy, originalTy); const SymExpr *se = val.getAsSymbolicExpression(); if (!se) // Let evalCast handle non symbolic expressions. return evalCast(val, castTy, originalTy); // Find the maximum value of the target type. APSIntType ToType(getContext().getTypeSize(castTy), castTy->isUnsignedIntegerType()); llvm::APSInt ToTypeMax = ToType.getMaxValue(); NonLoc ToTypeMaxVal = makeIntVal(ToTypeMax.isUnsigned() ? ToTypeMax.getZExtValue() : ToTypeMax.getSExtValue(), castTy) .castAs<NonLoc>(); // Check the range of the symbol being casted against the maximum value of the // target type. NonLoc FromVal = val.castAs<NonLoc>(); QualType CmpTy = getConditionType(); NonLoc CompVal = evalBinOpNN(state, BO_LE, FromVal, ToTypeMaxVal, CmpTy).castAs<NonLoc>(); ProgramStateRef IsNotTruncated, IsTruncated; std::tie(IsNotTruncated, IsTruncated) = state->assume(CompVal); if (!IsNotTruncated && IsTruncated) { // Symbol is truncated so we evaluate it as a cast. NonLoc CastVal = makeNonLoc(se, originalTy, castTy); return CastVal; } return evalCast(val, castTy, originalTy); }
SVal GRSimpleVals::EvalCast(GRExprEngine& Eng, Loc X, QualType T) { // Casts from pointers -> pointers, just return the lval. // // Casts from pointers -> references, just return the lval. These // can be introduced by the frontend for corner cases, e.g // casting from va_list* to __builtin_va_list&. // assert (!X.isUnknownOrUndef()); if (Loc::IsLocType(T) || T->isReferenceType()) return X; // FIXME: Handle transparent unions where a value can be "transparently" // lifted into a union type. if (T->isUnionType()) return UnknownVal(); assert (T->isIntegerType()); BasicValueFactory& BasicVals = Eng.getBasicVals(); unsigned BitWidth = Eng.getContext().getTypeSize(T); if (!isa<loc::ConcreteInt>(X)) return nonloc::LocAsInteger::Make(BasicVals, X, BitWidth); llvm::APSInt V = cast<loc::ConcreteInt>(X).getValue(); V.setIsUnsigned(T->isUnsignedIntegerType() || Loc::IsLocType(T)); V.extOrTrunc(BitWidth); return nonloc::ConcreteInt(BasicVals.getValue(V)); }
bool ConversionChecker::isLossOfSign(const ImplicitCastExpr *Cast, CheckerContext &C) const { QualType CastType = Cast->getType(); QualType SubType = Cast->IgnoreParenImpCasts()->getType(); if (!CastType->isUnsignedIntegerType() || !SubType->isSignedIntegerType()) return false; return C.isNegative(Cast->getSubExpr()); }
SVal GRSimpleVals::EvalCast(GRExprEngine& Eng, NonLoc X, QualType T) { if (!isa<nonloc::ConcreteInt>(X)) return UnknownVal(); bool isLocType = Loc::IsLocType(T); // Only handle casts from integers to integers. if (!isLocType && !T->isIntegerType()) return UnknownVal(); BasicValueFactory& BasicVals = Eng.getBasicVals(); llvm::APSInt V = cast<nonloc::ConcreteInt>(X).getValue(); V.setIsUnsigned(T->isUnsignedIntegerType() || Loc::IsLocType(T)); V.extOrTrunc(Eng.getContext().getTypeSize(T)); if (isLocType) return loc::ConcreteInt(BasicVals.getValue(V)); else return nonloc::ConcreteInt(BasicVals.getValue(V)); }
bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx, bool IsObjCLiteral) { // %n is different from other conversion specifiers; don't try to fix it. if (CS.getKind() == ConversionSpecifier::nArg) return false; // Handle Objective-C objects first. Note that while the '%@' specifier will // not warn for structure pointer or void pointer arguments (because that's // how CoreFoundation objects are implemented), we only show a fixit for '%@' // if we know it's an object (block, id, class, or __attribute__((NSObject))). if (QT->isObjCRetainableType()) { if (!IsObjCLiteral) return false; CS.setKind(ConversionSpecifier::ObjCObjArg); // Disable irrelevant flags HasThousandsGrouping = false; HasPlusPrefix = false; HasSpacePrefix = false; HasAlternativeForm = false; HasLeadingZeroes = false; Precision.setHowSpecified(OptionalAmount::NotSpecified); LM.setKind(LengthModifier::None); return true; } // Handle strings next (char *, wchar_t *) if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { CS.setKind(ConversionSpecifier::sArg); // Disable irrelevant flags HasAlternativeForm = 0; HasLeadingZeroes = 0; // Set the long length modifier for wide characters if (QT->getPointeeType()->isWideCharType()) LM.setKind(LengthModifier::AsWideChar); else LM.setKind(LengthModifier::None); return true; } // If it's an enum, get its underlying type. if (const EnumType *ETy = QT->getAs<EnumType>()) QT = ETy->getDecl()->getIntegerType(); // We can only work with builtin types. const BuiltinType *BT = QT->getAs<BuiltinType>(); if (!BT) return false; // Set length modifier switch (BT->getKind()) { case BuiltinType::Bool: case BuiltinType::WChar_U: case BuiltinType::WChar_S: case BuiltinType::Char16: case BuiltinType::Char32: case BuiltinType::UInt128: case BuiltinType::Int128: case BuiltinType::Half: case BuiltinType::Float128: // Various types which are non-trivial to correct. return false; #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" #define SIGNED_TYPE(Id, SingletonId) #define UNSIGNED_TYPE(Id, SingletonId) #define FLOATING_TYPE(Id, SingletonId) #define BUILTIN_TYPE(Id, SingletonId) \ case BuiltinType::Id: #include "clang/AST/BuiltinTypes.def" // Misc other stuff which doesn't make sense here. return false; case BuiltinType::UInt: case BuiltinType::Int: case BuiltinType::Float: case BuiltinType::Double: LM.setKind(LengthModifier::None); break; case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::Char_S: case BuiltinType::SChar: LM.setKind(LengthModifier::AsChar); break; case BuiltinType::Short: case BuiltinType::UShort: LM.setKind(LengthModifier::AsShort); break; case BuiltinType::Long: case BuiltinType::ULong: LM.setKind(LengthModifier::AsLong); break; case BuiltinType::LongLong: case BuiltinType::ULongLong: LM.setKind(LengthModifier::AsLongLong); break; case BuiltinType::LongDouble: LM.setKind(LengthModifier::AsLongDouble); break; } // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11)) namedTypeToLengthModifier(QT, LM); // If fixing the length modifier was enough, we might be done. if (hasValidLengthModifier(Ctx.getTargetInfo())) { // If we're going to offer a fix anyway, make sure the sign matches. switch (CS.getKind()) { case ConversionSpecifier::uArg: case ConversionSpecifier::UArg: if (QT->isSignedIntegerType()) CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg); break; case ConversionSpecifier::dArg: case ConversionSpecifier::DArg: case ConversionSpecifier::iArg: if (QT->isUnsignedIntegerType() && !HasPlusPrefix) CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg); break; default: // Other specifiers do not have signed/unsigned variants. break; } const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral); if (ATR.isValid() && ATR.matchesType(Ctx, QT)) return true; } // Set conversion specifier and disable any flags which do not apply to it. // Let typedefs to char fall through to int, as %c is silly for uint8_t. if (!isa<TypedefType>(QT) && QT->isCharType()) { CS.setKind(ConversionSpecifier::cArg); LM.setKind(LengthModifier::None); Precision.setHowSpecified(OptionalAmount::NotSpecified); HasAlternativeForm = 0; HasLeadingZeroes = 0; HasPlusPrefix = 0; } // Test for Floating type first as LongDouble can pass isUnsignedIntegerType else if (QT->isRealFloatingType()) { CS.setKind(ConversionSpecifier::fArg); } else if (QT->isSignedIntegerType()) { CS.setKind(ConversionSpecifier::dArg); HasAlternativeForm = 0; } else if (QT->isUnsignedIntegerType()) { CS.setKind(ConversionSpecifier::uArg); HasAlternativeForm = 0; HasPlusPrefix = 0; } else { llvm_unreachable("Unexpected type"); } return true; }
bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt) { if (!QT->isPointerType()) return false; QualType PT = QT->getPointeeType(); const BuiltinType *BT = PT->getAs<BuiltinType>(); if (!BT) return false; // Pointer to a character. if (PT->isAnyCharacterType()) { CS.setKind(ConversionSpecifier::sArg); if (PT->isWideCharType()) LM.setKind(LengthModifier::AsWideChar); else LM.setKind(LengthModifier::None); return true; } // Figure out the length modifier. switch (BT->getKind()) { // no modifier case BuiltinType::UInt: case BuiltinType::Int: case BuiltinType::Float: LM.setKind(LengthModifier::None); break; // hh case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::Char_S: case BuiltinType::SChar: LM.setKind(LengthModifier::AsChar); break; // h case BuiltinType::Short: case BuiltinType::UShort: LM.setKind(LengthModifier::AsShort); break; // l case BuiltinType::Long: case BuiltinType::ULong: case BuiltinType::Double: LM.setKind(LengthModifier::AsLong); break; // ll case BuiltinType::LongLong: case BuiltinType::ULongLong: LM.setKind(LengthModifier::AsLongLong); break; // L case BuiltinType::LongDouble: LM.setKind(LengthModifier::AsLongDouble); break; // Don't know. default: return false; } // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus0x)) { const IdentifierInfo *Identifier = QT.getBaseTypeIdentifier(); if (Identifier->getName() == "size_t") { LM.setKind(LengthModifier::AsSizeT); } else if (Identifier->getName() == "ssize_t") { // Not C99, but common in Unix. LM.setKind(LengthModifier::AsSizeT); } else if (Identifier->getName() == "intmax_t") { LM.setKind(LengthModifier::AsIntMax); } else if (Identifier->getName() == "uintmax_t") { LM.setKind(LengthModifier::AsIntMax); } else if (Identifier->getName() == "ptrdiff_t") { LM.setKind(LengthModifier::AsPtrDiff); } } // Figure out the conversion specifier. if (PT->isRealFloatingType()) CS.setKind(ConversionSpecifier::fArg); else if (PT->isSignedIntegerType()) CS.setKind(ConversionSpecifier::dArg); else if (PT->isUnsignedIntegerType()) { // Preserve the original formatting, e.g. 'X', 'o'. if (!CS.isUIntArg()) { CS.setKind(ConversionSpecifier::uArg); } } else llvm_unreachable("Unexpected type"); return true; }
bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt) { // Handle strings first (char *, wchar_t *) if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { CS.setKind(ConversionSpecifier::sArg); // Disable irrelevant flags HasAlternativeForm = 0; HasLeadingZeroes = 0; // Set the long length modifier for wide characters if (QT->getPointeeType()->isWideCharType()) LM.setKind(LengthModifier::AsWideChar); else LM.setKind(LengthModifier::None); return true; } // We can only work with builtin types. const BuiltinType *BT = QT->getAs<BuiltinType>(); if (!BT) return false; // Set length modifier switch (BT->getKind()) { case BuiltinType::Bool: case BuiltinType::WChar_U: case BuiltinType::WChar_S: case BuiltinType::Char16: case BuiltinType::Char32: case BuiltinType::UInt128: case BuiltinType::Int128: case BuiltinType::Half: // Various types which are non-trivial to correct. return false; #define SIGNED_TYPE(Id, SingletonId) #define UNSIGNED_TYPE(Id, SingletonId) #define FLOATING_TYPE(Id, SingletonId) #define BUILTIN_TYPE(Id, SingletonId) \ case BuiltinType::Id: #include "clang/AST/BuiltinTypes.def" // Misc other stuff which doesn't make sense here. return false; case BuiltinType::UInt: case BuiltinType::Int: case BuiltinType::Float: case BuiltinType::Double: LM.setKind(LengthModifier::None); break; case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::Char_S: case BuiltinType::SChar: LM.setKind(LengthModifier::AsChar); break; case BuiltinType::Short: case BuiltinType::UShort: LM.setKind(LengthModifier::AsShort); break; case BuiltinType::Long: case BuiltinType::ULong: LM.setKind(LengthModifier::AsLong); break; case BuiltinType::LongLong: case BuiltinType::ULongLong: LM.setKind(LengthModifier::AsLongLong); break; case BuiltinType::LongDouble: LM.setKind(LengthModifier::AsLongDouble); break; } // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus0x)) { const IdentifierInfo *Identifier = QT.getBaseTypeIdentifier(); if (Identifier->getName() == "size_t") { LM.setKind(LengthModifier::AsSizeT); } else if (Identifier->getName() == "ssize_t") { // Not C99, but common in Unix. LM.setKind(LengthModifier::AsSizeT); } else if (Identifier->getName() == "intmax_t") { LM.setKind(LengthModifier::AsIntMax); } else if (Identifier->getName() == "uintmax_t") { LM.setKind(LengthModifier::AsIntMax); } else if (Identifier->getName() == "ptrdiff_t") { LM.setKind(LengthModifier::AsPtrDiff); } } // Set conversion specifier and disable any flags which do not apply to it. // Let typedefs to char fall through to int, as %c is silly for uint8_t. if (isa<TypedefType>(QT) && QT->isAnyCharacterType()) { CS.setKind(ConversionSpecifier::cArg); LM.setKind(LengthModifier::None); Precision.setHowSpecified(OptionalAmount::NotSpecified); HasAlternativeForm = 0; HasLeadingZeroes = 0; HasPlusPrefix = 0; } // Test for Floating type first as LongDouble can pass isUnsignedIntegerType else if (QT->isRealFloatingType()) { CS.setKind(ConversionSpecifier::fArg); } else if (QT->isSignedIntegerType()) { CS.setKind(ConversionSpecifier::dArg); HasAlternativeForm = 0; } else if (QT->isUnsignedIntegerType()) { // Preserve the original formatting, e.g. 'X', 'o'. if (!cast<PrintfConversionSpecifier>(CS).isUIntArg()) CS.setKind(ConversionSpecifier::uArg); HasAlternativeForm = 0; HasPlusPrefix = 0; } else { llvm_unreachable("Unexpected type"); } return true; }
bool ScanfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx) { if (!QT->isPointerType()) return false; // %n is different from other conversion specifiers; don't try to fix it. if (CS.getKind() == ConversionSpecifier::nArg) return false; QualType PT = QT->getPointeeType(); // If it's an enum, get its underlying type. if (const EnumType *ETy = QT->getAs<EnumType>()) QT = ETy->getDecl()->getIntegerType(); const BuiltinType *BT = PT->getAs<BuiltinType>(); if (!BT) return false; // Pointer to a character. if (PT->isAnyCharacterType()) { CS.setKind(ConversionSpecifier::sArg); if (PT->isWideCharType()) LM.setKind(LengthModifier::AsWideChar); else LM.setKind(LengthModifier::None); return true; } // Figure out the length modifier. switch (BT->getKind()) { // no modifier case BuiltinType::UInt: case BuiltinType::Int: case BuiltinType::Float: LM.setKind(LengthModifier::None); break; // hh case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::Char_S: case BuiltinType::SChar: LM.setKind(LengthModifier::AsChar); break; // h case BuiltinType::Short: case BuiltinType::UShort: LM.setKind(LengthModifier::AsShort); break; // l case BuiltinType::Long: case BuiltinType::ULong: case BuiltinType::Double: LM.setKind(LengthModifier::AsLong); break; // ll case BuiltinType::LongLong: case BuiltinType::ULongLong: LM.setKind(LengthModifier::AsLongLong); break; // L case BuiltinType::LongDouble: LM.setKind(LengthModifier::AsLongDouble); break; // Don't know. default: return false; } // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. if (isa<TypedefType>(PT) && (LangOpt.F90 || LangOpt.F90)) namedTypeToLengthModifier(PT, LM); // If fixing the length modifier was enough, we are done. if (hasValidLengthModifier(Ctx.getTargetInfo())) { const analyze_scanf::ArgType &AT = getArgType(Ctx); if (AT.isValid() && AT.matchesType(Ctx, QT)) return true; } // Figure out the conversion specifier. if (PT->isRealFloatingType()) CS.setKind(ConversionSpecifier::fArg); else if (PT->isSignedIntegerType()) CS.setKind(ConversionSpecifier::dArg); else if (PT->isUnsignedIntegerType()) CS.setKind(ConversionSpecifier::uArg); else llvm_unreachable("Unexpected type"); return true; }
bool PrintfSpecifier::fixType(QualType QT) { // Handle strings first (char *, wchar_t *) if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { CS.setKind(ConversionSpecifier::sArg); // Disable irrelevant flags HasAlternativeForm = 0; HasLeadingZeroes = 0; // Set the long length modifier for wide characters if (QT->getPointeeType()->isWideCharType()) LM.setKind(LengthModifier::AsWideChar); return true; } // We can only work with builtin types. if (!QT->isBuiltinType()) return false; // Everything else should be a base type const BuiltinType *BT = QT->getAs<BuiltinType>(); // Set length modifier switch (BT->getKind()) { default: // The rest of the conversions are either optional or for non-builtin types LM.setKind(LengthModifier::None); break; case BuiltinType::WChar: case BuiltinType::Long: case BuiltinType::ULong: LM.setKind(LengthModifier::AsLong); break; case BuiltinType::LongLong: case BuiltinType::ULongLong: LM.setKind(LengthModifier::AsLongLong); break; case BuiltinType::LongDouble: LM.setKind(LengthModifier::AsLongDouble); break; } // Set conversion specifier and disable any flags which do not apply to it. if (QT->isAnyCharacterType()) { CS.setKind(ConversionSpecifier::cArg); Precision.setHowSpecified(OptionalAmount::NotSpecified); HasAlternativeForm = 0; HasLeadingZeroes = 0; HasPlusPrefix = 0; } // Test for Floating type first as LongDouble can pass isUnsignedIntegerType else if (QT->isRealFloatingType()) { CS.setKind(ConversionSpecifier::fArg); } else if (QT->isPointerType()) { CS.setKind(ConversionSpecifier::pArg); Precision.setHowSpecified(OptionalAmount::NotSpecified); HasAlternativeForm = 0; HasLeadingZeroes = 0; HasPlusPrefix = 0; } else if (QT->isSignedIntegerType()) { CS.setKind(ConversionSpecifier::dArg); HasAlternativeForm = 0; } else if (QT->isUnsignedIntegerType()) { CS.setKind(ConversionSpecifier::uArg); HasAlternativeForm = 0; HasPlusPrefix = 0; } else { return false; } return true; }
const GRState *SimpleConstraintManager::AssumeSymRel(const GRState *state, const SymExpr *LHS, BinaryOperator::Opcode op, const llvm::APSInt& Int) { assert(BinaryOperator::isComparisonOp(op) && "Non-comparison ops should be rewritten as comparisons to zero."); // We only handle simple comparisons of the form "$sym == constant" // or "($sym+constant1) == constant2". // The adjustment is "constant1" in the above expression. It's used to // "slide" the solution range around for modular arithmetic. For example, // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to // the subclasses of SimpleConstraintManager to handle the adjustment. llvm::APSInt Adjustment; // First check if the LHS is a simple symbol reference. SymbolRef Sym = dyn_cast<SymbolData>(LHS); if (Sym) { Adjustment = 0; } else { // Next, see if it's a "($sym+constant1)" expression. const SymIntExpr *SE = dyn_cast<SymIntExpr>(LHS); // We don't handle "($sym1+$sym2)". // Give up and assume the constraint is feasible. if (!SE) return state; // We don't handle "(<expr>+constant1)". // Give up and assume the constraint is feasible. Sym = dyn_cast<SymbolData>(SE->getLHS()); if (!Sym) return state; // Get the constant out of the expression "($sym+constant1)". switch (SE->getOpcode()) { case BO_Add: Adjustment = SE->getRHS(); break; case BO_Sub: Adjustment = -SE->getRHS(); break; default: // We don't handle non-additive operators. // Give up and assume the constraint is feasible. return state; } } // FIXME: This next section is a hack. It silently converts the integers to // be of the same type as the symbol, which is not always correct. Really the // comparisons should be performed using the Int's type, then mapped back to // the symbol's range of values. GRStateManager &StateMgr = state->getStateManager(); ASTContext &Ctx = StateMgr.getContext(); QualType T = Sym->getType(Ctx); assert(T->isIntegerType() || Loc::IsLocType(T)); unsigned bitwidth = Ctx.getTypeSize(T); bool isSymUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T); // Convert the adjustment. Adjustment.setIsUnsigned(isSymUnsigned); Adjustment.extOrTrunc(bitwidth); // Convert the right-hand side integer. llvm::APSInt ConvertedInt(Int, isSymUnsigned); ConvertedInt.extOrTrunc(bitwidth); switch (op) { default: // No logic yet for other operators. Assume the constraint is feasible. return state; case BO_EQ: return AssumeSymEQ(state, Sym, ConvertedInt, Adjustment); case BO_NE: return AssumeSymNE(state, Sym, ConvertedInt, Adjustment); case BO_GT: return AssumeSymGT(state, Sym, ConvertedInt, Adjustment); case BO_GE: return AssumeSymGE(state, Sym, ConvertedInt, Adjustment); case BO_LT: return AssumeSymLT(state, Sym, ConvertedInt, Adjustment); case BO_LE: return AssumeSymLE(state, Sym, ConvertedInt, Adjustment); } // end switch }
void IntegerOverflowChecker::checkPostStmt(const BinaryOperator *B, CheckerContext &C) const { if (OverflowLoc.find(B->getExprLoc()) != OverflowLoc.end()) return; if (!B->getLHS()->getType()->isIntegerType() || !B->getRHS()->getType()->isIntegerType()) return; ProgramStateRef State = C.getState(); QualType BinType = B->getType(); const Expr *ExprLhs = B->getLHS(); const Expr *ExprRhs = B->getRHS(); SVal Lhs = C.getSVal(ExprLhs); SVal Rhs = C.getSVal(ExprRhs); if (makeGlobalsMembersHeuristics(Lhs, ExprLhs, C)) { C.addTransition(addToWhiteList(Lhs, State)); return; } if (makeGlobalsMembersHeuristics(Rhs, ExprRhs, C)) { C.addTransition(addToWhiteList(Rhs, State)); return; } if (!Filter.CheckIntegerOverflowDef && BinType->isUnsignedIntegerType()) return; if (!Filter.CheckIntegerOverflowUndef && BinType->isSignedIntegerType()) return; BinaryOperator::Opcode Op = B->getOpcode(); if (Op != BO_Add && Op != BO_Mul && Op != BO_Sub && Op != BO_AddAssign && Op != BO_MulAssign && Op != BO_SubAssign) return; Optional<DefinedOrUnknownSVal> CondOverflow; ProgramStateRef StateOverflow, StateNotOverflow; bool isOverflow = false; if (Op == BO_Add || Op == BO_AddAssign) CondOverflow = checkAdd(C, Lhs, Rhs, BinType, isOverflow); else if (Op == BO_Sub || Op == BO_SubAssign) { if ((BinType->isUnsignedIntegerType()) && makeUSubHeuristics(B)) return; CondOverflow = checkSub(C, Lhs, Rhs, BinType, isOverflow); } else if (Op == BO_Mul || Op == BO_MulAssign) CondOverflow = checkMul(C, Lhs, Rhs, BinType, isOverflow); if (!CondOverflow) return; std::tie(StateOverflow, StateNotOverflow) = State->assume(*CondOverflow); if (!StateOverflow || (StateNotOverflow && !(State->isTainted(Lhs) || State->isTainted(Rhs)))) return; std::string Msg = composeMsg(StateNotOverflow, Lhs, Rhs, ExprLhs, ExprRhs, B->getType()->isSignedIntegerOrEnumerationType(), isOverflow, &Op, C); reportBug(Msg, C, B->getExprLoc(), BinType->isSignedIntegerType()); }
void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, const Decl *TargetDecl, AttributeListType &PAL, unsigned &CallingConv) { unsigned FuncAttrs = 0; unsigned RetAttrs = 0; CallingConv = FI.getEffectiveCallingConvention(); // FIXME: handle sseregparm someday... if (TargetDecl) { if (TargetDecl->hasAttr<NoThrowAttr>()) FuncAttrs |= llvm::Attribute::NoUnwind; if (TargetDecl->hasAttr<NoReturnAttr>()) FuncAttrs |= llvm::Attribute::NoReturn; if (TargetDecl->hasAttr<ConstAttr>()) FuncAttrs |= llvm::Attribute::ReadNone; else if (TargetDecl->hasAttr<PureAttr>()) FuncAttrs |= llvm::Attribute::ReadOnly; if (TargetDecl->hasAttr<MallocAttr>()) RetAttrs |= llvm::Attribute::NoAlias; } if (CodeGenOpts.OptimizeSize) FuncAttrs |= llvm::Attribute::OptimizeForSize; if (CodeGenOpts.DisableRedZone) FuncAttrs |= llvm::Attribute::NoRedZone; if (CodeGenOpts.NoImplicitFloat) FuncAttrs |= llvm::Attribute::NoImplicitFloat; QualType RetTy = FI.getReturnType(); unsigned Index = 1; const ABIArgInfo &RetAI = FI.getReturnInfo(); switch (RetAI.getKind()) { case ABIArgInfo::Extend: if (RetTy->isSignedIntegerType()) { RetAttrs |= llvm::Attribute::SExt; } else if (RetTy->isUnsignedIntegerType()) { RetAttrs |= llvm::Attribute::ZExt; } // FALLTHROUGH case ABIArgInfo::Direct: break; case ABIArgInfo::Indirect: PAL.push_back(llvm::AttributeWithIndex::get(Index, llvm::Attribute::StructRet | llvm::Attribute::NoAlias)); ++Index; // sret disables readnone and readonly FuncAttrs &= ~(llvm::Attribute::ReadOnly | llvm::Attribute::ReadNone); break; case ABIArgInfo::Ignore: case ABIArgInfo::Coerce: break; case ABIArgInfo::Expand: assert(0 && "Invalid ABI kind for return argument"); } if (RetAttrs) PAL.push_back(llvm::AttributeWithIndex::get(0, RetAttrs)); // FIXME: we need to honour command line settings also... // FIXME: RegParm should be reduced in case of nested functions and/or global // register variable. signed RegParm = 0; if (TargetDecl) if (const RegparmAttr *RegParmAttr = TargetDecl->getAttr<RegparmAttr>()) RegParm = RegParmAttr->getNumParams(); unsigned PointerWidth = getContext().Target.getPointerWidth(0); for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); it != ie; ++it) { QualType ParamType = it->type; const ABIArgInfo &AI = it->info; unsigned Attributes = 0; switch (AI.getKind()) { case ABIArgInfo::Coerce: break; case ABIArgInfo::Indirect: if (AI.getIndirectByVal()) Attributes |= llvm::Attribute::ByVal; Attributes |= llvm::Attribute::constructAlignmentFromInt(AI.getIndirectAlign()); // byval disables readnone and readonly. FuncAttrs &= ~(llvm::Attribute::ReadOnly | llvm::Attribute::ReadNone); break; case ABIArgInfo::Extend: if (ParamType->isSignedIntegerType()) { Attributes |= llvm::Attribute::SExt; } else if (ParamType->isUnsignedIntegerType()) { Attributes |= llvm::Attribute::ZExt; } // FALLS THROUGH case ABIArgInfo::Direct: if (RegParm > 0 && (ParamType->isIntegerType() || ParamType->isPointerType())) { RegParm -= (Context.getTypeSize(ParamType) + PointerWidth - 1) / PointerWidth; if (RegParm >= 0) Attributes |= llvm::Attribute::InReg; } // FIXME: handle sseregparm someday... break; case ABIArgInfo::Ignore: // Skip increment, no matching LLVM parameter. continue; case ABIArgInfo::Expand: { std::vector<const llvm::Type*> Tys; // FIXME: This is rather inefficient. Do we ever actually need to do // anything here? The result should be just reconstructed on the other // side, so extension should be a non-issue. getTypes().GetExpandedTypes(ParamType, Tys); Index += Tys.size(); continue; } } if (Attributes) PAL.push_back(llvm::AttributeWithIndex::get(Index, Attributes)); ++Index; } if (FuncAttrs) PAL.push_back(llvm::AttributeWithIndex::get(~0, FuncAttrs)); }
bool PrintfSpecifier::fixType(QualType QT) { // Handle strings first (char *, wchar_t *) if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { CS.setKind(ConversionSpecifier::sArg); // Disable irrelevant flags HasAlternativeForm = 0; HasLeadingZeroes = 0; // Set the long length modifier for wide characters if (QT->getPointeeType()->isWideCharType()) LM.setKind(LengthModifier::AsWideChar); return true; } // We can only work with builtin types. if (!QT->isBuiltinType()) return false; // Everything else should be a base type const BuiltinType *BT = QT->getAs<BuiltinType>(); // Set length modifier switch (BT->getKind()) { case BuiltinType::Bool: case BuiltinType::WChar_U: case BuiltinType::WChar_S: case BuiltinType::Char16: case BuiltinType::Char32: case BuiltinType::UInt128: case BuiltinType::Int128: // Integral types which are non-trivial to correct. return false; case BuiltinType::Void: case BuiltinType::NullPtr: case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: case BuiltinType::Dependent: case BuiltinType::Overload: case BuiltinType::BoundMember: case BuiltinType::UnknownAny: // Misc other stuff which doesn't make sense here. return false; case BuiltinType::UInt: case BuiltinType::Int: case BuiltinType::Float: case BuiltinType::Double: LM.setKind(LengthModifier::None); break; case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::Char_S: case BuiltinType::SChar: LM.setKind(LengthModifier::AsChar); break; case BuiltinType::Short: case BuiltinType::UShort: LM.setKind(LengthModifier::AsShort); break; case BuiltinType::Long: case BuiltinType::ULong: LM.setKind(LengthModifier::AsLong); break; case BuiltinType::LongLong: case BuiltinType::ULongLong: LM.setKind(LengthModifier::AsLongLong); break; case BuiltinType::LongDouble: LM.setKind(LengthModifier::AsLongDouble); break; } // Set conversion specifier and disable any flags which do not apply to it. // Let typedefs to char fall through to int, as %c is silly for uint8_t. if (isa<TypedefType>(QT) && QT->isAnyCharacterType()) { CS.setKind(ConversionSpecifier::cArg); LM.setKind(LengthModifier::None); Precision.setHowSpecified(OptionalAmount::NotSpecified); HasAlternativeForm = 0; HasLeadingZeroes = 0; HasPlusPrefix = 0; } // Test for Floating type first as LongDouble can pass isUnsignedIntegerType else if (QT->isRealFloatingType()) { CS.setKind(ConversionSpecifier::fArg); } else if (QT->isSignedIntegerType()) { CS.setKind(ConversionSpecifier::dArg); HasAlternativeForm = 0; } else if (QT->isUnsignedIntegerType()) { // Preserve the original formatting, e.g. 'X', 'o'. if (!cast<PrintfConversionSpecifier>(CS).isUIntArg()) CS.setKind(ConversionSpecifier::uArg); HasAlternativeForm = 0; HasPlusPrefix = 0; } else { llvm_unreachable("Unexpected type"); } return true; }