Skip to content

Commit 5ec129e

Browse files
committed
Fix #11765 FN: minsize not checked for string literal, buffer access out of bounds not found
1 parent b2d8361 commit 5ec129e

4 files changed

Lines changed: 55 additions & 7 deletions

File tree

‎lib/checkbufferoverrun.cpp‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ void CheckBufferOverrunImpl::pointerArithmeticError(const Token *tok, const Toke
558558

559559
//---------------------------------------------------------------------------
560560

561-
ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok, const Settings& settings) const
561+
ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok, const Settings& settings, bool checkStringLiteral) const
562562
{
563563
if (!bufTok->valueType())
564564
return ValueFlow::Value(-1);
@@ -604,6 +604,14 @@ ValueFlow::Value CheckBufferOverrunImpl::getBufferSize(const Token *bufTok, cons
604604
return bufSizeVal;
605605
}
606606
}
607+
} else if (checkStringLiteral && bufTok->tokType() == Token::Type::eString && bufTok->valueType()) {
608+
ValueFlow::Value strSizeVal;
609+
strSizeVal.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE;
610+
const size_t charSize = bufTok->valueType()->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointee);
611+
if (charSize > 0) {
612+
strSizeVal.intvalue = Token::getStrArraySize(bufTok) * charSize;
613+
return strSizeVal;
614+
}
607615
}
608616
}
609617

@@ -715,7 +723,8 @@ void CheckBufferOverrunImpl::bufferOverflow()
715723
if (argtok->valueType() && argtok->valueType()->pointer == 0)
716724
continue;
717725
// TODO: strcpy(buf+10, "hello");
718-
ValueFlow::Value bufferSize = getBufferSize(argtok, mSettings);
726+
const bool strz = mSettings.library.isargstrz(tok, argnr + 1);
727+
ValueFlow::Value bufferSize = getBufferSize(argtok, mSettings, !strz);
719728
if (bufferSize.intvalue <= 0)
720729
continue;
721730
// buffer size == 1 => do not warn for dynamic memory

‎lib/checkbufferoverrun.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class CPPCHECKLIB CheckBufferOverrunImpl : public CheckImpl
129129
void objectIndex();
130130
void objectIndexError(const Token *tok, const ValueFlow::Value *v, bool known);
131131

132-
ValueFlow::Value getBufferSize(const Token *bufTok, const Settings& settings) const;
132+
ValueFlow::Value getBufferSize(const Token *bufTok, const Settings& settings, bool checkStringLiteral = false) const;
133133

134134
// CTU
135135
static bool isCtuUnsafeBufferUsage(const Settings &settings, const Token *argtok, CTU::FileInfo::Value *offset, int type);

‎test/cfg/posix.c‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,7 @@ size_t bufferAccessOutOfBounds_strnlen(const char *s, size_t maxlen)
719719
size_t len = strnlen(buf,2);
720720
// cppcheck-suppress bufferAccessOutOfBounds
721721
len+=strnlen(buf,3);
722+
len+=strnlen("ab",3);
722723
return len;
723724
}
724725

@@ -1606,4 +1607,4 @@ void pthread_define_test()
16061607
(void)rwlock;
16071608
PTHREAD_SCOPE_PROCESS;
16081609
PTHREAD_SCOPE_SYSTEM;
1609-
}
1610+
}

‎test/testbufferoverrun.cpp‎

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ class TestBufferOverrun : public TestFixture {
229229
TEST_CASE(buffer_overrun_36);
230230
TEST_CASE(buffer_overrun_37);
231231
TEST_CASE(buffer_overrun_38);
232+
TEST_CASE(buffer_overrun_39);
232233
TEST_CASE(buffer_overrun_errorpath);
233234
TEST_CASE(buffer_overrun_bailoutIfSwitch); // ticket #2378 : bailoutIfSwitch
234235
TEST_CASE(buffer_overrun_function_array_argument);
@@ -3638,6 +3639,44 @@ class TestBufferOverrun : public TestFixture {
36383639
ASSERT_EQUALS("", errout_str());
36393640
}
36403641

3642+
void buffer_overrun_39() { // #11765
3643+
check("void f() {\n"
3644+
" char buf[10];\n"
3645+
" memcpy(buf, \"abc\", 4);\n"
3646+
"}\n");
3647+
ASSERT_EQUALS("", errout_str());
3648+
3649+
check("void f() {\n"
3650+
" char buf[128];\n"
3651+
" memcpy(buf, \"abc\", 5);\n"
3652+
"}\n");
3653+
ASSERT_EQUALS("[test.cpp:3:17]: (warning) Buffer is accessed out of bounds: \"abc\" [bufferAccessOutOfBounds]\n",
3654+
errout_str());
3655+
3656+
check("void f() {\n"
3657+
" char buf[128];\n"
3658+
" memcpy(buf, L\"abc\", 4 * sizeof(wchar_t));\n"
3659+
"}\n");
3660+
ASSERT_EQUALS("", errout_str());
3661+
3662+
check("void f() {\n"
3663+
" char buf[128];\n"
3664+
" memcpy(buf, L\"abc\", 4 * sizeof(wchar_t) + 1);\n"
3665+
"}\n");
3666+
ASSERT_EQUALS("[test.cpp:3:17]: (warning) Buffer is accessed out of bounds: L\"abc\" [bufferAccessOutOfBounds]\n",
3667+
errout_str());
3668+
3669+
check("int f(char* s) {\n"
3670+
" return memcmp(s, \"\\0\\0\\0\", 3);\n"
3671+
"}\n");
3672+
ASSERT_EQUALS("", errout_str());
3673+
3674+
check("int f(const char16_t* buf) {\n"
3675+
" return memcmp(buf, u\"abc\", 4 * sizeof(char16_t));\n"
3676+
"}\n");
3677+
ASSERT_EQUALS("", errout_str());
3678+
}
3679+
36413680
void buffer_overrun_errorpath() {
36423681
setMultiline();
36433682
Settings s = settings0;
@@ -4618,9 +4657,8 @@ class TestBufferOverrun : public TestFixture {
46184657
check("void f() {\n"
46194658
" mymemset(\"abc\", 0, 20);\n"
46204659
"}\n", settings);
4621-
TODO_ASSERT_EQUALS("[test.cpp:2]: (error) Buffer is accessed out of bounds.\n",
4622-
"",
4623-
errout_str());
4660+
ASSERT_EQUALS("[test.cpp:2:12]: (warning) Buffer is accessed out of bounds: \"abc\" [bufferAccessOutOfBounds]\n",
4661+
errout_str());
46244662

46254663
check("void f() {\n"
46264664
" mymemset(temp, \"abc\", 4);\n"

0 commit comments

Comments
 (0)