diff --git a/CheckBufferOverrun.cpp b/CheckBufferOverrun.cpp index 9d479dff0..79c4f1787 100644 --- a/CheckBufferOverrun.cpp +++ b/CheckBufferOverrun.cpp @@ -16,9 +16,11 @@ static const TOKEN *findfunction(const TOKEN *tok) int indentlevel = 0, parlevel = 0; for (; tok; tok = tok->next) { - setindentlevel( tok, indentlevel, -1 ); - - if (tok->str[0] == '(') + if (tok->str[0] == '{') + indentlevel++; + else if (tok->str[0] == '}') + indentlevel--; + else if (tok->str[0] == '(') parlevel++; else if (tok->str[0] == ')') parlevel--; @@ -26,7 +28,7 @@ static const TOKEN *findfunction(const TOKEN *tok) if (!tok->next) break; - if (indentlevel==0 && parlevel==0 && match(tok,"var (")) + if (indentlevel==0 && parlevel==0 && IsName(tok->str) && tok->next->str[0]=='(') { for (const TOKEN *tok2 = tok->next; tok2; tok2 = tok2->next) { @@ -111,9 +113,13 @@ static void CheckBufferOverrun_DynamicData() int indentlevel = 0; for (const TOKEN *tok = ftok; tok; tok = tok->next) { - if (setindentlevel(tok, indentlevel, 0)) + if (tok->str[0] == '{') + indentlevel++; + else if (tok->str[0] == '}') { - break; + indentlevel--; + if (indentlevel <= 0) + break; } @@ -154,143 +160,160 @@ static void CheckBufferOverrun_LocalVariable() int indentlevel = 0; for (const TOKEN *tok = tokens; tok; tok = tok->next) { - if (setindentlevel( tok, indentlevel, -1 )) - break; + if (tok->str[0]=='{') + indentlevel++; - // Declaring array.. - if ( ! match(tok, "type var [ num ] ;") ) - continue; + else if (tok->str[0]=='}') + indentlevel--; - const char *varname = getstr(tok,1); - unsigned int size = strtoul(getstr(tok,3), NULL, 10); - int total_size = size * SizeOfType(tok->str); - if (total_size == 0) - continue; - - int _indentlevel = 0; - for (const TOKEN *tok2 = gettok(tok,5); tok2; tok2 = tok2->next) + else if (indentlevel > 0) { - if ( setindentlevel(tok2, _indentlevel, -1) ) - break; - - // Array index.. - if ( strcmp(tok2->str,varname)==0 && match( tok2->next, "[ num ]") ) + // Declaring array.. + if (match(tok, "type var [ num ] ;")) { - const char *str = getstr(tok2, 2); - if (strtoul(str, NULL, 10) >= size) + const char *varname = getstr(tok,1); + unsigned int size = strtoul(getstr(tok,3), NULL, 10); + int total_size = size * SizeOfType(tok->str); + if (total_size == 0) + continue; + int _indentlevel = indentlevel; + for (const TOKEN *tok2 = gettok(tok,5); tok2; tok2 = tok2->next) { - std::ostringstream ostr; - ostr << FileLine(tok2) << ": Array index out of bounds"; - ReportErr(ostr.str()); - } - } - - - // memset, memcmp, memcpy, strncpy, fgets.. - if (strcmp(tok2->str,"memset")==0 || - strcmp(tok2->str,"memcpy")==0 || - strcmp(tok2->str,"memmove")==0 || - strcmp(tok2->str,"memcmp")==0 || - strcmp(tok2->str,"strncpy")==0 || - strcmp(tok2->str,"fgets")==0 ) - { - if (match(tok2->next,"( var , num , num )") || - match(tok2->next,"( var , var , num )") ) - { - const char *var1 = getstr(tok2, 2); - const char *var2 = getstr(tok2, 4); - const char *num = getstr(tok2, 6); - - if ( atoi(num)>total_size && - (strcmp(var1,varname)==0 || - strcmp(var2,varname)==0 ) ) + if (tok2->str[0]=='{') { - std::ostringstream ostr; - ostr << FileLine(tok2) << ": Buffer overrun"; - ReportErr(ostr.str()); + _indentlevel++; } - } - } - - - // Loop.. - if ( match(tok2, "for ( var = 0 ;") ) - { - const char *strindex = 0; - int value = 0; - - if (match(tok2,"for ( var = 0 ; var < num ; var + + )")) - { - strindex = getstr(tok2,2); - value = atoi(getstr(tok2,8)); - } - else if (match(tok2,"for ( var = 0 ; var <= num ; var + + )")) - { - strindex = getstr(tok2,2); - value = 1 + atoi(getstr(tok2,8)); - } - else if (match(tok2,"for ( var = 0 ; var < num ; + + var )")) - { - strindex = getstr(tok2,2); - value = atoi(getstr(tok2,8)); - } - else if (match(tok2,"for ( var = 0 ; var <= num ; + + var )")) - { - strindex = getstr(tok2,2); - value = 1 + atoi(getstr(tok2,8)); - } - - if (strindex && value>(int)size) - { - const TOKEN *tok3 = tok2; - while (tok3 && strcmp(tok3->str,")")) - tok3 = tok3->next; - if (!tok3) - break; - tok3 = tok3->next; - if (tok3->str[0] == '{') - tok3 = tok3->next; - while (tok3 && !strchr(";}",tok3->str[0])) + else if (tok2->str[0]=='}') { - if ( match(tok3, "var [ var ]" && - strcmp(tok3->str,varname)==0 && - strcmp(getstr(tok3,2),strindex)==0 ) - { - std::ostringstream ostr; - ostr << FileLine(tok3) << ": Buffer overrun"; - ReportErr(ostr.str()); + _indentlevel--; + if (_indentlevel < indentlevel) break; - } - tok3 = tok3->next; } - } - } - - - // Writing data into array.. - if (match(tok2,"strcpy ( var , ")) - { - int len = 0; - if (strcmp(getstr(tok2, 2), varname) == 0) - { - const char *str = getstr(tok2, 4); - if (str[0] == '\"') + else { - while (*str) + // Array index.. + if (strcmp(tok2->str,varname)==0 && + strcmp(getstr(tok2,1),"[")==0 && + IsNumber(getstr(tok2,2)) && + strcmp(getstr(tok2,3),"]")==0 ) { - if (*str=='\\') - str++; - str++; - len++; + const char *str = getstr(tok2, 2); + if (strtoul(str, NULL, 10) >= size) + { + std::ostringstream ostr; + ostr << FileLine(tok2) << ": Array index out of bounds"; + ReportErr(ostr.str()); + } + } + + + // memset, memcmp, memcpy, strncpy, fgets.. + if (strcmp(tok2->str,"memset")==0 || + strcmp(tok2->str,"memcpy")==0 || + strcmp(tok2->str,"memmove")==0 || + strcmp(tok2->str,"memcmp")==0 || + strcmp(tok2->str,"strncpy")==0 || + strcmp(tok2->str,"fgets")==0 ) + { + if (match(tok2->next,"( var , num , num )") || + match(tok2->next,"( var , var , num )") ) + { + const char *var1 = getstr(tok2, 2); + const char *var2 = getstr(tok2, 4); + const char *num = getstr(tok2, 6); + + if ( atoi(num)>total_size && + (strcmp(var1,varname)==0 || + strcmp(var2,varname)==0 ) ) + { + std::ostringstream ostr; + ostr << FileLine(tok2) << ": Buffer overrun"; + ReportErr(ostr.str()); + } + } + } + + + // Loop.. + const char *strindex = 0; + int value = 0; + if ( match(tok2, "for ( var = 0 ;") ) + { + if (match(tok2,"for ( var = 0 ; var < num ; var + + )")) + { + strindex = getstr(tok2,2); + value = atoi(getstr(tok2,8)); + } + else if (match(tok2,"for ( var = 0 ; var <= num ; var + + )")) + { + strindex = getstr(tok2,2); + value = 1 + atoi(getstr(tok2,8)); + } + else if (match(tok2,"for ( var = 0 ; var < num ; + + var )")) + { + strindex = getstr(tok2,2); + value = atoi(getstr(tok2,8)); + } + else if (match(tok2,"for ( var = 0 ; var <= num ; + + var )")) + { + strindex = getstr(tok2,2); + value = 1 + atoi(getstr(tok2,8)); + } + } + if (strindex && value>(int)size) + { + const TOKEN *tok3 = tok2; + while (tok3 && strcmp(tok3->str,")")) + tok3 = tok3->next; + if (!tok3) + break; + tok3 = tok3->next; + if (tok3->str[0] == '{') + tok3 = tok3->next; + while (tok3 && !strchr(";}",tok3->str[0])) + { + if (strcmp(tok3->str,varname)==0 && + strcmp(getstr(tok3,1),"[")==0 && + strcmp(getstr(tok3,2),strindex)==0 && + strcmp(getstr(tok3,3),"]")==0 ) + { + std::ostringstream ostr; + ostr << FileLine(tok3) << ": Buffer overrun"; + ReportErr(ostr.str()); + break; + } + tok3 = tok3->next; + } + } + + + // Writing data into array.. + if (match(tok2,"strcpy ( var , ")) + { + int len = 0; + if (strcmp(getstr(tok2, 2), varname) == 0) + { + const char *str = getstr(tok2, 4); + if (str[0] == '\"') + { + while (*str) + { + if (*str=='\\') + str++; + str++; + len++; + } + } + } + if (len > 2 && len >= (int)size + 2) + { + std::ostringstream ostr; + ostr << FileLine(tok2) << ": Buffer overrun"; + ReportErr(ostr.str()); + } } } } - if (len > 2 && len >= (int)size + 2) - { - std::ostringstream ostr; - ostr << FileLine(tok2) << ": Buffer overrun"; - ReportErr(ostr.str()); - } } } } diff --git a/CheckHeaders.cpp b/CheckHeaders.cpp index a93b10195..8ad03ce1e 100644 --- a/CheckHeaders.cpp +++ b/CheckHeaders.cpp @@ -91,7 +91,12 @@ void WarningIncludeHeader() continue; // I'm only interested in stuff that is declared at indentlevel 0 - setindentlevel( tok1, indentlevel, -1 ); + if (tok1->str[0] == '{') + indentlevel++; + + else if (tok1->str[0] == '}') + indentlevel--; + if (indentlevel != 0) continue; diff --git a/CheckOther.cpp b/CheckOther.cpp index 720737312..198a5b836 100644 --- a/CheckOther.cpp +++ b/CheckOther.cpp @@ -16,7 +16,7 @@ void WarningOldStylePointerCast() { - for (const TOKEN *tok = FindMatchingToken(tokens); tok; tok = tok->next) + for (const TOKEN *tok = tokens; tok; tok = tok->next) { // Old style pointer casting.. if (!match(tok, "( type * ) var")) @@ -194,8 +194,15 @@ void WarningIf() } // Search for 'a=b; if (a==b)' - for (const TOKEN *tok = tokens; tok; GotoNextStatement(&tok)) + for (const TOKEN *tok = tokens; tok; tok = tok->next) { + // Begin statement? + if ( ! strchr(";{}", tok->str[0]) ) + continue; + tok = tok->next; + if ( ! tok ) + break; + if (!match(tok,"var = var ; if ( var")) continue; @@ -298,10 +305,17 @@ static const TOKEN *GetFunction( const TOKEN *content ) int indentlevel = 0; for (const TOKEN *tok = tokens; tok; tok = tok->next) { - if (setindentlevel(tok, indentlevel, 0)) - func = NULL; + if ( tok->str[0] == '{' ) + indentlevel++; - if (indentlevel == 0) + else if ( tok->str[0] == '}' ) + { + indentlevel--; + if (indentlevel == 0) + func = NULL; + } + + else if (indentlevel == 0) { if (tok->str[0] == ';') func = NULL; @@ -352,27 +366,34 @@ void WarningStrTok() int indentlevel = 0; for ( const TOKEN *tok = *it1; tok; tok = tok->next ) { - if (setindentlevel(tok, indentlevel, 0)) - break; + if ( tok->str[0] == '{' ) + indentlevel++; - if ( indentlevel == 0 ) - continue; - - // Only interested in function calls.. - if (! match(tok, "var (")) - continue; - - // Check if function name is in funclist.. - std::list::const_iterator it2; - for (it2 = funclist.begin(); it2 != funclist.end(); it2++) + else if ( tok->str[0] == '}' ) { - if ( strcmp( tok->str, (*it2)->str ) ) + if ( indentlevel <= 1 ) + break; + indentlevel--; + } + + else if ( indentlevel >= 1 ) + { + // Only interested in function calls.. + if (!(IsName(tok->str) && strcmp(getstr(tok,1), "(") == 0)) continue; - std::ostringstream ostr; - ostr << FileLine(tok) << ": Possible bug. Both '" << (*it1)->str << "' and '" << (*it2)->str << "' uses strtok."; - ReportErr(ostr.str()); - break; + // Check if function name is in funclist.. + std::list::const_iterator it2; + for (it2 = funclist.begin(); it2 != funclist.end(); it2++) + { + if ( strcmp( tok->str, (*it2)->str ) ) + continue; + + std::ostringstream ostr; + ostr << FileLine(tok) << ": Possible bug. Both '" << (*it1)->str << "' and '" << (*it2)->str << "' uses strtok."; + ReportErr(ostr.str()); + break; + } } } } @@ -415,13 +436,18 @@ void CheckCaseWithoutBreak() int indentlevel = 0; for (const TOKEN *tok2 = tok->next; tok2; tok2 = tok2->next) { - if ( setindentlevel( tok2, indentlevel, -1 ) ) + if (tok2->str[0] == '{') + indentlevel++; + else if (tok2->str[0] == '}') { - std::ostringstream ostr; - ostr << FileLine(tok) << ": 'case' without 'break'."; - ReportErr(ostr.str()); + indentlevel--; + if (indentlevel < 0) + { + std::ostringstream ostr; + ostr << FileLine(tok) << ": 'case' without 'break'."; + ReportErr(ostr.str()); + } } - if (indentlevel==0) { if (strcmp(tok2->str,"break")==0) @@ -438,6 +464,7 @@ void CheckCaseWithoutBreak() } } } + } //--------------------------------------------------------------------------- @@ -534,10 +561,18 @@ void CheckVariableScope() tok = tok2; for (tok = tok2; tok; tok = tok->next) { - if ( setindentlevel( tok, _indentlevel, 0 ) ) + if ( tok->str[0] == '{' ) { - tok = tok->next; - break; + _indentlevel++; + } + if ( tok->str[0] == '}' ) + { + _indentlevel--; + if ( _indentlevel <= 0 ) + { + tok = tok->next; + break; + } } } break; @@ -551,11 +586,16 @@ void CheckVariableScope() break; } - if ( setindentlevel( tok, indentlevel, 0 ) ) + if ( tok->str[0] == '{' ) { - func = false; + indentlevel++; + } + if ( tok->str[0] == '}' ) + { + indentlevel--; + if ( indentlevel == 0 ) + func = false; } - if ( indentlevel == 0 && match(tok, ") {") ) { func = true; @@ -592,18 +632,25 @@ static void CheckVariableScope_LookupVar( const TOKEN *tok1, const char varname[ // Check if the variable is used in this indentlevel.. bool used = false, used1 = false; - bool for_or_while = false; int indentlevel = 0; - for (; tok; tok = tok->next ) + bool for_or_while = false; + while ( indentlevel >= 0 && tok ) { - if ( setindentlevel( tok, indentlevel, 0 ) ) + if ( tok->str[0] == '{' ) { - if ( for_or_while && used ) - return; - used1 = used; - used = false; - if ( indentlevel < 0 ) - break; + indentlevel++; + } + + else if ( tok->str[0] == '}' ) + { + indentlevel--; + if ( indentlevel == 0 ) + { + if ( for_or_while && used ) + return; + used1 = used; + used = false; + } } else if ( strcmp(tok->str, varname) == 0 ) @@ -620,6 +667,8 @@ static void CheckVariableScope_LookupVar( const TOKEN *tok1, const char varname[ if ( tok->str[0] == ';' ) for_or_while = false; } + + tok = tok->next; } // Warning if "used" is true diff --git a/CommonCheck.cpp b/CommonCheck.cpp index e321822f9..f469f6804 100644 --- a/CommonCheck.cpp +++ b/CommonCheck.cpp @@ -58,43 +58,3 @@ bool IsStandardType(const char str[]) } //--------------------------------------------------------------------------- -bool setindentlevel( const TOKEN *tok, int &indentlevel, int endlevel ) -{ - if ( tok->str[0] == '{' ) - indentlevel++; - - else if ( tok->str[0] == '}' ) - indentlevel--; - - return bool(tok->str[0]=='}' && indentlevel<=endlevel); -} -//--------------------------------------------------------------------------- - -void GotoNextStatement( const TOKEN **tok ) -{ - // Goto end of statement.. - while ( *tok && ! strchr("{};", (*tok)->str[0]) ) - *tok = (*tok)->next; - - // Goto next statement - if ( *tok ) - *tok = (*tok)->next; -} -//--------------------------------------------------------------------------- - -void FindMatchingTokenInScope( const TOKEN **tok, const char pattern[], int &indentlevel ) -{ - while ( *tok ) - { - if ( setindentlevel( *tok, indentlevel, -1 ) ) - *tok = NULL; - - else if ( match( *tok, pattern ) ) - return; - - else - *tok = (*tok)->next; - } -} -//--------------------------------------------------------------------------- - diff --git a/CommonCheck.h b/CommonCheck.h index 2cbebf577..80fb2c2a5 100644 --- a/CommonCheck.h +++ b/CommonCheck.h @@ -6,38 +6,20 @@ #include #include -//--------------------------------------------------------------------------- -// Report errors.. -//--------------------------------------------------------------------------- - struct TOKEN; std::string FileLine(const TOKEN *tok); - + extern bool OnlyReportUniqueErrors; void ReportErr(const std::string &errmsg); extern std::ostringstream errout; -//--------------------------------------------------------------------------- -// Classify tokens.. -//--------------------------------------------------------------------------- - bool IsName(const char str[]); bool IsNumber(const char str[]); bool IsStandardType(const char str[]); - -//--------------------------------------------------------------------------- -// Iterating through tokens.. -//--------------------------------------------------------------------------- - -bool setindentlevel( const TOKEN *tok, int &indentlevel, int endlevel ); -void GotoNextStatement( const TOKEN **tok ); -void FindMatchingTokenInScope( const TOKEN **tok, const char pattern[], int &indentlevel ); - - //--------------------------------------------------------------------------- #endif diff --git a/tests.cpp b/tests.cpp index dcfee85e8..801efc313 100644 --- a/tests.cpp +++ b/tests.cpp @@ -494,16 +494,6 @@ static void constructors() "}\n"; check( CheckConstructors, __LINE__, test4, "[test.cpp:8] Uninitialized member variable 'Fred::i'\n" ); - - - const char test5[] = "class Fred\n" - "{\n" - "public:\n" - " unsigned int i;\n" - "};\n"; - check( CheckConstructors, __LINE__, test5, "[test.cpp:1] The class 'Fred' has no constructor\n" ); - - } //---------------------------------------------------------------------------