1 /* 2 * Cppcheck - A tool for static C/C++ code analysis 3 * Copyright (C) 2007-2021 Cppcheck team. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 20 //--------------------------------------------------------------------------- 21 #ifndef checkbufferoverrunH 22 #define checkbufferoverrunH 23 //--------------------------------------------------------------------------- 24 25 #include "check.h" 26 #include "config.h" 27 #include "ctu.h" 28 #include "errortypes.h" 29 #include "mathlib.h" 30 #include "symboldatabase.h" 31 #include "valueflow.h" 32 33 #include <list> 34 #include <map> 35 #include <string> 36 #include <vector> 37 38 namespace tinyxml2 { 39 class XMLElement; 40 } 41 42 class ErrorLogger; 43 class Settings; 44 class Token; 45 class Tokenizer; 46 47 /// @addtogroup Checks 48 /// @{ 49 50 /** 51 * @brief buffer overruns and array index out of bounds 52 * 53 * Buffer overrun and array index out of bounds are pretty much the same. 54 * But I generally use 'array index' if the code contains []. And the given 55 * index is out of bounds. 56 * I generally use 'buffer overrun' if you for example call a strcpy or 57 * other function and pass a buffer and reads or writes too much data. 58 */ 59 class CPPCHECKLIB CheckBufferOverrun : public Check { 60 public: 61 62 /** This constructor is used when registering the CheckClass */ CheckBufferOverrun()63 CheckBufferOverrun() : Check(myName()) {} 64 65 /** This constructor is used when running checks. */ CheckBufferOverrun(const Tokenizer * tokenizer,const Settings * settings,ErrorLogger * errorLogger)66 CheckBufferOverrun(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) 67 : Check(myName(), tokenizer, settings, errorLogger) {} 68 runChecks(const Tokenizer * tokenizer,const Settings * settings,ErrorLogger * errorLogger)69 void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { 70 CheckBufferOverrun checkBufferOverrun(tokenizer, settings, errorLogger); 71 checkBufferOverrun.arrayIndex(); 72 checkBufferOverrun.pointerArithmetic(); 73 checkBufferOverrun.bufferOverflow(); 74 checkBufferOverrun.arrayIndexThenCheck(); 75 checkBufferOverrun.stringNotZeroTerminated(); 76 checkBufferOverrun.objectIndex(); 77 checkBufferOverrun.argumentSize(); 78 } 79 getErrorMessages(ErrorLogger * errorLogger,const Settings * settings)80 void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const OVERRIDE { 81 CheckBufferOverrun c(nullptr, settings, errorLogger); 82 c.arrayIndexError(nullptr, std::vector<Dimension>(), std::vector<ValueFlow::Value>()); 83 c.pointerArithmeticError(nullptr, nullptr, nullptr); 84 c.negativeIndexError(nullptr, std::vector<Dimension>(), std::vector<ValueFlow::Value>()); 85 c.arrayIndexThenCheckError(nullptr, "i"); 86 c.bufferOverflowError(nullptr, nullptr, Certainty::normal); 87 c.objectIndexError(nullptr, nullptr, true); 88 c.argumentSizeError(nullptr, "function", 1, "buffer", nullptr, nullptr); 89 } 90 91 /** @brief Parse current TU and extract file info */ 92 Check::FileInfo *getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const OVERRIDE; 93 94 /** @brief Analyse all file infos for all TU */ 95 bool analyseWholeProgram(const CTU::FileInfo *ctu, const std::list<Check::FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger) OVERRIDE; 96 97 private: 98 99 void arrayIndex(); 100 void arrayIndexError(const Token* tok, 101 const std::vector<Dimension>& dimensions, 102 const std::vector<ValueFlow::Value>& indexes); 103 void negativeIndexError(const Token* tok, 104 const std::vector<Dimension>& dimensions, 105 const std::vector<ValueFlow::Value>& indexes); 106 107 void pointerArithmetic(); 108 void pointerArithmeticError(const Token *tok, const Token *indexToken, const ValueFlow::Value *indexValue); 109 110 void bufferOverflow(); 111 void bufferOverflowError(const Token *tok, const ValueFlow::Value *value, const Certainty::CertaintyLevel& certainty); 112 113 void arrayIndexThenCheck(); 114 void arrayIndexThenCheckError(const Token *tok, const std::string &indexName); 115 116 void stringNotZeroTerminated(); 117 void terminateStrncpyError(const Token *tok, const std::string &varname); 118 119 void argumentSize(); 120 void argumentSizeError(const Token *tok, const std::string &functionName, nonneg int paramIndex, const std::string ¶mExpression, const Variable *paramVar, const Variable *functionArg); 121 122 void objectIndex(); 123 void objectIndexError(const Token *tok, const ValueFlow::Value *v, bool known); 124 125 ValueFlow::Value getBufferSize(const Token *bufTok) const; 126 127 // CTU 128 129 /** data for multifile checking */ 130 class MyFileInfo : public Check::FileInfo { 131 public: 132 /** unsafe array index usage */ 133 std::list<CTU::FileInfo::UnsafeUsage> unsafeArrayIndex; 134 135 /** unsafe pointer arithmetics */ 136 std::list<CTU::FileInfo::UnsafeUsage> unsafePointerArith; 137 138 /** Convert MyFileInfo data into xml string */ 139 std::string toString() const OVERRIDE; 140 }; 141 142 static bool isCtuUnsafeBufferUsage(const Check *check, const Token *argtok, MathLib::bigint *offset, int type); 143 static bool isCtuUnsafeArrayIndex(const Check *check, const Token *argtok, MathLib::bigint *offset); 144 static bool isCtuUnsafePointerArith(const Check *check, const Token *argtok, MathLib::bigint *offset); 145 146 Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const OVERRIDE; 147 static bool analyseWholeProgram1(const std::map<std::string, std::list<const CTU::FileInfo::CallBase *>> &callsMap, const CTU::FileInfo::UnsafeUsage &unsafeUsage, int type, ErrorLogger &errorLogger); 148 149 myName()150 static std::string myName() { 151 return "Bounds checking"; 152 } 153 classInfo()154 std::string classInfo() const OVERRIDE { 155 return "Out of bounds checking:\n" 156 "- Array index out of bounds\n" 157 "- Pointer arithmetic overflow\n" 158 "- Buffer overflow\n" 159 "- Dangerous usage of strncat()\n" 160 "- Using array index before checking it\n" 161 "- Partial string write that leads to buffer that is not zero terminated.\n" 162 "- Check for large enough arrays being passed to functions\n"; 163 } 164 }; 165 /// @} 166 //--------------------------------------------------------------------------- 167 #endif // checkbufferoverrunH 168