Fixed #6349 (Pointer arithmetic: clarify message)
This commit is contained in:
parent
26aa049724
commit
bc594d52c8
|
@ -173,13 +173,24 @@ void CheckBufferOverrun::outOfBoundsError(const Token *tok, const std::string &w
|
|||
reportError(tok, Severity::error, "outOfBounds", oss.str());
|
||||
}
|
||||
|
||||
void CheckBufferOverrun::pointerOutOfBoundsError(const Token *tok, const std::string &object)
|
||||
void CheckBufferOverrun::pointerOutOfBoundsError(const Token *tok, const Token *index, const MathLib::bigint indexvalue)
|
||||
{
|
||||
// The severity is portability instead of error since this ub doesnt
|
||||
// cause bad behaviour on most implementations. people create out
|
||||
// of bounds pointers by intention.
|
||||
reportError(tok, Severity::portability, "pointerOutOfBounds", "Undefined behaviour: Pointer arithmetic result does not point into or just past the end of the " + object + ".\n"
|
||||
"Undefined behaviour: The result of this pointer arithmetic does not point into or just one element past the end of the " + object + ". Further information: https://www.securecoding.cert.org/confluence/display/seccode/ARR30-C.+Do+not+form+or+use+out+of+bounds+pointers+or+array+subscripts");
|
||||
const std::string expr(tok ? tok->expressionString() : std::string(""));
|
||||
std::string errmsg("Undefined behaviour. Pointer arithmetic '" + expr + "' result is out of bounds");
|
||||
if (index && !index->isNumber())
|
||||
errmsg += " when " + index->expressionString() + " is " + MathLib::toString(indexvalue);
|
||||
std::string verbosemsg(errmsg + ". From chapter 6.5.6 in the C specification:\n"
|
||||
"\"When an expression that has integer type is added to or subtracted from a pointer, ..\" and then \"If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.\"");
|
||||
reportError(tok, Severity::portability, "pointerOutOfBounds", errmsg + ".\n" + verbosemsg);
|
||||
/*
|
||||
"Undefined behaviour: The result of this pointer arithmetic does not point into
|
||||
or just one element past the end of the " + object + ".
|
||||
Further information:
|
||||
https://www.securecoding.cert.org/confluence/display/seccode/ARR30-C.+Do+not+form+or+use+out+of+bounds+pointers+or+array+subscripts");
|
||||
*/
|
||||
}
|
||||
|
||||
void CheckBufferOverrun::sizeArgumentAsCharError(const Token *tok)
|
||||
|
@ -699,7 +710,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
|
|||
else if (declarationId && Token::Match(tok, "= %varid% + %num% ;", declarationId)) {
|
||||
const MathLib::bigint index = MathLib::toLongNumber(tok->strAt(3));
|
||||
if (isPortabilityEnabled && index > size)
|
||||
pointerOutOfBoundsError(tok->next(), "buffer");
|
||||
pointerOutOfBoundsError(tok->tokAt(2));
|
||||
if (index >= size && Token::Match(tok->tokAt(-2), "[;{}] %varid% =", declarationId))
|
||||
pointerIsOutOfBounds = true;
|
||||
}
|
||||
|
@ -851,24 +862,24 @@ void CheckBufferOverrun::checkScope(const Token *tok, const ArrayInfo &arrayInfo
|
|||
}
|
||||
|
||||
else if (isPortabilityEnabled && !tok->isCast() && tok->astParent() && tok->astParent()->str() == "+") {
|
||||
const ValueFlow::Value *index;
|
||||
if (tok == tok->astParent()->astOperand1())
|
||||
index = tok->astParent()->astOperand2()->getMaxValue(false);
|
||||
else
|
||||
index = tok->astParent()->astOperand1()->getMaxValue(false);
|
||||
|
||||
// undefined behaviour: result of pointer arithmetic is out of bounds
|
||||
if (index && (index->intvalue < 0 || index->intvalue > arrayInfo.num(0))) {
|
||||
pointerOutOfBoundsError(tok, "array");
|
||||
}
|
||||
const Token *index;
|
||||
if (tok == tok->astParent()->astOperand1())
|
||||
index = tok->astParent()->astOperand2();
|
||||
else
|
||||
index = tok->astParent()->astOperand1();
|
||||
const ValueFlow::Value *value = index ? index->getMaxValue(false) : nullptr;
|
||||
if (value && (value->intvalue < 0 || value->intvalue > arrayInfo.num(0)))
|
||||
pointerOutOfBoundsError(tok->astParent(), index, value->intvalue);
|
||||
}
|
||||
|
||||
else if (isPortabilityEnabled && tok->astParent() && tok->astParent()->str() == "-") {
|
||||
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(declarationId);
|
||||
if (var && var->isArray()) {
|
||||
const Token *index = tok->astParent()->astOperand2();
|
||||
if (index && index->getValueGE(1,_settings))
|
||||
pointerOutOfBoundsError(tok, "array");
|
||||
const ValueFlow::Value *value = index ? index->getValueGE(1,_settings) : nullptr;
|
||||
if (value)
|
||||
pointerOutOfBoundsError(tok->astParent(), index, value->intvalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -240,7 +240,7 @@ private:
|
|||
void negativeIndexError(const Token *tok, MathLib::bigint index);
|
||||
void negativeIndexError(const Token *tok, const ValueFlow::Value &index);
|
||||
void cmdLineArgsError(const Token *tok);
|
||||
void pointerOutOfBoundsError(const Token *tok, const std::string &object); // UB when result of calculation is out of bounds
|
||||
void pointerOutOfBoundsError(const Token *tok, const Token *index=nullptr, const MathLib::bigint indexvalue=0);
|
||||
void arrayIndexThenCheckError(const Token *tok, const std::string &indexName);
|
||||
void possibleBufferOverrunError(const Token *tok, const std::string &src, const std::string &dst, bool cat);
|
||||
void possibleReadlinkBufferOverrunError(const Token *tok, const std::string &funcname, const std::string &varname);
|
||||
|
@ -263,7 +263,7 @@ public:
|
|||
c.bufferNotZeroTerminatedError(0, "buffer", "strncpy");
|
||||
c.negativeIndexError(0, -1);
|
||||
c.cmdLineArgsError(0);
|
||||
c.pointerOutOfBoundsError(0, "array");
|
||||
c.pointerOutOfBoundsError(nullptr, nullptr, 0);
|
||||
c.arrayIndexThenCheckError(0, "index");
|
||||
c.possibleBufferOverrunError(0, "source", "destination", false);
|
||||
c.possibleReadlinkBufferOverrunError(0, "readlink", "buffer");
|
||||
|
|
|
@ -2962,13 +2962,13 @@ private:
|
|||
" char a[10];\n"
|
||||
" char *p = a + 100;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour: Pointer arithmetic result does not point into or just past the end of the array.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour. Pointer arithmetic 'a+100' result is out of bounds.\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" char a[10];\n"
|
||||
" return a + 100;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour: Pointer arithmetic result does not point into or just past the end of the array.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour. Pointer arithmetic 'a+100' result is out of bounds.\n", errout.str());
|
||||
|
||||
check("void f() {\n" // #6350 - fp when there is cast of buffer
|
||||
" wchar_t buf[64];\n"
|
||||
|
@ -2983,7 +2983,7 @@ private:
|
|||
" p += 100;\n"
|
||||
" free(p);"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour: Pointer arithmetic result does not point into or just past the end of the buffer.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour. Pointer arithmetic 'p+100' result is out of bounds.\n", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" char *p = malloc(10);\n"
|
||||
|
@ -3017,7 +3017,7 @@ private:
|
|||
" char x[10];\n"
|
||||
" return x-1;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour: Pointer arithmetic result does not point into or just past the end of the array.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour. Pointer arithmetic 'x-1' result is out of bounds.\n", errout.str());
|
||||
}
|
||||
|
||||
void sprintf1() {
|
||||
|
|
Loading…
Reference in New Issue