diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 4892fa65a..5ebcf68f1 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -1246,6 +1246,17 @@ void CheckBufferOverrun::checkReadlinkBufferUsage(const Token* tok, const Token void CheckBufferOverrun::checkGlobalAndLocalVariable() { + // check string literals + for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { + if (Token::Match(tok, "%str% [ %num% ]")) { + std::string str = tok->strValue(); + std::size_t index = atoi(tok->tokAt(2)->str().c_str()); + if (index > str.length()) { + bufferOverrunError(tok, tok->str()); + } + } + } + // check all known fixed size arrays first by just looking them up for (unsigned int i = 1; i <= _tokenizer->varIdCount(); i++) { const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(i); diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index f8aa6ad57..76f6a5c60 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -128,6 +128,7 @@ private: TEST_CASE(array_index_vla_for); // #3221: access VLA inside for TEST_CASE(array_index_extern); // FP when using 'extern'. #1684 TEST_CASE(array_index_cast); // FP after cast. #2841 + TEST_CASE(array_index_string_literal); TEST_CASE(buffer_overrun_1); TEST_CASE(buffer_overrun_2); @@ -1657,6 +1658,38 @@ private: ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:2]: (error) Array 'x[2]' index 4 out of bounds\n", errout.str()); } + void array_index_string_literal() { + check("void f()\n" + "{\n" + " const char *str = \"abc\";\n" + " int i = 10;\n" + " bar(str[i]);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5]: (error) Buffer access out-of-bounds: \"abc\"\n", errout.str()); + + check("void f()\n" + "{\n" + " const char *str = \"abc\";\n" + " bar(str[4]);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: \"abc\"\n", errout.str()); + + check("void f()\n" + "{\n" + " const char *str = \"abc\";\n" + " bar(str[3]);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + check("void f()\n" + "{\n" + " const char *str = \"a\tc\";\n" + " bar(str[4]);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: \"a\tc\"\n", errout.str()); + + } + void buffer_overrun_1() { check("void f()\n" "{\n"