You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
voidcheckNormal_(constchar* file, int line, constchar (&code)[size]) {
// Tokenize..
SimpleTokenizer tokenizer(settings, *this);
ASSERT_LOC(tokenizer.tokenize(code), file, line);
CheckStl check;
runChecks(check, tokenizer, *this);
}
voidoutOfBounds() {
setMultiline();
checkNormal("bool f(const int a, const int b)\n"// #8648
"{\n"
" std::cout << a << b;\n"
" return true;\n"
"}\n"
"void f(const std::vector<int> &v)\n"
"{\n"
" if(v.size() >=2 &&\n"
" bar(v[2], v[3]) )\n"// v[3] is accessed
" {;}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9:18]: warning: Either the condition 'v.size()>=2' is redundant or size of 'v' can be 2. Expression 'v[2]' causes access out of bounds. [containerOutOfBounds]\n"
"[test.cpp:9:24]: warning: Either the condition 'v.size()>=2' is redundant or size of 'v' can be 2. Expression 'v[3]' causes access out of bounds. [containerOutOfBounds]\n"
"[test.cpp:9:24]: note: Access out of bounds\n", errout_str());
checkNormal("void f() {\n"
" std::string s;\n"
" s[10] = 1;\n"
"}");
ASSERT_EQUALS("[test.cpp:3:4]: error: Out of bounds access in expression 's[10]' because 's' is empty. [containerOutOfBounds]\n", errout_str());
checkNormal("void f() {\n"
" std::string s = \"abcd\";\n"
" s[10] = 1;\n"
"}");
ASSERT_EQUALS("[test.cpp:3:4]: error: Out of bounds access in 's[10]', if 's' size is 4 and '10' is 10 [containerOutOfBounds]\n", errout_str());
checkNormal("void f(std::vector<int> v) {\n"
" v.front();\n"
" if (v.empty()) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:2:12]: warning: Either the condition 'v.empty()' is redundant or expression 'v.front()' causes access out of bounds. [containerOutOfBounds]\n"
"[test.cpp:3:16]: note: condition 'v.empty()'\n"
"[test.cpp:2:12]: note: Access out of bounds\n", errout_str());
checkNormal("void f(std::vector<int> v) {\n"
" if (v.size() == 3) {}\n"
" v[16] = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:3:6]: warning: Either the condition 'v.size()==3' is redundant or size of 'v' can be 3. Expression 'v[16]' causes access out of bounds. [containerOutOfBounds]\n"
"[test.cpp:3:6]: note: Access out of bounds\n", errout_str());
checkNormal("void f(std::vector<int> v) {\n"
" int i = 16;\n"
" if (v.size() == 3) {\n"
" v[i] = 0;\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:4:10]: warning: Either the condition 'v.size()==3' is redundant or size of 'v' can be 3. Expression 'v[i]' causes access out of bounds. [containerOutOfBounds]\n"
"[test.cpp:4:10]: note: Access out of bounds\n", errout_str());
checkNormal("void f(std::vector<int> v, int i) {\n"
" if (v.size() == 3 || i == 16) {}\n"
" v[i] = 0;\n"
"}");
ASSERT_EQUALS("", errout_str());
checkNormal("void f(std::map<int,int> x) {\n"
" if (x.empty()) { x[1] = 2; }\n"
"}");
ASSERT_EQUALS("", errout_str());
checkNormal("void f(std::string s) {\n"
" if (s.size() == 1) {\n"
" s[2] = 0;\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:3:10]: warning: Either the condition 's.size()==1' is redundant or size of 's' can be 1. Expression 's[2]' causes access out of bounds. [containerOutOfBounds]\n"
"[test.cpp:3:10]: note: Access out of bounds\n", errout_str());
// Do not crash
checkNormal("void a() {\n"
" std::string b[];\n"
" for (auto c : b)\n"
" c.data();\n"
"}");
ASSERT_EQUALS("", errout_str());
checkNormal("std::string f(std::string x) {\n"
" if (x.empty()) return {};\n"
" x[0];\n"
"}");
ASSERT_EQUALS("", errout_str());
checkNormal("std::string f(std::string x) {\n"
" if (x.empty()) return std::string{};\n"
" x[0];\n"
"}");
ASSERT_EQUALS("", errout_str());
checkNormal("void f() {\n"
" std::string s;\n"
" x = s.begin() + 1;\n"
"}");
ASSERT_EQUALS(
"[test.cpp:3:17]: error: Out of bounds access in expression 's.begin()+1' because 's' is empty. [containerOutOfBounds]\n"
"[test.cpp:3:17]: error: Out of bounds access in expression 's.begin()+1' because 's' is empty. [containerOutOfBounds]\n", // duplicate
errout_str());
checkNormal("void f(int x) {\n"
" std::string s;\n"
" auto it = s.begin() + x;\n"
"}");
ASSERT_EQUALS("[test.cpp:3:23]: error: Out of bounds access in expression 's.begin()+x' because 's' is empty and 'x' may be non-zero. [containerOutOfBounds]\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]; }");
ASSERT_EQUALS("[test.cpp:1:54]: error: Out of bounds access in 's[42]', if 's' size is 6 and '42' is 42 [containerOutOfBounds]\n"
"[test.cpp:2:60]: error: Out of bounds access in 's[42]', if 's' size is 6 and '42' is 42 [containerOutOfBounds]\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]; }");
ASSERT_EQUALS("", errout_str());
checkNormal("int f() {\n"
" std::vector<int> v;\n"
" std::vector<int> * pv = &v;\n"
" return (*pv)[42];\n"
"}");
ASSERT_EQUALS("[test.cpp:4:17]: error: Out of bounds access in expression '(*pv)[42]' because '*pv' is empty. [containerOutOfBounds]\n", errout_str());
checkNormal("void f() {\n"
" std::string s;\n"
" ++abc[s];\n"
"}");
ASSERT_EQUALS("", errout_str());
// # 9274
checkNormal("char f(bool b) {\n"
" const std::string s = \"<a><b>\";\n"
" int x = 6;\n"
" if(b) ++x;\n"
" return s[x];\n"
"}");
ASSERT_EQUALS(
"[test.cpp:5:13]: error: Out of bounds access in 's[x]', if 's' size is 6 and 'x' is 7 [containerOutOfBounds]\n",
errout_str());
checkNormal("void f() {\n"
" static const int N = 4;\n"
" std::array<int, N> x;\n"
" x[0] = 0;\n"
"}");
ASSERT_EQUALS("", errout_str());
checkNormal("void f(bool b) {\n"
" std::vector<int> x;\n"
" if (b)\n"
" x.push_back(1);\n"
" if (x.size() < 2)\n"
" return;\n"
" x[0] = 2;\n"
"}\n");
ASSERT_EQUALS("", errout_str());
checkNormal("void f(bool b) {\n"
" std::vector<int> v;\n"
" if(v.at(b?42:0)) {}\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:3:12]: error: Out of bounds access in expression 'v.at(b?42:0)' because 'v' is empty. [containerOutOfBounds]\n",
"[test.cpp:3:16]: warning: Either the condition 'v.size()==1' is redundant or size of 'v' can be 1. Expression 'v.at(b?42:0)' causes access out of bounds. [containerOutOfBounds]\n"
ASSERT_EQUALS("[test.cpp:2:38]: warning: Either the condition 'v.size()>=1' is redundant or size of 'v' can be 1. Expression 'v[1]' causes access out of bounds. [containerOutOfBounds]\n"
"[test.cpp:2:38]: note: Access out of bounds\n", errout_str());
checkNormal("int f(int x, int y) {\n"
" std::vector<int> a = {0,1,2};\n"
" if(x<2)\n"
" y = a[x] + 1;\n"
" else\n"
" y = a[x];\n"
" return y;\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:6:14]: warning: Either the condition 'x<2' is redundant or 'x' can have the value greater or equal to 3. Expression 'a[x]' causes access out of bounds. [containerOutOfBounds]\n"
"[test.cpp:3:9]: note: condition 'x<2'\n"
"[test.cpp:6:14]: note: Access out of bounds\n",
errout_str());
checkNormal("int f(std::vector<int> v) {\n"
" if (v.size() > 3)\n"
" return v[v.size() - 3];\n"
" return 0;\n"
"}\n");
ASSERT_EQUALS("", errout_str());
checkNormal("void f(std::vector<int> v) {\n"
" v[v.size() - 1];\n"
" if (v.size() == 1) {}\n"
"}\n");
ASSERT_EQUALS("", errout_str());
checkNormal("void f(int n) {\n"
" std::vector<int> v = {1, 2, 3, 4};\n"
" const int i = qMin(n, v.size());\n"
" if (i > 1)\n"
" v[i] = 1;\n"
"}\n");
ASSERT_EQUALS("", errout_str());
checkNormal("void f(std::vector<int>& v, int i) {\n"
checkNormal("void f(int i, std::vector<int> v) {\n"// #9157
" if (i <= (int)v.size()) {\n"
" if (v[i]) {}\n"
" }\n"
" if (i <= static_cast<int>(v.size())) {\n"
" if (v[i]) {}\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:14]: warning: Either the condition 'i<=(int)v.size()' is redundant or 'i' can have the value v.size(). Expression 'v[i]' causes access out of bounds. [containerOutOfBounds]\n"
"[test.cpp:6:14]: warning: Either the condition 'i<=static_cast<int>(v.size())' is redundant or 'i' can have the value v.size(). Expression 'v[i]' causes access out of bounds. [containerOutOfBounds]\n"
ASSERT_EQUALS("[test.cpp:4:5]: error: Out of bounds access in expression 'd+c.length()' because 'buf' is empty. [containerOutOfBounds]\n",
errout_str());
check("template<class Iterator>\n"
"void b(Iterator d) {\n"
" std::string c = \"a\";\n"
" sort(d, d + c.length());\n"
"}\n"
"void f() {\n"
" std::string buf;\n"
" b(buf.begin());\n"
"}\n",
dinit(CheckOptions, $.inconclusive = true));
ASSERT_EQUALS("", errout_str());
check("int f(const std::vector<int> &v) {\n"
" return !v.empty() ? 42 : v.back();\n"
"}\n",
dinit(CheckOptions, $.inconclusive = true));
ASSERT_EQUALS(
"[test.cpp:2:36]: warning: Either the condition 'v.empty()' is redundant or expression 'v.back()' causes access out of bounds. [containerOutOfBounds]\n"
"[test.cpp:2:20]: note: condition 'v.empty()'\n"
"[test.cpp:2:36]: note: Access out of bounds\n",
errout_str());
check("std::vector<int> g() {\n"// #10779
" std::vector<int> v(10);\n"
" for(int i = 0; i <= 10; ++i)\n"
" v[i] = 42;\n"
" return v;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4:10]: error: Out of bounds access in 'v[i]', if 'v' size is 10 and 'i' is 10 [containerOutOfBounds]\n",
errout_str());
check("void f() {\n"
" int s = 2;\n"
" std::vector <int> v(s);\n"
" v[100] = 1;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4:6]: error: Out of bounds access in 'v[100]', if 'v' size is 2 and '100' is 100 [containerOutOfBounds]\n",
errout_str());
check("void f() {\n"
" std::vector <int> v({ 1, 2, 3 });\n"
" v[100] = 1;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:6]: error: Out of bounds access in 'v[100]', if 'v' size is 3 and '100' is 100 [containerOutOfBounds]\n",
errout_str());
check("void f() {\n"
" char c[] = { 1, 2, 3 };\n"
" std::vector<char> v(c, sizeof(c) + c);\n"
" v[100] = 1;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4:6]: error: Out of bounds access in 'v[100]', if 'v' size is 3 and '100' is 100 [containerOutOfBounds]\n",
errout_str());
check("void f() {\n"
" char c[] = { 1, 2, 3 };\n"
" std::vector<char> v{ c, c + sizeof(c) };\n"
" v[100] = 1;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4:6]: error: Out of bounds access in 'v[100]', if 'v' size is 3 and '100' is 100 [containerOutOfBounds]\n",
errout_str());
check("void f() {\n"
" int i[] = { 1, 2, 3 };\n"
" std::vector<int> v(i, i + sizeof(i) / 4);\n"
" v[100] = 1;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4:6]: error: Out of bounds access in 'v[100]', if 'v' size is 3 and '100' is 100 [containerOutOfBounds]\n",
errout_str());
check("void f() {\n"// #6615
" int i[] = { 1, 2, 3 };\n"
" std::vector<int> v(i, i + sizeof(i) / sizeof(int));\n"
" v[100] = 1;\n"
"}\n");
TODO_ASSERT_EQUALS("test.cpp:4:error:Out of bounds access in 'v[100]', if 'v' size is 3 and '100' is 100\n",
"",
errout_str());
check("void f() {\n"
" std::array<int, 10> a = {};\n"
" a[10];\n"
" constexpr std::array<int, 10> b = {};\n"
" b[10];\n"
" const std::array<int, 10> c = {};\n"
" c[10];\n"
" static constexpr std::array<int, 10> d = {};\n"
" d[10];\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:6]: error: Out of bounds access in 'a[10]', if 'a' size is 10 and '10' is 10 [containerOutOfBounds]\n"
"[test.cpp:5:6]: error: Out of bounds access in 'b[10]', if 'b' size is 10 and '10' is 10 [containerOutOfBounds]\n"
"[test.cpp:7:6]: error: Out of bounds access in 'c[10]', if 'c' size is 10 and '10' is 10 [containerOutOfBounds]\n"
"[test.cpp:9:6]: error: Out of bounds access in 'd[10]', if 'd' size is 10 and '10' is 10 [containerOutOfBounds]\n",
errout_str());
check("struct test_fixed {\n"
" std::array<int, 10> array = {};\n"
" void index(int i) { array[i]; }\n"
"};\n"
"void f() {\n"
" test_fixed x = test_fixed();\n"
" x.index(10);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3:30]: error: Out of bounds access in 'array[i]', if 'array' size is 10 and 'i' is 10 [containerOutOfBounds]\n",