Skip to content

Commit bf56f95

Browse files
Fix #8260 Improve check: Pointer calculation result not null
Signed-off-by: Francois Berder <fberder@outlook.fr>
1 parent f1379d6 commit bf56f95

3 files changed

Lines changed: 79 additions & 20 deletions

File tree

lib/checkcondition.cpp

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,43 @@ static bool isIfConstexpr(const Token* tok) {
11561156
return Token::simpleMatch(top->astOperand1(), "if") && top->astOperand1()->isConstexpr();
11571157
}
11581158

1159+
static const Token* isPointerArithmeticAdd(const Token* tok)
1160+
{
1161+
if (!tok || tok->str() != "+" || !astIsPointer(tok))
1162+
return nullptr;
1163+
1164+
const Token* intOp = astIsPointer(tok->astOperand1()) ? tok->astOperand2() : tok->astOperand1();
1165+
if (intOp && intOp->hasKnownIntValue() && intOp->getKnownIntValue() != 0)
1166+
return tok;
1167+
1168+
return nullptr;
1169+
}
1170+
1171+
static const Token* getPointerAdditionCalcToken(const Token * const tok)
1172+
{
1173+
for (const Token *op : {tok, tok->astOperand1(), tok->astOperand2()}) {
1174+
if (!op)
1175+
continue;
1176+
1177+
// case 1: op is ptr+nonzero
1178+
if (isPointerArithmeticAdd(op))
1179+
return op;
1180+
1181+
// case 2: op is a pointer variable assigned from ptr+nonzero
1182+
if (!astIsPointer(op))
1183+
continue;
1184+
1185+
for (const ValueFlow::Value& val : op->values()) {
1186+
if (!val.isSymbolicValue())
1187+
continue;
1188+
if (isPointerArithmeticAdd(val.tokvalue))
1189+
return op;
1190+
}
1191+
}
1192+
1193+
return nullptr;
1194+
}
1195+
11591196
void CheckConditionImpl::checkIncorrectLogicOperator()
11601197
{
11611198
const bool printStyle = mSettings->severity.isEnabled(Severity::style);
@@ -1618,6 +1655,11 @@ void CheckConditionImpl::alwaysTrueFalse()
16181655
continue;
16191656
}
16201657

1658+
// checkPointerAdditionResultNotNull emits a more specific warning for
1659+
// comparisons where the pointer is the result of an expression ptr+nonzero.
1660+
if (getPointerAdditionCalcToken(tok))
1661+
continue;
1662+
16211663
// Don't warn when there are expanded macros..
16221664
bool isExpandedMacro = false;
16231665
visitAstNodes(tok, [&](const Token * tok2) {
@@ -1801,32 +1843,27 @@ void CheckConditionImpl::checkPointerAdditionResultNotNull()
18011843
for (const Scope * scope : symbolDatabase->functionScopes) {
18021844

18031845
for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
1804-
if (!tok->isComparisonOp() || !tok->astOperand1() || !tok->astOperand2())
1805-
continue;
1806-
18071846
// Macros might have pointless safety checks
18081847
if (tok->isExpandedMacro())
18091848
continue;
18101849

1811-
const Token *calcToken, *exprToken;
1812-
if (tok->astOperand1()->str() == "+") {
1813-
calcToken = tok->astOperand1();
1814-
exprToken = tok->astOperand2();
1815-
} else if (tok->astOperand2()->str() == "+") {
1816-
calcToken = tok->astOperand2();
1817-
exprToken = tok->astOperand1();
1818-
} else
1850+
const Token *calcToken = getPointerAdditionCalcToken(tok);
1851+
if (!calcToken)
18191852
continue;
18201853

1821-
// pointer comparison against NULL (ptr+12==0)
1822-
if (calcToken->hasKnownIntValue())
1823-
continue;
1824-
if (!calcToken->valueType() || calcToken->valueType()->pointer==0)
1825-
continue;
1826-
if (!exprToken->hasKnownIntValue() || !exprToken->getValue(0))
1827-
continue;
1854+
if (tok->isComparisonOp() && tok->astOperand1() && tok->astOperand2()) {
1855+
const Token *exprToken = tok->astOperand1() == calcToken ? tok->astOperand2() : tok->astOperand1();
1856+
1857+
if (!exprToken)
1858+
continue;
18281859

1829-
pointerAdditionResultNotNullError(tok, calcToken);
1860+
if (!exprToken->hasKnownIntValue() || !exprToken->getValue(0))
1861+
continue;
1862+
1863+
pointerAdditionResultNotNullError(tok, calcToken);
1864+
} else if (astIsPointer(tok) && isUsedAsBool(tok, *mSettings) && !tok->astParent()->isComparisonOp()) {
1865+
pointerAdditionResultNotNullError(tok, calcToken);
1866+
}
18301867
}
18311868
}
18321869
}

lib/valueflow.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,16 @@ static void valueFlowImpossibleValues(TokenList& tokenList, const Settings& sett
11741174
ValueFlow::Value value{0};
11751175
value.setImpossible();
11761176
setTokenValue(tok, std::move(value), settings);
1177+
} else if (Token::simpleMatch(tok, "+") && astIsPointer(tok)) {
1178+
const Token* op1 = tok->astOperand1();
1179+
const Token* op2 = tok->astOperand2();
1180+
if ((op1 && op1->hasKnownIntValue() && op1->getKnownIntValue() != 0)
1181+
|| (op2 && op2->hasKnownIntValue() && op2->getKnownIntValue() != 0)) {
1182+
ValueFlow::Value val(0);
1183+
val.setImpossible();
1184+
val.errorPath.emplace_back(tok, "Pointer arithmetic result cannot be null");
1185+
setTokenValue(tok, std::move(val), settings);
1186+
}
11771187
}
11781188
}
11791189
}

test/testcondition.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6248,7 +6248,19 @@ class TestCondition : public TestFixture {
62486248
" if (ptr + 1 != 0);\n"
62496249
"}");
62506250
ASSERT_EQUALS("[test.cpp:2:15]: (warning) Comparison is wrong. Result of 'ptr+1' can't be 0 unless there is pointer overflow, and pointer overflow is undefined behaviour. [pointerAdditionResultNotNull]\n", errout_str());
6251-
}
6251+
6252+
check("void f(char *ptr) {\n"
6253+
" int *q = ptr + 1;\n"
6254+
" if (q != 0);\n"
6255+
"}");
6256+
ASSERT_EQUALS("[test.cpp:3:9]: (warning) Comparison is wrong. Result of 'q' can't be 0 unless there is pointer overflow, and pointer overflow is undefined behaviour. [pointerAdditionResultNotNull]\n", errout_str());
6257+
6258+
check("void f(char *ptr) {\n"
6259+
" int *q = ptr + 1;\n"
6260+
" if (q);\n"
6261+
"}");
6262+
ASSERT_EQUALS("[test.cpp:3:7]: (warning) Comparison is wrong. Result of 'q' can't be 0 unless there is pointer overflow, and pointer overflow is undefined behaviour. [pointerAdditionResultNotNull]\n", errout_str());
6263+
}
62526264

62536265
void duplicateConditionalAssign() {
62546266
setMultiline();

0 commit comments

Comments
 (0)