Skip to content

Commit cc46f77

Browse files
committed
Fix #14294 FN CastAddressToIntegerAtReturn with cast
1 parent 602da94 commit cc46f77

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

lib/check64bit.cpp

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

43+
static bool is32BitIntegerReturn(const Function* func, const Settings* settings)
44+
{
45+
const ValueType* vt = func->arg->valueType();
46+
return vt && vt->isIntegral() && vt->typeSize(settings->platform) < settings->platform.sizeof_pointer;
47+
}
48+
4349
void Check64BitPortability::pointerassignment()
4450
{
4551
if (!mSettings->severity.isEnabled(Severity::portability))
@@ -57,7 +63,7 @@ void Check64BitPortability::pointerassignment()
5763
bool retPointer = false;
5864
if (scope->function->token->strAt(-1) == "*") // Function returns a pointer
5965
retPointer = true;
60-
else if (Token::Match(scope->function->token->previous(), "int|long|DWORD")) // Function returns an integer
66+
else if (is32BitIntegerReturn(scope->function, mSettings))
6167
;
6268
else
6369
continue;
@@ -82,8 +88,17 @@ void Check64BitPortability::pointerassignment()
8288
if (retPointer && !returnType->typeScope && returnType->pointer == 0U)
8389
returnIntegerError(tok);
8490

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

@@ -148,7 +163,7 @@ void Check64BitPortability::returnPointerError(const Token *tok)
148163
"Returning an address value in a function with integer (int/long/etc) return type is not portable across "
149164
"different platforms and compilers. For example in 32-bit Windows and Linux they are same width, but in "
150165
"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);
166+
"to 32-bit integer. The safe way is to return a type such as intptr_t.", CWE758, Certainty::normal);
152167
}
153168

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

test/test64bit.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,18 @@ 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());
310322
}
311323
};
312324

0 commit comments

Comments
 (0)