Fix issue 8431 and 8776: Size of constant string

Fixes these cases:

```cpp
void f(void) {
        const std::string msg="xyz";
        if(!msg.empty()){} // Always true
}
```

And out of bounds access:

```cpp
#include <string>
char fstr1(){const std::string s = "<a><b>"; return s[42]; }
wchar_t fwstr1(){const std::wstring s = L"<a><b>"; return s[42]; }
```
This commit is contained in:
Paul Fultz II 2019-08-12 20:24:16 +02:00 committed by Daniel Marjamäki
parent 68e8253920
commit c0c6f92221
3 changed files with 23 additions and 1 deletions

View File

@ -5257,7 +5257,7 @@ static void valueFlowContainerSize(TokenList *tokenlist, SymbolDatabase* symbold
// after assignment // after assignment
for (const Scope *functionScope : symboldatabase->functionScopes) { for (const Scope *functionScope : symboldatabase->functionScopes) {
for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) {
if (Token::Match(tok, "[;{}] %var% = %str% ;")) { if (Token::Match(tok, "%name%|;|{|} %var% = %str% ;")) {
const Token *containerTok = tok->next(); const Token *containerTok = tok->next();
if (containerTok && containerTok->valueType() && containerTok->valueType()->container && containerTok->valueType()->container->stdStringLike) { if (containerTok && containerTok->valueType() && containerTok->valueType()->container && containerTok->valueType()->container->stdStringLike) {
ValueFlow::Value value(Token::getStrLength(containerTok->tokAt(2))); ValueFlow::Value value(Token::getStrLength(containerTok->tokAt(2)));

View File

@ -3176,6 +3176,19 @@ private:
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void f() {\n"
" const std::string x=\"xyz\";\n"
" if(!x.empty()){}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Condition '!x.empty()' is always true\n", errout.str());
check("std::string g();\n"
"void f() {\n"
" const std::string msg = g();\n"
" if(!msg.empty()){}\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void f(int *array, int size ) {\n" check("void f(int *array, int size ) {\n"
" for(int i = 0; i < size; ++i) {\n" " for(int i = 0; i < size; ++i) {\n"
" if(array == 0)\n" " if(array == 0)\n"

View File

@ -290,6 +290,15 @@ private:
"}\n"); "}\n");
ASSERT_EQUALS("test.cpp:3:error:Out of bounds access in expression 's.begin()+x' because 's' is empty and 'x' may be non-zero.\n", errout.str()); ASSERT_EQUALS("test.cpp:3:error:Out of bounds access in expression 's.begin()+x' because 's' is empty and 'x' may be non-zero.\n", errout.str());
checkNormal("char fstr1(){const std::string s = \"<a><b>\"; return s[42]; }\n"
"wchar_t fwstr1(){const std::wstring s = L\"<a><b>\"; return s[42]; }\n");
ASSERT_EQUALS("test.cpp:1:error:Out of bounds access in 's[42]', if 's' size is 6 and '42' is 42\n"
"test.cpp:2:error:Out of bounds access in 's[42]', if 's' size is 6 and '42' is 42\n", errout.str());
checkNormal("char fstr1(){const std::string s = \"<a><b>\"; return s[1]; }\n"
"wchar_t fwstr1(){const std::wstring s = L\"<a><b>\"; return s[1]; }\n");
ASSERT_EQUALS("", errout.str());
checkNormal("int f() {\n" checkNormal("int f() {\n"
" std::vector<int> v;\n" " std::vector<int> v;\n"
" std::vector<int> * pv = &v;\n" " std::vector<int> * pv = &v;\n"