⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 checkbufferoverrun.cpp

📁 cppcheck is a static C/C++ code analyzer that checks for memory leaks, mismatching allocation-deallo
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2009 Daniel Marjamäki, Reijo Tomperi, Nicolas Le Cam, * Leandro Penz, Kimmo Varis, Vesa Pikki * * 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 <http://www.gnu.org/licenses/ *///---------------------------------------------------------------------------// Buffer overrun..//---------------------------------------------------------------------------#include "checkbufferoverrun.h"#include "tokenize.h"#include "errorlogger.h"#include <algorithm>#include <sstream>#include <list>#include <cstring>#include <cstdlib>     // <- strtoul//---------------------------------------------------------------------------// _callStack used when parsing into subfunctions.CheckBufferOverrunClass::CheckBufferOverrunClass(const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger)        :  _settings(settings){    _tokenizer = tokenizer;    _errorLogger = errorLogger;}CheckBufferOverrunClass::~CheckBufferOverrunClass(){}void CheckBufferOverrunClass::arrayIndexOutOfBounds(const Token *tok){    _callStack.push_back(tok);    _errorLogger->arrayIndexOutOfBounds(_tokenizer, _callStack);    _callStack.pop_back();}//---------------------------------------------------------------------------//---------------------------------------------------------------------------// Check array usage..//---------------------------------------------------------------------------void CheckBufferOverrunClass::CheckBufferOverrun_CheckScope(const Token *tok, const char *varname[], const int size, const int total_size, unsigned int varid){    unsigned int varc = 0;    std::string varnames;    while (varname[varc])    {        if (varc > 0)            varnames += " . ";        varnames += varname[varc];        ++varc;    }    if (varc == 0)        varc = 1;    varc = 2 * (varc - 1);    // Array index..    if (varid > 0)    {        if (Token::Match(tok, "%varid% [ %num% ]", varid))        {            const char *num = tok->strAt(2);            if (std::strtol(num, NULL, 10) >= size)            {                arrayIndexOutOfBounds(tok->next());            }        }    }    else if (Token::Match(tok, std::string(varnames + " [ %num% ]").c_str()))    {        const char *num = tok->strAt(2 + varc);        if (std::strtol(num, NULL, 10) >= size)        {            arrayIndexOutOfBounds(tok->next());        }    }    int indentlevel = 0;    for (; tok; tok = tok->next())    {        if (tok->str() == "{")        {            ++indentlevel;        }        else if (tok->str() == "}")        {            --indentlevel;            if (indentlevel < 0)                return;        }        // Array index..        if (varid > 0)        {            if (!tok->isName() && !Token::Match(tok, "[.&]") && Token::Match(tok->next(), "%varid% [ %num% ]", varid))            {                const char *num = tok->strAt(3);                if (std::strtol(num, NULL, 10) >= size)                {                    arrayIndexOutOfBounds(tok->next());                }            }        }        else if (!tok->isName() && !Token::Match(tok, "[.&]") && Token::Match(tok->next(), std::string(varnames + " [ %num% ]").c_str()))        {            const char *num = tok->next()->strAt(2 + varc);            if (std::strtol(num, NULL, 10) >= size)            {                arrayIndexOutOfBounds(tok->next());            }            tok = tok->tokAt(4);            continue;        }        // memset, memcmp, memcpy, strncpy, fgets..        if (varid > 0)        {            if (Token::Match(tok, "memset|memcpy|memmove|memcmp|strncpy|fgets"))            {                if (Token::Match(tok->next(), "( %varid% , %num% , %num% )", varid) ||                    Token::Match(tok->next(), "( %var% , %varid% , %num% )", varid))                {                    const char *num  = tok->strAt(6);                    if (std::atoi(num) > total_size)                    {                        _errorLogger->bufferOverrun(_tokenizer, tok);                    }                }            }        }        else if (Token::Match(tok, "memset|memcpy|memmove|memcmp|strncpy|fgets"))        {            if (Token::Match(tok->next(), std::string("( " + varnames + " , %num% , %num% )").c_str()) ||                Token::Match(tok->next(), std::string("( %var% , " + varnames + " , %num% )").c_str()))            {                const char *num  = tok->strAt(varc + 6);                if (std::atoi(num) > total_size)                {                    _errorLogger->bufferOverrun(_tokenizer, tok);                }            }            continue;        }        // Loop..        if (Token::simpleMatch(tok, "for ("))        {            const Token *tok2 = tok->tokAt(2);            // for - setup..            if (Token::Match(tok2, "%var% = 0 ;"))                tok2 = tok2->tokAt(4);            else if (Token::Match(tok2, "%type% %var% = 0 ;"))                tok2 = tok2->tokAt(5);            else if (Token::Match(tok2, "%type% %type% %var% = 0 ;"))                tok2 = tok2->tokAt(6);            else                continue;            // for - condition..            if (!Token::Match(tok2, "%var% < %num% ;") && !Token::Match(tok2, "%var% <= %num% ;"))                continue;            // Get index variable and stopsize.            const char *strindex = tok2->aaaa();            int value = ((tok2->next()->aaaa1() == '=') ? 1 : 0) + std::atoi(tok2->strAt(2));            if (value <= size)                continue;            // Goto the end of the for loop..            while (tok2 && tok2->str() != ")")                tok2 = tok2->next();            if (!tok2 || !tok2->tokAt(5))                break;            std::ostringstream pattern;            pattern << varnames << " [ " << strindex << " ]";            int indentlevel2 = 0;            while ((tok2 = tok2->next()))            {                if (tok2->str() == ";" && indentlevel2 == 0)                    break;                if (tok2->str() == "{")                    ++indentlevel2;                if (tok2->str() == "}")                {                    --indentlevel2;                    if (indentlevel2 <= 0)                        break;                }                if (Token::Match(tok2, pattern.str().c_str()))                {                    _errorLogger->bufferOverrun(_tokenizer, tok2);                    break;                }            }            continue;        }        // Writing data into array..        if (Token::Match(tok, ("strcpy|strcat ( " + varnames + " , %str% )").c_str()))        {            int len = 0;            const char *str = tok->strAt(varc + 4);            while (*str)            {                if (*str == '\\')                    ++str;                ++str;                ++len;            }            if (len > 2 && len >= (int)size + 2)            {                _errorLogger->bufferOverrun(_tokenizer, tok);            }            continue;        }        // Dangerous usage of strncat..        if (varid > 0 && Token::Match(tok, "strncat ( %varid% , %any% , %num% )", varid))        {            int n = atoi(tok->strAt(6));            if (n == size)                _errorLogger->strncatUsage(_tokenizer, tok);        }        // Dangerous usage of strncpy + strncat..        if (varid > 0 && Token::Match(tok, "strncpy|strncat ( %varid% , %any% , %num% ) ; strncat ( %varid% , %any% , %num% )", varid))        {            int n = atoi(tok->strAt(6)) + atoi(tok->strAt(15));            if (n > size)                _errorLogger->strncatUsage(_tokenizer, tok->tokAt(9));        }        // sprintf..        if (varid > 0 && Token::Match(tok, "sprintf ( %varid% , %str% ,", varid))        {            int len = 0;            for (const Token *tok2 = tok->tokAt(6); tok2 && tok2->str() != ")"; tok2 = tok2->next())            {                if (tok2->aaaa0() == '\"')                {                    len -= 2;                    const char *str = tok->strAt(0);                    while (*str)                    {                        if (*str == '\\')                            ++str;                        ++str;                        ++len;                    }                }            }            if (len > (int)size)            {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -