Skip to content

Commit 566de27

Browse files
Fix #14294 FN CastAddressToIntegerAtReturn with cast (#7998)
Co-authored-by: chrchr-github <noreply@github.com>
1 parent 2fa0c1e commit 566de27

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

lib/check64bit.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ namespace {
4040
Check64BitPortability instance;
4141
}
4242

43+
static bool is32BitIntegerReturn(const Function* func, const Settings* settings)
44+
{
45+
if (settings->platform.sizeof_pointer != 8)
46+
return false;
47+
const ValueType* vt = func->arg->valueType();
48+
return vt && vt->pointer == 0 && vt->isIntegral() && vt->typeSize(settings->platform) == 4;
49+
}
50+
4351
void Check64BitPortability::pointerassignment()
4452
{
4553
if (!mSettings->severity.isEnabled(Severity::portability))
@@ -57,7 +65,7 @@ void Check64BitPortability::pointerassignment()
5765
bool retPointer = false;
5866
if (scope->function->token->strAt(-1) == "*") // Function returns a pointer
5967
retPointer = true;
60-
else if (Token::Match(scope->function->token->previous(), "int|long|DWORD")) // Function returns an integer
68+
else if (is32BitIntegerReturn(scope->function, mSettings))
6169
;
6270
else
6371
continue;
@@ -82,8 +90,17 @@ void Check64BitPortability::pointerassignment()
8290
if (retPointer && !returnType->typeScope && returnType->pointer == 0U)
8391
returnIntegerError(tok);
8492

85-
if (!retPointer && returnType->pointer >= 1U)
86-
returnPointerError(tok);
93+
if (!retPointer) {
94+
bool warn = returnType->pointer >= 1U;
95+
if (!warn) {
96+
const Token* tok2 = tok->astOperand1();
97+
while (tok2 && tok2->isCast())
98+
tok2 = tok2->astOperand2() ? tok2->astOperand2() : tok2->astOperand1();
99+
warn = tok2 && tok2->valueType() && tok2->valueType()->pointer;
100+
}
101+
if (warn)
102+
returnPointerError(tok);
103+
}
87104
}
88105
}
89106

@@ -148,7 +165,7 @@ void Check64BitPortability::returnPointerError(const Token *tok)
148165
"Returning an address value in a function with integer (int/long/etc) return type is not portable across "
149166
"different platforms and compilers. For example in 32-bit Windows and Linux they are same width, but in "
150167
"64-bit Windows and Linux they are of different width. In worst case you end up casting 64-bit address down "
151-
"to 32-bit integer. The safe way is to always return an integer.", CWE758, Certainty::normal);
168+
"to 32-bit integer. The safe way is to return a type such as intptr_t.", CWE758, Certainty::normal);
152169
}
153170

154171
void Check64BitPortability::returnIntegerError(const Token *tok)

test/test64bit.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,23 @@ class Test64BitPortability : public TestFixture {
307307
" return x.get();\n"
308308
"}\n");
309309
ASSERT_EQUALS("", errout_str());
310+
311+
check("int f(int* p) {\n" // #14294
312+
" return (int)p;\n"
313+
"}\n");
314+
ASSERT_EQUALS("[test.cpp:2:5]: (portability) Returning an address value in a function with integer return type is not portable. [CastAddressToIntegerAtReturn]\n",
315+
errout_str());
316+
317+
check("int f(int* p) {\n"
318+
" return reinterpret_cast<int>(p);\n"
319+
"}\n");
320+
ASSERT_EQUALS("[test.cpp:2:5]: (portability) Returning an address value in a function with integer return type is not portable. [CastAddressToIntegerAtReturn]\n",
321+
errout_str());
322+
323+
check("bool f(const int* p) {\n"
324+
" return p;\n"
325+
"}\n");
326+
ASSERT_EQUALS("", errout_str());
310327
}
311328
};
312329

0 commit comments

Comments
 (0)