checkTooBigBitwiseShift: Separate id for signed shift overflow

This commit is contained in:
Daniel Marjamäki 2017-09-19 09:21:20 +02:00
parent be0ad20a04
commit 6bc0df2908
3 changed files with 31 additions and 6 deletions

View File

@ -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);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -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);

View File

@ -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"