diff --git a/CheckBufferOverrun.cpp b/CheckBufferOverrun.cpp index f9fd79fd6..20da1ff28 100644 --- a/CheckBufferOverrun.cpp +++ b/CheckBufferOverrun.cpp @@ -156,7 +156,7 @@ static void _DynamicData() // Buffer overrun.. //--------------------------------------------------------------------------- -void CheckBufferOverrun() +static void CheckBufferOverrun_LocalVariable() { _DynamicData(); @@ -323,6 +323,76 @@ void CheckBufferOverrun() } //--------------------------------------------------------------------------- +static void CheckBufferOverrun_StructVariable() +{ + const char *declstruct_pattern[] = {"struct","","{",0}; + for ( TOKEN * tok = findtoken( tokens, declstruct_pattern ); + tok; + tok = findtoken( tok->next, declstruct_pattern ) ) + { + const char *structname = tok->next->str; + + if ( ! IsName( structname ) ) + continue; + + // Found a struct declaration. Search for arrays.. + for ( TOKEN * tok2 = tok->next->next; tok2; tok2 = tok2->next ) + { + if ( tok2->str[0] == '}' ) + break; + if ( strchr( ";{", tok2->str[0] ) ) + { + const char *arrname = 0; + const char *arrsize = 0; + + // Declare array.. + if ( match(tok2->next, "var var [ num ] ;") ) + { + arrname = getstr(tok2, 2); + arrsize = getstr(tok2, 4); + } + + if ( ! arrname ) + continue; + + for ( TOKEN *tok3 = tokens; tok3; tok3 = tok3->next ) + { + if ( strcmp(tok3->str, structname) ) + continue; + if ( ! match( tok3->next, "var ;" ) ) + continue; + const char *varname = tok3->next->str; + + const char *badpattern[] = {"varname",".","arrname","[","","]",NULL}; + badpattern[0] = varname; + badpattern[2] = arrname; + TOKEN *tok4 = findtoken( tok3, badpattern ); + while (tok4) + { + if ( IsNumber( getstr(tok4, 4) ) ) + { + if ( atoi( getstr(tok4,4) ) >= atoi(arrsize) ) + { + std::ostringstream errmsg; + errmsg << FileLine(tok4) << ": Buffer overrun"; + ReportErr(errmsg.str()); + } + } + tok4 = findtoken( tok4->next, badpattern ); + } + } + } + } + } +} +//--------------------------------------------------------------------------- + +void CheckBufferOverrun() +{ + CheckBufferOverrun_LocalVariable(); + CheckBufferOverrun_StructVariable(); +} +//--------------------------------------------------------------------------- diff --git a/tests.cpp b/tests.cpp index 620a009c2..67c413d69 100644 --- a/tests.cpp +++ b/tests.cpp @@ -289,6 +289,7 @@ static void buffer_overrun() // test5: constant array index // test6: calculated array index that is out of bounds // test7: unknown string length + // test8: struct member.. const char test1[] = "void f()\n" "{\n" @@ -380,9 +381,23 @@ static void buffer_overrun() check( CheckBufferOverrun, __LINE__, test7, err7 ); + const char test8[] = "struct ABC\n" + "{\n" + " char str[10];\n" + "};\n" + "\n" + "static void f()\n" + "{\n" + " struct ABC abc;\n" + " abc.str[10] = 0;\n" + "}\n"; + check( CheckBufferOverrun, __LINE__, test8, "[test.cpp:9]: Buffer overrun\n" ); + + + // TODO /* - const char test8[] = "class Fred\n" + const char test[] = "class Fred\n" "{\n" "private:\n" " char str[10];\n" @@ -393,8 +408,9 @@ static void buffer_overrun() "{\n" " str[10] = 0;\n" "}\n"; - check( CheckBufferOverrun, __LINE__, test8, "[test.cpp:5]: Array index out of bounds\n" ); + check( CheckBufferOverrun, __LINE__, test, "[test.cpp:5]: Array index out of bounds\n" ); */ + } //---------------------------------------------------------------------------