checkTooBigBitwiseShift: Separate id for signed shift overflow
This commit is contained in:
parent
be0ad20a04
commit
6bc0df2908
|
@ -82,20 +82,24 @@ void CheckType::checkTooBigBitwiseShift()
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (lhstype->sign == ValueType::Sign::SIGNED)
|
|
||||||
--lhsbits;
|
|
||||||
|
|
||||||
// Get biggest rhs value. preferably a value which doesn't have 'condition'.
|
// Get biggest rhs value. preferably a value which doesn't have 'condition'.
|
||||||
const ValueFlow::Value *value = tok->astOperand2()->getValueGE(lhsbits, _settings);
|
const ValueFlow::Value *value = tok->astOperand2()->getValueGE(lhsbits, _settings);
|
||||||
if (value && _settings->isEnabled(value, false))
|
if (value && _settings->isEnabled(value, false))
|
||||||
tooBigBitwiseShiftError(tok, lhsbits, *value);
|
tooBigBitwiseShiftError(tok, lhsbits, *value);
|
||||||
|
else if (lhstype->sign == ValueType::Sign::SIGNED) {
|
||||||
|
value = tok->astOperand2()->getValueGE(lhsbits-1, _settings);
|
||||||
|
if (value && _settings->isEnabled(value, false))
|
||||||
|
tooBigSignedBitwiseShiftError(tok, lhsbits, *value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckType::tooBigBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits)
|
void CheckType::tooBigBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits)
|
||||||
{
|
{
|
||||||
|
const char id[] = "shiftTooManyBits";
|
||||||
|
|
||||||
if (!tok) {
|
if (!tok) {
|
||||||
reportError(tok, Severity::error, "shiftTooManyBits", "Shifting 32-bit value by 40 bits is undefined behaviour", CWE758, false);
|
reportError(tok, Severity::error, id, "Shifting 32-bit value by 40 bits is undefined behaviour", CWE758, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +110,26 @@ void CheckType::tooBigBitwiseShiftError(const Token *tok, int lhsbits, const Val
|
||||||
if (rhsbits.condition)
|
if (rhsbits.condition)
|
||||||
errmsg << ". See condition at line " << rhsbits.condition->linenr() << ".";
|
errmsg << ". See condition at line " << rhsbits.condition->linenr() << ".";
|
||||||
|
|
||||||
reportError(errorPath, rhsbits.errorSeverity() ? Severity::error : Severity::warning, "shiftTooManyBits", errmsg.str(), CWE758, rhsbits.inconclusive);
|
reportError(errorPath, rhsbits.errorSeverity() ? Severity::error : Severity::warning, id, errmsg.str(), CWE758, rhsbits.inconclusive);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckType::tooBigSignedBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits)
|
||||||
|
{
|
||||||
|
const char id[] = "shiftTooManyBitsSigned";
|
||||||
|
|
||||||
|
if (!tok) {
|
||||||
|
reportError(tok, Severity::error, id, "Shifting signed 32-bit value by 31 bits is undefined behaviour", CWE758, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ErrorPath errorPath = getErrorPath(tok, &rhsbits, "Shift");
|
||||||
|
|
||||||
|
std::ostringstream errmsg;
|
||||||
|
errmsg << "Shifting signed " << lhsbits << "-bit value by " << rhsbits.intvalue << " bits is undefined behaviour";
|
||||||
|
if (rhsbits.condition)
|
||||||
|
errmsg << ". See condition at line " << rhsbits.condition->linenr() << ".";
|
||||||
|
|
||||||
|
reportError(errorPath, rhsbits.errorSeverity() ? Severity::error : Severity::warning, id, errmsg.str(), CWE758, rhsbits.inconclusive);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
|
@ -84,6 +84,7 @@ private:
|
||||||
|
|
||||||
// Error messages..
|
// Error messages..
|
||||||
void tooBigBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits);
|
void tooBigBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits);
|
||||||
|
void tooBigSignedBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits);
|
||||||
void integerOverflowError(const Token *tok, const ValueFlow::Value &value);
|
void integerOverflowError(const Token *tok, const ValueFlow::Value &value);
|
||||||
void signConversionError(const Token *tok, const bool constvalue);
|
void signConversionError(const Token *tok, const bool constvalue);
|
||||||
void longCastAssignError(const Token *tok);
|
void longCastAssignError(const Token *tok);
|
||||||
|
@ -93,6 +94,7 @@ private:
|
||||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||||
CheckType c(nullptr, settings, errorLogger);
|
CheckType c(nullptr, settings, errorLogger);
|
||||||
c.tooBigBitwiseShiftError(nullptr, 32, ValueFlow::Value(64));
|
c.tooBigBitwiseShiftError(nullptr, 32, ValueFlow::Value(64));
|
||||||
|
c.tooBigSignedBitwiseShiftError(nullptr, 31, ValueFlow::Value(31));
|
||||||
c.integerOverflowError(nullptr, ValueFlow::Value(1LL<<32));
|
c.integerOverflowError(nullptr, ValueFlow::Value(1LL<<32));
|
||||||
c.signConversionError(nullptr, false);
|
c.signConversionError(nullptr, false);
|
||||||
c.longCastAssignError(nullptr);
|
c.longCastAssignError(nullptr);
|
||||||
|
|
|
@ -71,7 +71,7 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) Shifting 32-bit value by 32 bits is undefined behaviour\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (error) Shifting 32-bit value by 32 bits is undefined behaviour\n", errout.str());
|
||||||
|
|
||||||
check("x = (short)x << 31;",&settings);
|
check("x = (short)x << 31;",&settings);
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 31-bit value by 31 bits is undefined behaviour\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:1]: (error) Shifting signed 32-bit value by 31 bits is undefined behaviour\n", errout.str());
|
||||||
|
|
||||||
check("int foo(int x) {\n"
|
check("int foo(int x) {\n"
|
||||||
" return x << 2;\n"
|
" return x << 2;\n"
|
||||||
|
|
Loading…
Reference in New Issue