FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2026 Cppcheck team. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "check.h" #include "checkbufferoverrun.h" #include "ctu.h" #include "errortypes.h" #include "helpers.h" #include "platform.h" #include "settings.h" #include "fixture.h" #include #include #include class TestBufferOverrun : public TestFixture { public: TestBufferOverrun() : TestFixture("TestBufferOverrun") {} private: /*const*/ Settings settings0 = settingsBuilder().library("std.cfg").severity(Severity::warning).severity(Severity::style).build(); const Settings settings0_i = settingsBuilder(settings0).certainty(Certainty::inconclusive).build(); const Settings settings0_p = settingsBuilder(settings0).severity(Severity::portability).build(); const Settings settings1 = settingsBuilder(settings0).severity(Severity::performance).certainty(Certainty::inconclusive).build(); struct CheckOptions { bool cpp = true; }; #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__) template void check_(const char* file, int line, const char (&code)[size], const CheckOptions& options = make_default_obj()) { check_(file, line, code, settings0_i, options.cpp); } template void check_(const char* file, int line, const char (&code)[size], const Settings& settings, bool cpp = true) { SimpleTokenizer tokenizer(settings, *this, cpp); ASSERT_LOC(tokenizer.tokenize(code), file, line); CheckBufferOverrun check; runChecks(check, tokenizer, *this); } // TODO: get rid of this void check_(const char* file, int line, const std::string& code) { // Tokenize.. SimpleTokenizer tokenizer(settings0_i, *this); ASSERT_LOC(tokenizer.tokenize(code), file, line); CheckBufferOverrun check; runChecks(check, tokenizer, *this); } #define checkP(...) checkP_(__FILE__, __LINE__, __VA_ARGS__) template void checkP_(const char* file, int line, const char (&code)[size]) { SimpleTokenizer2 tokenizer(settings1, *this, code, "test.cpp"); // Tokenizer.. ASSERT_LOC(tokenizer.simplifyTokens1(""), file, line); CheckBufferOverrun check; runChecks(check, tokenizer, *this); } void run() override { mNewTemplate = true; TEST_CASE(noerr1); TEST_CASE(noerr2); TEST_CASE(noerr3); TEST_CASE(noerr4); TEST_CASE(sizeof3); TEST_CASE(array_index_1); TEST_CASE(array_index_2); TEST_CASE(array_index_3); TEST_CASE(array_index_4); TEST_CASE(array_index_6); TEST_CASE(array_index_7); TEST_CASE(array_index_11); TEST_CASE(array_index_12); TEST_CASE(array_index_13); TEST_CASE(array_index_14); TEST_CASE(array_index_15); TEST_CASE(array_index_16); TEST_CASE(array_index_17); TEST_CASE(array_index_18); TEST_CASE(array_index_19); TEST_CASE(array_index_20); TEST_CASE(array_index_21); TEST_CASE(array_index_22); TEST_CASE(array_index_23); TEST_CASE(array_index_24); // ticket #1492 and #1539 TEST_CASE(array_index_25); // ticket #1536 TEST_CASE(array_index_26); TEST_CASE(array_index_27); TEST_CASE(array_index_28); // ticket #1418 TEST_CASE(array_index_29); // ticket #1734 TEST_CASE(array_index_30); // ticket #2086 - out of bounds when type is unknown TEST_CASE(array_index_31); // ticket #2120 - out of bounds in subfunction when type is unknown TEST_CASE(array_index_32); TEST_CASE(array_index_33); // ticket #3044 TEST_CASE(array_index_34); // ticket #3063 TEST_CASE(array_index_35); // ticket #2889 TEST_CASE(array_index_36); // ticket #2960 TEST_CASE(array_index_37); TEST_CASE(array_index_38); // ticket #3273 TEST_CASE(array_index_39); TEST_CASE(array_index_40); // loop variable calculation, taking address TEST_CASE(array_index_41); // structs with the same name TEST_CASE(array_index_42); TEST_CASE(array_index_43); // struct with array TEST_CASE(array_index_44); // #3979 TEST_CASE(array_index_45); // #4207 - calling function with variable number of parameters (...) TEST_CASE(array_index_46); // #4840 - two-statement for loop TEST_CASE(array_index_47); // #5849 TEST_CASE(array_index_48); // #9478 TEST_CASE(array_index_49); // #8653 TEST_CASE(array_index_50); TEST_CASE(array_index_51); // #3763 TEST_CASE(array_index_52); // #7682 TEST_CASE(array_index_53); // #4750 TEST_CASE(array_index_54); // #10268 TEST_CASE(array_index_55); // #10254 TEST_CASE(array_index_56); // #10284 TEST_CASE(array_index_57); // #10023 TEST_CASE(array_index_58); // #7524 TEST_CASE(array_index_59); // #10413 TEST_CASE(array_index_60); // #10617, #9824 TEST_CASE(array_index_61); // #10621 TEST_CASE(array_index_62); // #7684 TEST_CASE(array_index_63); // #10979 TEST_CASE(array_index_64); // #10878 TEST_CASE(array_index_65); // #11066 TEST_CASE(array_index_66); // #10740 TEST_CASE(array_index_67); // #1596 TEST_CASE(array_index_68); // #6655 TEST_CASE(array_index_69); // #6370 TEST_CASE(array_index_70); // #11355 TEST_CASE(array_index_71); // #11461 TEST_CASE(array_index_72); // #11784 TEST_CASE(array_index_73); // #11530 TEST_CASE(array_index_74); // #11088 TEST_CASE(array_index_75); TEST_CASE(array_index_76); TEST_CASE(array_index_multidim); TEST_CASE(array_index_switch_in_for); TEST_CASE(array_index_for_in_for); // FP: #2634 TEST_CASE(array_index_bounds); TEST_CASE(array_index_calculation); TEST_CASE(array_index_negative1); TEST_CASE(array_index_negative2); // ticket #3063 TEST_CASE(array_index_negative3); TEST_CASE(array_index_negative4); TEST_CASE(array_index_negative5); // #10526 TEST_CASE(array_index_negative6); // #11349 TEST_CASE(array_index_negative7); // #5685 TEST_CASE(array_index_negative8); // #11651 TEST_CASE(array_index_negative9); TEST_CASE(array_index_negative10); TEST_CASE(array_index_for_decr); TEST_CASE(array_index_varnames); // FP: struct member #1576, FN: #1586 TEST_CASE(array_index_for_continue); // for,continue TEST_CASE(array_index_for); // FN: for,if TEST_CASE(array_index_for_neq); // #2211: Using != in condition TEST_CASE(array_index_for_question); // #2561: for, ?: TEST_CASE(array_index_for_andand_oror); // FN: using && or || in the for loop condition TEST_CASE(array_index_for_varid0); // #4228: No varid for counter variable 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(array_index_same_struct_and_var_name); // #4751 - not handled well when struct name and var name is same TEST_CASE(array_index_valueflow); TEST_CASE(array_index_valueflow_pointer); TEST_CASE(array_index_function_parameter); TEST_CASE(array_index_enum_array); // #8439 TEST_CASE(array_index_container); // #9386 TEST_CASE(array_index_container_data); // pointer from data()/c_str() carries the container size TEST_CASE(array_index_two_for_loops); TEST_CASE(array_index_new); // #7690 TEST_CASE(buffer_overrun_2_struct); TEST_CASE(buffer_overrun_3); TEST_CASE(buffer_overrun_4); TEST_CASE(buffer_overrun_5); TEST_CASE(buffer_overrun_6); TEST_CASE(buffer_overrun_7); TEST_CASE(buffer_overrun_8); TEST_CASE(buffer_overrun_9); TEST_CASE(buffer_overrun_10); TEST_CASE(buffer_overrun_11); TEST_CASE(buffer_overrun_15); // ticket #1787 TEST_CASE(buffer_overrun_16); TEST_CASE(buffer_overrun_18); // ticket #2576 - for, calculation with loop variable TEST_CASE(buffer_overrun_19); // #2597 - class member with unknown type TEST_CASE(buffer_overrun_21); TEST_CASE(buffer_overrun_24); // index variable is changed in for-loop TEST_CASE(buffer_overrun_26); // #4432 (segmentation fault) TEST_CASE(buffer_overrun_27); // #4444 (segmentation fault) TEST_CASE(buffer_overrun_29); // #7083: false positive: typedef and initialization with strings TEST_CASE(buffer_overrun_30); // #6367 TEST_CASE(buffer_overrun_31); TEST_CASE(buffer_overrun_32); //#10244 TEST_CASE(buffer_overrun_33); //#2019 TEST_CASE(buffer_overrun_34); //#11035 TEST_CASE(buffer_overrun_35); //#2304 TEST_CASE(buffer_overrun_36); TEST_CASE(buffer_overrun_37); TEST_CASE(buffer_overrun_38); TEST_CASE(buffer_overrun_errorpath); TEST_CASE(buffer_overrun_bailoutIfSwitch); // ticket #2378 : bailoutIfSwitch TEST_CASE(buffer_overrun_function_array_argument); TEST_CASE(possible_buffer_overrun_1); // #3035 TEST_CASE(buffer_overrun_readSizeFromCfg); TEST_CASE(buffer_overrun_handle_addr_of_var); // ticket #7570 - correctly handle &var TEST_CASE(valueflow_string); // using ValueFlow string values in checking // It is undefined behaviour to point out of bounds of an array // the address beyond the last element is in bounds // char a[10]; // char *p1 = a + 10; // OK // char *p2 = a + 11 // UB TEST_CASE(pointer_out_of_bounds_1); TEST_CASE(pointer_out_of_bounds_2); TEST_CASE(pointer_out_of_bounds_3); TEST_CASE(pointer_out_of_bounds_4); TEST_CASE(pointer_out_of_bounds_5); // #10227 TEST_CASE(pointer_out_of_bounds_sub); TEST_CASE(strcat1); TEST_CASE(varid1); TEST_CASE(varid2); // ticket #4764 TEST_CASE(assign1); TEST_CASE(alloc_new); // Buffer allocated with new TEST_CASE(alloc_malloc); // Buffer allocated with malloc TEST_CASE(alloc_string); // statically allocated buffer TEST_CASE(alloc_alloca); // Buffer allocated with alloca // TODO TEST_CASE(countSprintfLength); TEST_CASE(minsize_argvalue); TEST_CASE(minsize_sizeof); TEST_CASE(minsize_strlen); TEST_CASE(minsize_mul); TEST_CASE(unknownType); TEST_CASE(terminateStrncpy1); TEST_CASE(terminateStrncpy2); TEST_CASE(terminateStrncpy3); TEST_CASE(terminateStrncpy4); TEST_CASE(terminateStrncpy5); // #9944 TEST_CASE(terminateStrncpy_handle_addr_of_var); // #7570 TEST_CASE(recursive_long_time); TEST_CASE(crash1); // Ticket #1587 - crash TEST_CASE(crash2); // Ticket #3034 - crash TEST_CASE(crash3); // Ticket #5426 - crash TEST_CASE(crash4); // Ticket #8679 - crash TEST_CASE(crash5); // Ticket #8644 - crash TEST_CASE(crash6); // Ticket #9024 - crash TEST_CASE(crash7); // Ticket #9073 - crash TEST_CASE(insecureCmdLineArgs); TEST_CASE(checkBufferAllocatedWithStrlen); TEST_CASE(scope); // handling different scopes TEST_CASE(getErrorMessages); // Access array and then check if the used index is within bounds TEST_CASE(arrayIndexThenCheck); TEST_CASE(arrayIndexEarlyReturn); // #6884 TEST_CASE(bufferNotZeroTerminated); TEST_CASE(negativeMemoryAllocationSizeError); // #389 TEST_CASE(negativeArraySize); TEST_CASE(pointerAddition1); TEST_CASE(ctu_malloc); TEST_CASE(ctu_array); TEST_CASE(ctu_variable); TEST_CASE(ctu_arithmetic); TEST_CASE(objectIndex); TEST_CASE(checkPipeParameterSize); // ticket #3521 } void noerr1() { check("extern int ab;\n" "void f()\n" "{\n" " if (ab)\n" " {\n" " char str[50];\n" " }\n" " if (ab)\n" " {\n" " char str[50];\n" " }\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void noerr2() { check("static char buf[2];\n" "void f1(char *str)\n" "{\n" " strcpy(buf,str);\n" "}\n" "void f2(char *str)\n" "{\n" " strcat(buf,str);\n" "}\n" "void f3(char *str)\n" "{\n" " sprintf(buf,\"%s\",str);\n" "}\n" "void f4(const char str[])\n" "{\n" " strcpy(buf, str);\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void noerr3() { check("struct { char data[10]; } abc;\n" "static char f()\n" "{\n" " char data[1];\n" " return abc.data[1];\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void noerr4() { // The memory isn't read or written and therefore there is no error. check("static void f() {\n" " char data[100];\n" " const char *p = data + 100;\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void sizeof3() { check("struct group { int gr_gid; };\n" "void f()\n" "{\n" " char group[32];\n" " snprintf(group, 32, \"%u\", 0);\n" " struct group *gr;\n" " snprintf(group, 32, \"%u\", gr->gr_gid);\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void array_index_1() { check("void f()\n" "{\n" " char str[0x10] = {0};\n" " str[15] = 0;\n" " str[16] = 0;\n" "}\n"); ASSERT_EQUALS("[test.cpp:5:8]: (error) Array 'str[16]' accessed at index 16, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("char f()\n" "{\n" " char str[16] = {0};\n" " return str[16];\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:15]: (error) Array 'str[16]' accessed at index 16, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); // test stack array check("int f()\n" "{\n" " int x[ 3 ] = { 0, 1, 2 };\n" " int y;\n" " y = x[ 4 ];\n" " return y;\n" "}\n"); ASSERT_EQUALS("[test.cpp:5:9]: (error) Array 'x[3]' accessed at index 4, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("int f()\n" "{\n" " int x[ 3 ] = { 0, 1, 2 };\n" " int y;\n" " y = x[ 2 ];\n" " return y;\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("int x[5] = {0};\n" "int a = x[10];\n"); ASSERT_EQUALS("[test.cpp:2:10]: (error) Array 'x[5]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("int x[5] = {0};\n" "int a = (x)[10];\n"); ASSERT_EQUALS("[test.cpp:2:12]: (error) Array 'x[5]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_2() { check("void a(int i)\n" // valueflow "{\n" " char *str = new char[0x10];\n" " str[i] = 0;\n" "}\n" "void b() { a(16); }\n"); ASSERT_EQUALS("[test.cpp:4:8]: (error) Array 'str[16]' accessed at index 16, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_4() { check("char c = \"abc\"[4];\n"); ASSERT_EQUALS("[test.cpp:1:15]: (error) Array '\"abc\"[4]' accessed at index 4, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("p = &\"abc\"[4];\n"); ASSERT_EQUALS("", errout_str()); check("char c = \"\\0abc\"[2];\n"); ASSERT_EQUALS("", errout_str()); check("char c = L\"abc\"[4];\n"); ASSERT_EQUALS("[test.cpp:1:16]: (error) Array 'L\"abc\"[4]' accessed at index 4, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_3() { check("void f()\n" "{\n" " int val[50];\n" " int i, sum=0;\n" " for (i = 0; i < 100; i++)\n" " sum += val[i];\n" "}\n"); ASSERT_EQUALS("[test.cpp:6:19]: (error) Array 'val[50]' accessed at index 99, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("void f()\n" "{\n" " int val[50];\n" " int i, sum=0;\n" " for (i = 1; i < 100; i++)\n" " sum += val[i];\n" "}\n"); ASSERT_EQUALS("[test.cpp:6:19]: (error) Array 'val[50]' accessed at index 99, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("void f(int a)\n" "{\n" " int val[50];\n" " int i, sum=0;\n" " for (i = a; i < 100; i++)\n" " sum += val[i];\n" "}\n"); ASSERT_EQUALS("[test.cpp:6:19]: (error) Array 'val[50]' accessed at index 99, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("typedef struct g g2[3];\n" "void foo(char *a)\n" "{\n" " for (int i = 0; i < 4; i++)\n" " {\n" " a[i]=0;\n" " }\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("void foo(int argc)\n" "{\n" " char a[2];\n" " for (int i = 4; i < argc; i++){}\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("void foo(int a[10]) {\n" " for (int i=0;istr[1] = 0;" "}\n"); ASSERT_EQUALS("", errout_str()); // This is not out of bounds because it is not a variable length array check("struct ABC\n" "{\n" " char str[1];\n" " int x;\n" "};\n" "\n" "static void f()\n" "{\n" " struct ABC* x = malloc(sizeof(struct ABC) + 10);\n" " x->str[1] = 0;" "}\n"); TODO_ASSERT_EQUALS("error", "", errout_str()); // This is not out of bounds because it is a variable length array // and the index is within the memory allocated. /** @todo this works by accident because we ignore any access to this array */ check("struct ABC\n" "{\n" " char str[1];\n" "};\n" "\n" "static void f()\n" "{\n" " struct ABC* x = malloc(sizeof(struct ABC) + 10);\n" " x->str[10] = 0;\n" "}\n"); ASSERT_EQUALS("", errout_str()); // This is out of bounds because it is outside the memory allocated. /** @todo this doesn't work because of a bug in sizeof(struct) */ check("struct ABC\n" "{\n" " char str[1];\n" "};\n" "\n" "static void f()\n" "{\n" " struct ABC* x = malloc(sizeof(struct ABC) + 10);\n" " x->str[11] = 0;\n" "}\n"); TODO_ASSERT_EQUALS("[test.cpp:9]: (error) Array 'str[1]' accessed at index 11, which is out of bounds.\n", "", errout_str()); // This is out of bounds if 'sizeof(ABC)' is 1 (No padding) check("struct ABC\n" "{\n" " char str[1];\n" "};\n" "\n" "static void f()\n" "{\n" " struct ABC* x = malloc(sizeof(ABC) + 10);\n" " x->str[11] = 0;\n" "}\n"); TODO_ASSERT_EQUALS("error", "", errout_str()); // This is out of bounds because it is outside the memory allocated /** @todo this doesn't work because of a bug in sizeof(struct) */ check("struct ABC\n" "{\n" " char str[1];\n" "};\n" "\n" "static void f()\n" "{\n" " struct ABC* x = malloc(sizeof(struct ABC));\n" " x->str[1] = 0;\n" "}\n"); TODO_ASSERT_EQUALS("[test.cpp:9]: (error) Array 'str[1]' accessed at index 1, which is out of bounds.\n", "", errout_str()); // This is out of bounds because it is outside the memory allocated // But only if 'sizeof(ABC)' is 1 (No padding) check("struct ABC\n" "{\n" " char str[1];\n" "};\n" "\n" "static void f()\n" "{\n" " struct ABC* x = malloc(sizeof(ABC));\n" " x->str[1] = 0;\n" "}\n"); TODO_ASSERT_EQUALS("error", "", errout_str()); // This is out of bounds because it is not a variable array check("struct ABC\n" "{\n" " char str[1];\n" "};\n" "\n" "static void f()\n" "{\n" " struct ABC x;\n" " x.str[1] = 0;\n" "}\n"); ASSERT_EQUALS("[test.cpp:9:10]: (error) Array 'x.str[1]' accessed at index 1, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("struct foo\n" "{\n" " char str[10];\n" "};\n" "\n" "void x()\n" "{\n" " foo f;\n" " for ( unsigned int i = 0; i < 64; ++i )\n" " f.str[i] = 0;\n" "}\n"); ASSERT_EQUALS("[test.cpp:10:14]: (error) Array 'f.str[10]' accessed at index 63, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("struct AB { char a[NUM]; char b[NUM]; }\n" "void f(struct AB *ab) {\n" " ab->a[0] = 0;\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("union { char a[1]; int b; } ab;\n" "void f() {\n" " ab.a[2] = 0;\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:9]: (error) Array 'ab.a[1]' accessed at index 2, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_7() { check("struct ABC\n" "{\n" " char str[10];\n" "};\n" "\n" "static void f(struct ABC *abc)\n" "{\n" " abc->str[10] = 0;\n" "}\n"); ASSERT_EQUALS("[test.cpp:8:13]: (error) Array 'abc->str[10]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_11() { check("class ABC\n" "{\n" "public:\n" " ABC();\n" " char *str[10];\n" " struct ABC *next();\n" "};\n" "\n" "static void f(ABC *abc1)\n" "{\n" " for ( ABC *abc = abc1; abc; abc = abc->next() )\n" " {\n" " abc->str[10] = 0;\n" " }\n" "}\n"); ASSERT_EQUALS("[test.cpp:13:17]: (error) Array 'abc->str[10]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_12() { check("class Fred\n" "{\n" "private:\n" " char str[10];\n" "public:\n" " Fred();\n" "};\n" "Fred::Fred()\n" "{\n" " str[10] = 0;\n" "}\n"); ASSERT_EQUALS("[test.cpp:10:8]: (error) Array 'str[10]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("class Fred\n" "{\n" "private:\n" " char str[10];\n" "public:\n" " char c();\n" "};\n" "char Fred::c()\n" "{\n" " return str[10];\n" "}\n"); ASSERT_EQUALS("[test.cpp:10:15]: (error) Array 'str[10]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_13() { check("void f()\n" "{\n" " char buf[10];\n" " for (int i = 0; i < 100; i++)\n" " {\n" " if (i < 10)\n" " int x = buf[i];\n" " }\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void array_index_14() { check("void f()\n" "{\n" " int a[10];\n" " for (int i = 0; i < 10; i++)\n" " a[i+10] = i;\n" "}\n"); ASSERT_EQUALS("[test.cpp:5:10]: (error) Array 'a[10]' accessed at index 19, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_15() { check("void f()\n" "{\n" " int a[10];\n" " for (int i = 0; i < 10; i++)\n" " a[10+i] = i;\n" "}\n"); ASSERT_EQUALS("[test.cpp:5:10]: (error) Array 'a[10]' accessed at index 19, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_16() { check("void f()\n" "{\n" " int a[10];\n" " for (int i = 0; i < 10; i++)\n" " a[i+1] = i;\n" "}\n"); ASSERT_EQUALS("[test.cpp:5:10]: (error) Array 'a[10]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_17() { check("void f()\n" "{\n" " int a[10];\n" " for (int i = 0; i < 10; i++)\n" " a[i*2] = i;\n" "}\n"); ASSERT_EQUALS("[test.cpp:5:10]: (error) Array 'a[10]' accessed at index 18, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("void f()\n" "{\n" " int a[12];\n" " for (int i = 0; i < 12; i+=6)\n" " a[i+5] = i;\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("void f()\n" "{\n" " int a[12];\n" " for (int i = 0; i < 12; i+=6)\n" " a[i+6] = i;\n" "}\n"); ASSERT_EQUALS("[test.cpp:5:10]: (error) Array 'a[12]' accessed at index 12, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("void f() {\n" // #4398 " int a[2];\n" " for (int i = 0; i < 4; i+=2)\n" " a[i] = 0;\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:10]: (error) Array 'a[2]' accessed at index 2, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("void f() {\n" // #4398 " int a[2];\n" " for (int i = 0; i < 4; i+=2)\n" " do_stuff(a+i);\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void array_index_18() { check("void f()\n" "{\n" " int a[5];\n" " for (int i = 0; i < 6; i++)\n" " {\n" " a[i] = i;\n" " i+=1;\n" " }\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("void f()\n" "{\n" " int a[5];\n" " for (int i = 0; i < 6; i++)\n" " {\n" " a[i] = i;\n" " i++;\n" " }\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("void f()\n" "{\n" " int a[5];\n" " for (int i = 0; i < 6; i++)\n" " {\n" " a[i] = i;\n" " ++i;\n" " }\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("void f()\n" "{\n" " int a[5];\n" " for (int i = 0; i < 6; i++)\n" " {\n" " a[i] = i;\n" " i=4;\n" " }\n" "}\n"); ASSERT_EQUALS("[test.cpp:6:10]: (error) Array 'a[5]' accessed at index 5, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("void f()\n" "{\n" " int a[6];\n" " for (int i = 0; i < 7; i++)\n" " {\n" " a[i] = i;\n" " i+=1;\n" " }\n" "}\n"); TODO_ASSERT_EQUALS("[test.cpp:6]: (error) Buffer overrun\n", "", errout_str()); } void array_index_19() { // "One Past the End" is legal, as long as pointer is not dereferenced. check("void f()\n" "{\n" " char a[2];\n" " char *end = &(a[2]);\n" "}\n"); ASSERT_EQUALS("", errout_str()); // Getting more than one past the end is not legal check("void f()\n" "{\n" " char a[2];\n" " char *end = &(a[3]);\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:18]: (error) Array 'a[2]' accessed at index 3, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_20() { check("void f()\n" "{\n" " char a[8];\n" " int b[10];\n" " for ( int i = 0; i < 9; i++ )\n" " b[i] = 0;\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void array_index_21() { check("class A {\n" " int indices[2];\n" " void foo(int indices[3]);\n" "};\n" "\n" "void A::foo(int indices[3]) {\n" " for(int j=0; jb[10][2] = 4;\n" " ptest->b[0][19] = 4;\n" "}\n"); ASSERT_EQUALS("[test.cpp:9:11]: (error) Array 'test.a[10]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]\n" "[test.cpp:10:11]: (error) Array 'test.b[10][5]' accessed at index test.b[10][2], which is out of bounds. [arrayIndexOutOfBounds]\n" "[test.cpp:11:11]: (error) Array 'test.b[10][5]' accessed at index test.b[0][19], which is out of bounds. [arrayIndexOutOfBounds]\n" "[test.cpp:14:13]: (error) Array 'ptest->a[10]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]\n" "[test.cpp:15:13]: (error) Array 'ptest->b[10][5]' accessed at index ptest->b[10][2], which is out of bounds. [arrayIndexOutOfBounds]\n" "[test.cpp:16:13]: (error) Array 'ptest->b[10][5]' accessed at index ptest->b[0][19], which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("struct TEST\n" "{\n" " char a[10][5];\n" "};\n" "void foo()\n" "{\n" " TEST test;\n" " test.a[9][5] = 4;\n" " test.a[0][50] = 4;\n" " TEST *ptest;\n" " ptest = &test;\n" " ptest->a[9][5] = 4;\n" " ptest->a[0][50] = 4;\n" "}\n"); ASSERT_EQUALS("[test.cpp:8:11]: (error) Array 'test.a[10][5]' accessed at index test.a[9][5], which is out of bounds. [arrayIndexOutOfBounds]\n" "[test.cpp:9:11]: (error) Array 'test.a[10][5]' accessed at index test.a[0][50], which is out of bounds. [arrayIndexOutOfBounds]\n" "[test.cpp:12:13]: (error) Array 'ptest->a[10][5]' accessed at index ptest->a[9][5], which is out of bounds. [arrayIndexOutOfBounds]\n" "[test.cpp:13:13]: (error) Array 'ptest->a[10][5]' accessed at index ptest->a[0][50], which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_35() { // ticket #2889 check("void f() {\n" " struct Struct { unsigned m_Var[1]; } s;\n" " s.m_Var[1] = 1;\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:12]: (error) Array 's.m_Var[1]' accessed at index 1, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("struct Struct { unsigned m_Var[1]; };\n" "void f() {\n" " struct Struct s;\n" " s.m_Var[1] = 1;\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:12]: (error) Array 's.m_Var[1]' accessed at index 1, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("struct Struct { unsigned m_Var[1]; };\n" "void f() {\n" " struct Struct * s = calloc(40);\n" " s->m_Var[1] = 1;\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void array_index_36() { // ticket #2960 check("class Fred {\n" " Fred(const Fred &);\n" "private:\n" " bool m_b[2];\n" "};\n" "Fred::Fred(const Fred & rhs) {\n" " m_b[2] = rhs.m_b[2];\n" "}\n"); ASSERT_EQUALS("[test.cpp:7:8]: (error) Array 'm_b[2]' accessed at index 2, which is out of bounds. [arrayIndexOutOfBounds]\n" "[test.cpp:7:21]: (error) Array 'rhs.m_b[2]' accessed at index 2, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_37() { check("class Fred {\n" " char x[X];\n" " Fred() {\n" " for (unsigned int i = 0; i < 15; i++)\n" " i;\n" " }\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void array_index_38() { //ticket #3273 check("void aFunction() {\n" " double aDoubleArray[ 10 ];\n" " unsigned int i; i = 0;\n" " for( i = 0; i < 6; i++ )\n" " {\n" " unsigned int j; j = 0;\n" " for( j = 0; j < 5; j++ )\n" " {\n" " unsigned int x; x = 0;\n" " for( x = 0; x < 4; x++ )\n" " {\n" " }\n" " }\n" " }\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void array_index_39() { // ticket 3387 check("void aFunction()\n" "{\n" " char a[10];\n" " a[10] = 0;\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:6]: (error) Array 'a[10]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_40() { check("void f() {\n" " char a[10];\n" " for (int i = 0; i < 10; ++i)\n" " f2(&a[i + 1]);\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void array_index_41() { // Don't generate false positives when structs have the same name check("void a() {\n" " struct Fred { char data[6]; } fred;\n" " fred.data[4] = 0;\n" // no error check("void f1(char *buf) {\n" " buf[4] = 0;\n" "}\n" "void f2() {\n" " int x[2];\n" " f1(x);\n" "}\n"); ASSERT_EQUALS("", errout_str()); // Same type => error check("void f1(const char buf[]) {\n" " char c = buf[4];\n" "}\n" "void f2() {\n" " char x[2];\n" " f1(x);\n" "}\n"); TODO_ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:2]: (error) Array 'x[2]' accessed at index 4, which is out of bounds.\n", "", errout_str()); } void array_index_string_literal() { check("void f() {\n" " const char *str = \"abc\";\n" " bar(str[10]);\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:12]: (error) Array 'str[4]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("void f()\n" "{\n" " const char *str = \"abc\";\n" " bar(str[4]);\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:12]: (error) Array 'str[4]' accessed at index 4, which is out of bounds. [arrayIndexOutOfBounds]\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:12]: (error) Array 'str[4]' accessed at index 4, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); check("void f() {\n" // #6973 " const char *name = \"\";\n" " if ( name[0] == 'U' ? name[1] : 0) {}\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("int main(int argc, char **argv) {\n" " char str[6] = \"\\0\";\n" " unsigned short port = 65535;\n" " snprintf(str, sizeof(str), \"%hu\", port);\n" "}\n", dinit(CheckOptions, $.cpp = false)); ASSERT_EQUALS("", errout_str()); check("int f(int x) {\n" // #11020 " const char* p = (x == 0 ? \"12345\" : \"ABC\");\n" " int s = 0;\n" " for (int i = 0; p[i]; i++)\n" " s += p[i];\n" " return s;\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void array_index_same_struct_and_var_name() { // don't throw internal error check("struct tt {\n" " char name[21];\n" "} ;\n" "void doswitch(struct tt *x)\n" "{\n" " struct tt *tt=x;\n" " tt->name;\n" "}\n"); ASSERT_EQUALS("", errout_str()); // detect error check("struct tt {\n" " char name[21];\n" "} ;\n" "void doswitch(struct tt *x)\n" "{\n" " struct tt *tt=x;\n" " tt->name[22] = 123;\n" "}\n"); ASSERT_EQUALS("[test.cpp:7:13]: (error) Array 'tt->name[21]' accessed at index 22, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void array_index_valueflow() { check("void f(int i) {\n" " char str[3];\n" " str[i] = 0;\n" " if (i==10) {}\n" "}\n"); ASSERT_EQUALS("[test.cpp:4:10] -> [test.cpp:3:8]: (warning) Either the condition 'i==10' is redundant or the array 'str[3]' is accessed at index 10, which is out of bounds. [arrayIndexOutOfBoundsCond]\n", errout_str()); check("void f(int i) {\n" " char str[3];\n" " str[i] = 0;\n" " switch (i) {\n" " case 10: break;\n" " }\n" "}\n"); ASSERT_EQUALS("[test.cpp:5:5] -> [test.cpp:3:8]: (warning) Either the switch case 'case 10' is redundant or the array 'str[3]' is accessed at index 10, which is out of bounds. [arrayIndexOutOfBoundsCond]\n", errout_str()); check("void f() {\n" " char str[3];\n" " str[((unsigned char)3) - 1] = 0;\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("void f() {\n" // #5416 FP " char *str[3];\n" " do_something(&str[0][5]);\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("class X { static const int x[100]; };\n" // #6070 "const int X::x[100] = {0};\n"); ASSERT_EQUALS("", errout_str()); check("namespace { class X { static const int x[100]; };\n" // #6232 "const int X::x[100] = {0}; }\n"); ASSERT_EQUALS("", errout_str()); check("class ActorSprite { static ImageSet * targetCursorImages[2][10]; };\n" "ImageSet *ActorSprite::targetCursorImages[2][10];\n"); ASSERT_EQUALS("", errout_str()); check("int f(const std::size_t s) {\n" // #10130 " const char a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };\n" " return (s > sizeof(a)) ? 11 : (int)a[s];\n" "}\n" "int g() {\n" " return f(16);\n" "}\n"); ASSERT_EQUALS("[test.cpp:3:15] -> [test.cpp:3:41]: (warning) Either the condition 's>sizeof(a)' is redundant or the array 'a[16]' is accessed at index 16, which is out of bounds. [arrayIndexOutOfBoundsCond]\n", errout_str()); check("void f(int fd) {\n" // #12318 " char buf[10];\n" " int size = 0;\n" " int pos = -1;\n" " do {\n" " pos++;\n" " size = read(fd, &buf[pos], 1);\n" " } while (size > 0);\n" " buf[pos] = '\\0';\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void array_index_valueflow_pointer() { check("void f() {\n" " int a[10];\n" " int *p = a;\n" " p[20] = 0;\n" "}\n"); TODO_ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Array 'a[10]' accessed at index 20, which is out of bounds.\n", "", errout_str()); { // address of check("void f() {\n" " int a[10];\n" " int *p = a;\n" " p[10] = 0;\n" "}\n"); TODO_ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4:6]: (error) Array 'a[10]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]\n", "", errout_str()); check("void f() {\n" " int a[10];\n" " int *p = a;\n" " dostuff(&p[10]);\n" "}\n"); ASSERT_EQUALS("", errout_str()); } check("void f() {\n" " int a[X];\n" // unknown size " int *p = a;\n" " p[20] = 0;\n" "}\n"); ASSERT_EQUALS("", errout_str()); check("void f() {\n" " int a[2];\n" " char *p = (char *)a;\n" // cast " p[4] = 0;\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void array_index_function_parameter() { check("void f(char a[10]) {\n" " a[20] = 0;\n" // m[9]' accessed at index 36, which is out of bounds. [arrayIndexOutOfBounds]\n", errout_str()); } void buffer_overrun_31() { check("void f(WhereInfo *pWInfo, int *aiCur) {\n" " memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2);\n" "}\n"); ASSERT_EQUALS("", errout_str()); } void buffer_overrun_32() { // destination size is too small check("void f(void) {\n" " const char src[3] = \"abc\";\n" " char dest[1] = \"a\";\n" " (void)strxfrm(dest,src,1);\n" " (void)strxfrm(dest,src,2);\n"//

Back | FazBrowse Home | New Git URL