67 logChecker(
"CheckType::checkTooBigBitwiseShift");
71 if (tok->isCpp() &&
Token::Match(tok,
"[;{}] %name% (") &&
Token::simpleMatch(tok->linkAt(2),
") ;") && tok->next()->isUpperCaseName() && !tok->next()->function())
74 if (!tok->astOperand1() || !tok->astOperand2())
81 const ValueType *
const lhstype = tok->astOperand1()->valueType();
88 if ((lhstype->
type == ValueType::Type::CHAR) ||
89 (lhstype->
type == ValueType::Type::SHORT) ||
90 (lhstype->
type == ValueType::Type::WCHAR_T) ||
91 (lhstype->
type == ValueType::Type::BOOL) ||
92 (lhstype->
type == ValueType::Type::INT))
94 else if (lhstype->
type == ValueType::Type::LONG)
96 else if (lhstype->
type == ValueType::Type::LONGLONG)
105 else if (lhstype->
sign == ValueType::Sign::SIGNED) {
106 value = tok->astOperand2()->getValueGE(lhsbits-1, *
mSettings);
115 constexpr
char id[] =
"shiftTooManyBits";
124 std::ostringstream errmsg;
125 errmsg <<
"Shifting " << lhsbits <<
"-bit value by " << rhsbits.
intvalue <<
" bits is undefined behaviour";
127 errmsg <<
". See condition at line " << rhsbits.
condition->
linenr() <<
".";
134 constexpr
char id[] =
"shiftTooManyBitsSigned";
138 std::string behaviour =
"undefined";
140 behaviour =
"implementation-defined";
155 std::ostringstream errmsg;
156 errmsg <<
"Shifting signed " << lhsbits <<
"-bit value by " << rhsbits.
intvalue <<
" bits is " + behaviour +
" behaviour";
158 errmsg <<
". See condition at line " << rhsbits.
condition->
linenr() <<
".";
173 logChecker(
"CheckType::checkIntegerOverflow");
176 if (!tok->isArithmeticalOp())
181 if (!vt || !vt->
isIntegral() || vt->
sign != ValueType::Sign::SIGNED)
185 if (vt->
type == ValueType::Type::INT)
187 else if (vt->
type == ValueType::Type::LONG)
189 else if (vt->
type == ValueType::Type::LONGLONG)
203 value = tok->getValueLE(-maxvalue - 2, *
mSettings);
222 " or there is signed integer overflow for expression '" + expr +
"'.";
224 msg =
"Signed integer overflow for expression '" + expr +
"'.";
227 msg =
"Safe checks: " + msg;
249 if (!tok->isArithmeticalOp() ||
Token::Match(tok,
"+|-"))
253 if (!(tok->valueType() && tok->valueType()->sign == ValueType::Sign::UNSIGNED))
258 for (
const Token * tok1 : astOperands) {
263 return !v.isImpossible() && v.isIntValue() && (v.intvalue <= -1 || v.wideintvalue <= -1);
267 if (tok1->valueType() && tok1->valueType()->sign != ValueType::Sign::UNSIGNED)
277 std::ostringstream msg;
279 msg <<
"$symbol:" << expr <<
"\n";
281 msg <<
"Expression '" << expr <<
"' has a negative value. That is converted to an unsigned value and used in an unsigned calculation.";
283 msg <<
"Expression '" << expr <<
"' can have a negative value. That is converted to an unsigned value and used in an unsigned calculation.";
288 const ErrorPath &errorPath =
getErrorPath(tok,negativeValue,
"Negative value is converted to an unsigned value");
304 static const std::pair<ValueType::Type, ValueType::Type> typeCombinations[] = {
305 { ValueType::Type::INT, ValueType::Type::LONG },
306 { ValueType::Type::INT, ValueType::Type::LONGLONG },
307 { ValueType::Type::LONG, ValueType::Type::LONGLONG },
308 { ValueType::Type::FLOAT, ValueType::Type::DOUBLE },
309 { ValueType::Type::FLOAT, ValueType::Type::LONGDOUBLE },
310 { ValueType::Type::DOUBLE, ValueType::Type::LONGDOUBLE },
318 if (!(sizeSrc > 0 && sizeTgt > 0 && sizeSrc < sizeTgt))
321 return std::any_of(std::begin(typeCombinations), std::end(typeCombinations), [&](
const std::pair<ValueType::Type, ValueType::Type>& p) {
322 return src.
type == p.first && tgt.
type == p.second;
335 if (tok->str() !=
"=" || !
Token::Match(tok->astOperand2(),
"*|<<") || tok->astOperand2()->isUnaryOp(
"*"))
338 if (tok->astOperand2()->hasKnownIntValue()) {
344 const ValueType *lhstype = tok->astOperand1() ? tok->astOperand1()->valueType() :
nullptr;
345 const ValueType *rhstype = tok->astOperand2()->valueType();
347 if (!lhstype || !rhstype)
371 const Token *ret =
nullptr;
373 if (tok->str() ==
"return") {
375 const ValueType *type = tok->astOperand1()->valueType();
396 const auto pos = typeStr.find(
"signed");
397 if (pos != std::string::npos)
398 typeStr.erase(typeStr.begin(), typeStr.begin() + pos + 6 + 1);
403 std::string srcStr = src ? src->
str() :
"int";
405 std::string tgtStr = tgt ? tgt->
str() :
"long";
409 "truncLongCastAssignment",
410 srcStr +
" result is assigned to " + tgtStr +
" variable. If the variable is " + tgtStr +
" to avoid loss of information, then you have loss of information.\n" +
411 srcStr +
" result is assigned to " + tgtStr +
" variable. If the variable is " + tgtStr +
" to avoid loss of information, then there is loss of information. To avoid loss of information you must cast a calculation operand to " + tgtStr +
", for example 'l = a * b;' => 'l = (" + tgtStr +
")a * b;'.",
CWE197,
Certainty::normal);
416 std::string srcStr = src ? src->
str() :
"int";
418 std::string tgtStr = tgt ? tgt->
str() :
"long";
422 "truncLongCastReturn",
423 srcStr +
" result is returned as " + tgtStr +
" value. If the return value is " + tgtStr +
" to avoid loss of information, then you have loss of information.\n" +
424 srcStr +
" result is returned as " + tgtStr +
" value. If the return value is " + tgtStr +
" to avoid loss of information, then there is loss of information. To avoid loss of information you must cast a calculation operand to long, for example 'return a*b;' => 'return (long)a*b'.",
CWE197,
Certainty::normal);
433 logChecker(
"CheckType::checkFloatToIntegerOverflow");
439 if (
Token::Match(tok,
"( %name%") && tok->astOperand1() && !tok->astOperand2()) {
440 vtint = tok->valueType();
441 vtfloat = tok->astOperand1()->valueType();
446 else if (tok->str() ==
"=" && tok->astOperand1() && tok->astOperand2()) {
447 vtint = tok->astOperand1()->valueType();
448 vtfloat = tok->astOperand2()->valueType();
452 else if (tok->str() ==
"return" && tok->astOperand1() && tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->isFloat()) {
453 const Scope *scope = tok->scope();
454 while (scope && scope->
type != Scope::ScopeType::eLambda && scope->
type != Scope::ScopeType::eFunction)
458 vtfloat = tok->astOperand1()->valueType();
470 if (!vtfloat || !vtfloat->
isFloat())
484 if (vtint->
type == ValueType::Type::CHAR)
486 else if (vtint->
type == ValueType::Type::SHORT)
488 else if (vtint->
type == ValueType::Type::INT)
490 else if (vtint->
type == ValueType::Type::LONG)
492 else if (vtint->
type == ValueType::Type::LONGLONG)
496 if (bits < MathLib::bigint_bits && f.floatValue >= (((
MathLib::biguint)1) << bits))
504 std::ostringstream errmsg;
505 errmsg <<
"Undefined behaviour: float (" << value.
floatValue <<
") to integer conversion overflow.";
508 "floatConversionOverflow",
static bool checkTypeCombination(ValueType src, ValueType tgt, const Settings &settings)
static const CWE CWE190(190U)
static const CWE CWE758(758U)
static void makeBaseTypeString(std::string &typeStr)
static const CWE CWE197(197U)
static const CWE CWE195(195U)
void tooBigSignedBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits)
void signConversionError(const Token *tok, const ValueFlow::Value *negativeValue, const bool constvalue)
void checkFloatToIntegerOverflow()
Check for float to integer overflow
void checkIntegerOverflow()
Check for integer overflow
void longCastAssignError(const Token *tok, const ValueType *src=nullptr, const ValueType *tgt=nullptr)
void checkSignConversion()
Check for dangerous sign conversion
void integerOverflowError(const Token *tok, const ValueFlow::Value &value)
void floatToIntegerOverflowError(const Token *tok, const ValueFlow::Value &value)
void checkLongCast()
Check for implicit long cast of int result
void longCastReturnError(const Token *tok, const ValueType *src=nullptr, const ValueType *tgt=nullptr)
void checkTooBigBitwiseShift()
Check for bitwise shift with too big right operand
void tooBigBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits)
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
const Settings *const mSettings
ErrorPath getErrorPath(const Token *errtok, const ValueFlow::Value *value, std::string bug) const
const Tokenizer *const mTokenizer
static std::string getMessageId(const ValueFlow::Value &value, const char id[])
void logChecker(const char id[])
log checker
const Token * retDef
function return type token
static const int bigint_bits
unsigned long long biguint
Function * function
function info for this function
const Token * classDef
class/struct/union/namespace token
const Token * bodyStart
'{' token
const Token * bodyEnd
'}' token
This is just a container for general settings so that we don't need to pass individual values to func...
bool isEnabled(const ValueFlow::Value *value, bool inconclusiveCheck=false) const
Returns true if given value can be shown.
bool isPremiumEnabled(const char id[]) const
Is checker id enabled by premiumArgs.
SimpleEnableGroup< Severity > severity
Standards standards
Struct contains standards settings.
bool isEnabled(T flag) const
std::vector< const Scope * > functionScopes
Fast access to function scopes.
The token list that the TokenList generates is a linked-list of this class.
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
const ValueType * valueType() const
void astOperand1(Token *tok)
std::string expressionString() const
nonneg int linenr() const
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
const Token * tokens() const
const SymbolDatabase * getSymbolDatabase() const
bool isCPP() const
Is the code CPP.
bool errorSeverity() const
double floatValue
float value
const Token * condition
Condition that this value depends on.
long long intvalue
int value (or sometimes bool value?)
bool isInconclusive() const
bool safe
value relies on safe checking
enum ValueType::Type type
Reference reference
Is the outermost indirection of this type a reference or rvalue.
nonneg int pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
std::string originalTypeName
original type name as written in the source code.
static ValueType parseDecl(const Token *type, const Settings &settings)
enum ValueType::Sign sign
Severity
enum class for severity.
std::list< ErrorPathItem > ErrorPath
@ portability
Portability warning.
@ error
Programming error.
std::string eitherTheConditionIsRedundant(const Token *condition)
const Value * findValue(const std::list< Value > &values, const Settings &settings, const std::function< bool(const Value &)> &pred)
size_t getSizeOf(const ValueType &vt, const Settings &settings, int maxRecursion=0)
enum Standards::cppstd_t cpp