Fixed #6356 (Improve checking: pointer arithmetic "ab.a + 100" overrun)
This commit is contained in:
parent
c110770481
commit
bc40f5041d
|
@ -1481,6 +1481,39 @@ void CheckBufferOverrun::bufferOverrun()
|
||||||
{
|
{
|
||||||
// singlepass checking using ast, symboldatabase and valueflow
|
// singlepass checking using ast, symboldatabase and valueflow
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
|
if (_settings->isEnabled(Settings::PORTABILITY) && tok->str() == "+" && tok->valueType() && tok->valueType()->pointer > 0) {
|
||||||
|
if (!tok->astOperand1() || !tok->astOperand1()->valueType())
|
||||||
|
continue;
|
||||||
|
if (!tok->astOperand2() || !tok->astOperand2()->valueType())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// pointer arithmetic..
|
||||||
|
const Token *pointerToken, *indexToken;
|
||||||
|
|
||||||
|
if (tok->astOperand1()->valueType()->pointer == 0) {
|
||||||
|
indexToken = tok->astOperand1();
|
||||||
|
pointerToken = tok->astOperand2();
|
||||||
|
} else if (tok->astOperand2()->valueType()->pointer == 0) {
|
||||||
|
indexToken = tok->astOperand2();
|
||||||
|
pointerToken = tok->astOperand1();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pointerToken && pointerToken->str() == ".")
|
||||||
|
pointerToken = pointerToken->astOperand2();
|
||||||
|
|
||||||
|
if (!pointerToken || !pointerToken->isName())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const Variable *var = pointerToken->variable();
|
||||||
|
if (!var || !var->isArray())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const ValueFlow::Value *value = indexToken->getValueGE(var->dimension(0)+1, _settings);
|
||||||
|
if (value) {
|
||||||
|
pointerOutOfBoundsError(tok, indexToken, value->intvalue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Array index
|
// Array index
|
||||||
if (!Token::Match(tok, "%name% ["))
|
if (!Token::Match(tok, "%name% ["))
|
||||||
continue;
|
continue;
|
||||||
|
@ -1876,7 +1909,7 @@ MathLib::bigint CheckBufferOverrun::ArrayInfo::totalIndex(const std::vector<Valu
|
||||||
|
|
||||||
void CheckBufferOverrun::arrayIndexThenCheck()
|
void CheckBufferOverrun::arrayIndexThenCheck()
|
||||||
{
|
{
|
||||||
if (!_settings->isEnabled(Settings::STYLE))
|
if (!_settings->isEnabled(Settings::PORTABILITY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|
|
|
@ -185,6 +185,7 @@ private:
|
||||||
// char *p2 = a + 11 // UB
|
// char *p2 = a + 11 // UB
|
||||||
TEST_CASE(pointer_out_of_bounds_1);
|
TEST_CASE(pointer_out_of_bounds_1);
|
||||||
TEST_CASE(pointer_out_of_bounds_2);
|
TEST_CASE(pointer_out_of_bounds_2);
|
||||||
|
TEST_CASE(pointer_out_of_bounds_3);
|
||||||
TEST_CASE(pointer_out_of_bounds_sub);
|
TEST_CASE(pointer_out_of_bounds_sub);
|
||||||
|
|
||||||
TEST_CASE(strncat1);
|
TEST_CASE(strncat1);
|
||||||
|
@ -2795,6 +2796,14 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pointer_out_of_bounds_3() {
|
||||||
|
check("struct S { int a[10]; };\n"
|
||||||
|
"void f(struct S *s) {\n"
|
||||||
|
" char *p = s->a + 100;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (portability) Undefined behaviour, pointer arithmetic 's->a+100' is out of bounds.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void pointer_out_of_bounds_sub() {
|
void pointer_out_of_bounds_sub() {
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" char x[10];\n"
|
" char x[10];\n"
|
||||||
|
|
Loading…
Reference in New Issue