📄 checkbufferoverrun.cpp
字号:
_errorLogger->bufferOverrun(_tokenizer, tok); } } // snprintf.. if (varid > 0 && Token::Match(tok, "snprintf ( %varid% , %num%", varid)) { int n = std::atoi(tok->strAt(4)); if (n > size) _errorLogger->outOfBounds(_tokenizer, tok->tokAt(4), "snprintf size"); } // cin.. if (varid > 0 && Token::Match(tok, "cin >> %varid% ;", varid)) { _errorLogger->bufferOverrun(_tokenizer, tok); } // Function call.. // It's not interesting to check what happens when the whole struct is // sent as the parameter, that is checked separately anyway. if (Token::Match(tok, "%var% (")) { // Don't make recursive checking.. if (std::find(_callStack.begin(), _callStack.end(), tok) != _callStack.end()) continue; // Only perform this checking if showAll setting is enabled.. if (!_settings._showAll) continue; unsigned int parlevel = 0, par = 0; for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { if (tok2->str() == "(") { ++parlevel; } else if (tok2->str() == ")") { --parlevel; if (parlevel < 1) { par = 0; break; } } else if (parlevel == 1 && (tok2->str() == ",")) { ++par; } if (parlevel == 1 && Token::Match(tok2, std::string("[(,] " + varnames + " [,)]").c_str())) { ++par; break; } } if (par == 0) continue; // Find function.. const Token *ftok = _tokenizer->GetFunctionTokenByName(tok->aaaa()); if (!ftok) continue; // Parse head of function.. ftok = ftok->tokAt(2); parlevel = 1; while (ftok && parlevel == 1 && par >= 1) { if (ftok->str() == "(") ++parlevel; else if (ftok->str() == ")") --parlevel; else if (ftok->str() == ",") --par; else if (par == 1 && parlevel == 1 && Token::Match(ftok, "%var% [,)]")) { // Parameter name.. const char *parname[2]; parname[0] = ftok->aaaa(); parname[1] = 0; // Goto function body.. while (ftok && (ftok->str() != "{")) ftok = ftok->next(); ftok = ftok ? ftok->next() : 0; // Check variable usage in the function.. _callStack.push_back(tok); CheckBufferOverrun_CheckScope(ftok, parname, size, total_size, 0); _callStack.pop_back(); // break out.. break; } ftok = ftok->next(); } } }}//---------------------------------------------------------------------------// Checking local variables in a scope//---------------------------------------------------------------------------void CheckBufferOverrunClass::CheckBufferOverrun_GlobalAndLocalVariable(){ int indentlevel = 0; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (tok->str() == "{") ++indentlevel; else if (tok->str() == "}") --indentlevel; const char *varname[2] = {0}; unsigned int size = 0; const char *type = 0; unsigned int varid = 0; int nextTok = 0; if (Token::Match(tok, "%type% %var% [ %num% ] [;=]")) { varname[0] = tok->strAt(1); size = std::strtoul(tok->strAt(3), NULL, 10); type = tok->aaaa(); varid = tok->tokAt(1)->varId(); nextTok = 6; } else if (indentlevel > 0 && Token::Match(tok, "[*;{}] %var% = new %type% [ %num% ]")) { varname[0] = tok->strAt(1); size = std::strtoul(tok->strAt(6), NULL, 10); type = tok->strAt(4); varid = tok->tokAt(1)->varId(); nextTok = 8; } else { continue; } int total_size = size * _tokenizer->SizeOfType(type); if (total_size == 0) continue; // The callstack is empty _callStack.clear(); CheckBufferOverrun_CheckScope(tok->tokAt(nextTok), varname, size, total_size, varid); }}//---------------------------------------------------------------------------//---------------------------------------------------------------------------// Checking member variables of structs..//---------------------------------------------------------------------------void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable(){ const char declstruct[] = "struct|class %var% {"; for (const Token *tok = Token::findmatch(_tokenizer->tokens(), declstruct); tok; tok = Token::findmatch(tok->next(), declstruct)) { const std::string &structname = tok->next()->str(); // Found a struct declaration. Search for arrays.. for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { if (tok2->str() == "}") break; int ivar = 0; if (Token::Match(tok2->next(), "%type% %var% [ %num% ] ;")) ivar = 2; else if (Token::Match(tok2->next(), "%type% %type% %var% [ %num% ] ;")) ivar = 3; else if (Token::Match(tok2->next(), "%type% * %var% [ %num% ] ;")) ivar = 3; else if (Token::Match(tok2->next(), "%type% %type% * %var% [ %num% ] ;")) ivar = 4; else continue; const char *varname[3] = {0, 0, 0}; varname[1] = tok2->strAt(ivar); int arrsize = std::atoi(tok2->strAt(ivar + 2)); int total_size = arrsize * _tokenizer->SizeOfType(tok2->next()->aaaa()); if (total_size == 0) continue; // Class member variable => Check functions if (tok->str() == "class") { std::string func_pattern(structname + " :: %var% ("); const Token *tok3 = Token::findmatch(_tokenizer->tokens(), func_pattern.c_str()); while (tok3) { for (const Token *tok4 = tok3; tok4; tok4 = tok4->next()) { if (Token::Match(tok4, "[;{}]")) break; if (Token::simpleMatch(tok4, ") {")) { const char *names[2] = {varname[1], 0}; CheckBufferOverrun_CheckScope(tok4->tokAt(2), names, arrsize, total_size, 0); break; } } tok3 = Token::findmatch(tok3->next(), func_pattern.c_str()); } } for (const Token *tok3 = _tokenizer->tokens(); tok3; tok3 = tok3->next()) { if (tok3->str() != structname) continue; // Declare variable: Fred fred1; if (Token::Match(tok3->next(), "%var% ;")) varname[0] = tok3->strAt(1); // Declare pointer: Fred *fred1 else if (Token::Match(tok3->next(), "* %var% [,);=]")) varname[0] = tok3->strAt(2); else continue; // Goto end of statement. const Token *CheckTok = NULL; while (tok3) { // End of statement. if (tok3->str() == ";") { CheckTok = tok3; break; } // End of function declaration.. if (Token::simpleMatch(tok3, ") ;")) break; // Function implementation.. if (Token::simpleMatch(tok3, ") {")) { CheckTok = tok3->tokAt(2); break; } tok3 = tok3->next(); } if (!tok3) break; if (!CheckTok) continue; // Check variable usage.. CheckBufferOverrun_CheckScope(CheckTok, varname, arrsize, total_size, 0); } } }}//---------------------------------------------------------------------------void CheckBufferOverrunClass::bufferOverrun(){ CheckBufferOverrun_GlobalAndLocalVariable(); CheckBufferOverrun_StructVariable();}//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -