2009-01-31 20:29:27 +01:00
|
|
|
/*
|
|
|
|
* Cppcheck - A tool for static C/C++ code analysis
|
2023-01-28 10:16:34 +01:00
|
|
|
* Copyright (C) 2007-2023 Cppcheck team.
|
2009-01-31 20:29:27 +01:00
|
|
|
*
|
|
|
|
* 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
|
2009-09-27 17:08:31 +02:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2009-01-31 20:29:27 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
2013-09-04 20:59:49 +02:00
|
|
|
#ifndef checkbufferoverrunH
|
|
|
|
#define checkbufferoverrunH
|
2009-01-31 20:29:27 +01:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2009-03-20 17:35:53 +01:00
|
|
|
#include "check.h"
|
2017-05-27 04:33:47 +02:00
|
|
|
#include "config.h"
|
2019-03-23 08:36:10 +01:00
|
|
|
#include "ctu.h"
|
2021-04-13 16:40:38 +02:00
|
|
|
#include "errortypes.h"
|
2010-11-21 11:48:27 +01:00
|
|
|
#include "mathlib.h"
|
2019-03-17 13:09:15 +01:00
|
|
|
#include "symboldatabase.h"
|
2023-08-18 12:03:50 +02:00
|
|
|
#include "tokenize.h"
|
2023-01-26 22:23:22 +01:00
|
|
|
#include "vfvalue.h"
|
Mapped toomanyconfigs ,AssignmentAddressToInteger
,AssignmentIntegerToAddress ,CastIntegerToAddressAtReturn
,CastAddressToIntegerAtReturn ,assertWithSideEffect ,assignmentInAssert
,uselessAssignmentArg ,uselessAssignmentPtrArg
,comparisonOfFuncReturningBoolError
,comparisonOfTwoFuncsReturningBoolError ,comparisonOfBoolWithBoolError
,incrementboolean ,comparisonOfBoolWithInt ,compareBoolExpressionWithInt
,negativeIndex ,pointerOutOfBounds ,arrayIndexThenCheck
,possibleBufferAccessOutOfBounds ,argumentSize
,arrayIndexOutOfBoundsCond ,noConstructor ,copyCtorPointerCopying
,noCopyConstructor ,uninitMemberVar ,operatorEqVarError
,unusedPrivateFunction ,memsetClassFloat ,mallocOnClassWarning
,operatorEq ,thisSubtraction ,operatorEqRetRefThis ,operatorEqToSelf
,useInitializationList ,duplInheritedMember ,assignIfError
,comparisonError ,multiCondition ,mismatchingBitAnd
,oppositeInnerCondition ,incorrectLogicOperator ,redundantCondition
,moduloAlwaysTrueFalse to their CWEs ids.
2016-02-20 23:56:36 +01:00
|
|
|
|
2009-02-11 06:16:10 +01:00
|
|
|
#include <list>
|
2017-05-27 04:33:47 +02:00
|
|
|
#include <map>
|
2010-02-14 19:58:17 +01:00
|
|
|
#include <string>
|
2017-05-27 04:33:47 +02:00
|
|
|
#include <vector>
|
|
|
|
|
2020-04-13 13:44:48 +02:00
|
|
|
namespace tinyxml2 {
|
2020-04-13 13:48:05 +02:00
|
|
|
class XMLElement;
|
2020-04-13 13:44:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
class ErrorLogger;
|
|
|
|
class Settings;
|
|
|
|
class Token;
|
2009-01-31 20:29:27 +01:00
|
|
|
|
2009-07-17 10:49:01 +02:00
|
|
|
/// @addtogroup Checks
|
|
|
|
/// @{
|
|
|
|
|
2010-03-13 21:42:59 +01:00
|
|
|
/**
|
|
|
|
* @brief buffer overruns and array index out of bounds
|
|
|
|
*
|
|
|
|
* Buffer overrun and array index out of bounds are pretty much the same.
|
|
|
|
* But I generally use 'array index' if the code contains []. And the given
|
|
|
|
* index is out of bounds.
|
|
|
|
* I generally use 'buffer overrun' if you for example call a strcpy or
|
|
|
|
* other function and pass a buffer and reads or writes too much data.
|
|
|
|
*/
|
2012-06-10 14:19:09 +02:00
|
|
|
class CPPCHECKLIB CheckBufferOverrun : public Check {
|
2009-01-31 20:29:27 +01:00
|
|
|
public:
|
2009-03-20 17:35:53 +01:00
|
|
|
|
2009-03-21 07:53:23 +01:00
|
|
|
/** This constructor is used when registering the CheckClass */
|
2021-08-07 20:51:18 +02:00
|
|
|
CheckBufferOverrun() : Check(myName()) {}
|
2009-03-20 17:35:53 +01:00
|
|
|
|
2010-03-17 22:16:18 +01:00
|
|
|
/** This constructor is used when running checks. */
|
2009-07-13 16:00:15 +02:00
|
|
|
CheckBufferOverrun(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
2021-08-07 20:51:18 +02:00
|
|
|
: Check(myName(), tokenizer, settings, errorLogger) {}
|
2009-03-20 17:35:53 +01:00
|
|
|
|
2023-08-18 12:03:50 +02:00
|
|
|
void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override {
|
|
|
|
CheckBufferOverrun checkBufferOverrun(&tokenizer, tokenizer.getSettings(), errorLogger);
|
2019-03-09 22:14:02 +01:00
|
|
|
checkBufferOverrun.arrayIndex();
|
2019-03-31 09:00:52 +02:00
|
|
|
checkBufferOverrun.pointerArithmetic();
|
2019-03-09 22:14:02 +01:00
|
|
|
checkBufferOverrun.bufferOverflow();
|
2019-03-11 19:20:06 +01:00
|
|
|
checkBufferOverrun.arrayIndexThenCheck();
|
2019-03-12 21:15:26 +01:00
|
|
|
checkBufferOverrun.stringNotZeroTerminated();
|
2019-05-31 11:16:04 +02:00
|
|
|
checkBufferOverrun.objectIndex();
|
2021-08-22 16:37:41 +02:00
|
|
|
checkBufferOverrun.argumentSize();
|
2022-06-11 09:55:38 +02:00
|
|
|
checkBufferOverrun.negativeArraySize();
|
2009-03-20 17:35:53 +01:00
|
|
|
}
|
2009-01-31 20:29:27 +01:00
|
|
|
|
2022-02-10 23:02:24 +01:00
|
|
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override {
|
2016-05-07 16:30:54 +02:00
|
|
|
CheckBufferOverrun c(nullptr, settings, errorLogger);
|
2021-08-16 09:19:07 +02:00
|
|
|
c.arrayIndexError(nullptr, std::vector<Dimension>(), std::vector<ValueFlow::Value>());
|
2019-03-31 09:00:52 +02:00
|
|
|
c.pointerArithmeticError(nullptr, nullptr, nullptr);
|
2021-08-16 09:19:07 +02:00
|
|
|
c.negativeIndexError(nullptr, std::vector<Dimension>(), std::vector<ValueFlow::Value>());
|
2019-03-11 19:20:06 +01:00
|
|
|
c.arrayIndexThenCheckError(nullptr, "i");
|
2021-04-13 16:40:38 +02:00
|
|
|
c.bufferOverflowError(nullptr, nullptr, Certainty::normal);
|
2019-05-31 11:16:04 +02:00
|
|
|
c.objectIndexError(nullptr, nullptr, true);
|
2021-08-29 15:38:58 +02:00
|
|
|
c.argumentSizeError(nullptr, "function", 1, "buffer", nullptr, nullptr);
|
2022-08-20 07:56:31 +02:00
|
|
|
c.negativeMemoryAllocationSizeError(nullptr, nullptr);
|
2022-06-11 09:55:38 +02:00
|
|
|
c.negativeArraySizeError(nullptr);
|
2009-03-22 08:20:15 +01:00
|
|
|
}
|
2019-03-09 22:14:02 +01:00
|
|
|
|
2019-03-23 08:36:10 +01:00
|
|
|
/** @brief Parse current TU and extract file info */
|
2022-02-10 23:02:24 +01:00
|
|
|
Check::FileInfo *getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const override;
|
2019-03-23 08:36:10 +01:00
|
|
|
|
|
|
|
/** @brief Analyse all file infos for all TU */
|
2022-02-10 23:02:24 +01:00
|
|
|
bool analyseWholeProgram(const CTU::FileInfo *ctu, const std::list<Check::FileInfo*> &fileInfo, const Settings& settings, ErrorLogger &errorLogger) override;
|
2019-03-23 08:36:10 +01:00
|
|
|
|
2012-03-17 21:55:08 +01:00
|
|
|
private:
|
2009-06-12 12:19:37 +02:00
|
|
|
|
2019-03-09 22:14:02 +01:00
|
|
|
void arrayIndex();
|
2021-08-16 09:19:07 +02:00
|
|
|
void arrayIndexError(const Token* tok,
|
|
|
|
const std::vector<Dimension>& dimensions,
|
|
|
|
const std::vector<ValueFlow::Value>& indexes);
|
|
|
|
void negativeIndexError(const Token* tok,
|
|
|
|
const std::vector<Dimension>& dimensions,
|
|
|
|
const std::vector<ValueFlow::Value>& indexes);
|
2019-03-09 22:14:02 +01:00
|
|
|
|
2019-03-31 09:00:52 +02:00
|
|
|
void pointerArithmetic();
|
|
|
|
void pointerArithmeticError(const Token *tok, const Token *indexToken, const ValueFlow::Value *indexValue);
|
|
|
|
|
2019-03-09 22:14:02 +01:00
|
|
|
void bufferOverflow();
|
2023-01-08 19:31:54 +01:00
|
|
|
void bufferOverflowError(const Token *tok, const ValueFlow::Value *value, Certainty certainty);
|
2019-03-09 22:14:02 +01:00
|
|
|
|
2019-03-11 19:20:06 +01:00
|
|
|
void arrayIndexThenCheck();
|
|
|
|
void arrayIndexThenCheckError(const Token *tok, const std::string &indexName);
|
|
|
|
|
2019-03-12 21:15:26 +01:00
|
|
|
void stringNotZeroTerminated();
|
|
|
|
void terminateStrncpyError(const Token *tok, const std::string &varname);
|
|
|
|
|
2021-08-22 16:37:41 +02:00
|
|
|
void argumentSize();
|
2021-08-29 15:38:58 +02:00
|
|
|
void argumentSizeError(const Token *tok, const std::string &functionName, nonneg int paramIndex, const std::string ¶mExpression, const Variable *paramVar, const Variable *functionArg);
|
2021-08-22 16:37:41 +02:00
|
|
|
|
2022-06-11 09:55:38 +02:00
|
|
|
void negativeArraySize();
|
|
|
|
void negativeArraySizeError(const Token* tok);
|
2022-08-20 07:56:31 +02:00
|
|
|
void negativeMemoryAllocationSizeError(const Token* tok, const ValueFlow::Value* value); // provide a negative value to memory allocation function
|
2022-06-11 09:55:38 +02:00
|
|
|
|
2019-05-31 11:16:04 +02:00
|
|
|
void objectIndex();
|
|
|
|
void objectIndexError(const Token *tok, const ValueFlow::Value *v, bool known);
|
|
|
|
|
2019-03-17 20:12:02 +01:00
|
|
|
ValueFlow::Value getBufferSize(const Token *bufTok) const;
|
2019-03-09 22:14:02 +01:00
|
|
|
|
2019-03-23 08:36:10 +01:00
|
|
|
// CTU
|
|
|
|
|
|
|
|
/** data for multifile checking */
|
|
|
|
class MyFileInfo : public Check::FileInfo {
|
|
|
|
public:
|
2019-04-03 06:43:56 +02:00
|
|
|
/** unsafe array index usage */
|
|
|
|
std::list<CTU::FileInfo::UnsafeUsage> unsafeArrayIndex;
|
|
|
|
|
2023-06-14 12:30:45 +02:00
|
|
|
/** unsafe pointer arithmetic */
|
2019-04-03 06:43:56 +02:00
|
|
|
std::list<CTU::FileInfo::UnsafeUsage> unsafePointerArith;
|
2019-03-23 08:36:10 +01:00
|
|
|
|
|
|
|
/** Convert MyFileInfo data into xml string */
|
2022-02-10 23:02:24 +01:00
|
|
|
std::string toString() const override;
|
2019-03-23 08:36:10 +01:00
|
|
|
};
|
|
|
|
|
2019-06-15 13:01:45 +02:00
|
|
|
static bool isCtuUnsafeBufferUsage(const Check *check, const Token *argtok, MathLib::bigint *offset, int type);
|
|
|
|
static bool isCtuUnsafeArrayIndex(const Check *check, const Token *argtok, MathLib::bigint *offset);
|
|
|
|
static bool isCtuUnsafePointerArith(const Check *check, const Token *argtok, MathLib::bigint *offset);
|
2019-03-23 08:36:10 +01:00
|
|
|
|
2022-02-10 23:02:24 +01:00
|
|
|
Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const override;
|
2021-01-09 20:32:38 +01:00
|
|
|
static bool analyseWholeProgram1(const std::map<std::string, std::list<const CTU::FileInfo::CallBase *>> &callsMap, const CTU::FileInfo::UnsafeUsage &unsafeUsage, int type, ErrorLogger &errorLogger);
|
2019-03-23 08:36:10 +01:00
|
|
|
|
|
|
|
|
2014-11-20 14:20:09 +01:00
|
|
|
static std::string myName() {
|
2009-06-12 15:20:08 +02:00
|
|
|
return "Bounds checking";
|
|
|
|
}
|
|
|
|
|
2022-02-10 23:02:24 +01:00
|
|
|
std::string classInfo() const override {
|
2014-05-22 09:13:29 +02:00
|
|
|
return "Out of bounds checking:\n"
|
2019-03-09 22:14:02 +01:00
|
|
|
"- Array index out of bounds\n"
|
2019-03-31 09:00:52 +02:00
|
|
|
"- Pointer arithmetic overflow\n"
|
2019-03-09 22:14:02 +01:00
|
|
|
"- Buffer overflow\n"
|
2019-03-11 19:20:06 +01:00
|
|
|
"- Dangerous usage of strncat()\n"
|
2019-03-12 21:15:26 +01:00
|
|
|
"- Using array index before checking it\n"
|
2021-08-22 16:37:41 +02:00
|
|
|
"- Partial string write that leads to buffer that is not zero terminated.\n"
|
2022-06-11 09:55:38 +02:00
|
|
|
"- Check for large enough arrays being passed to functions\n"
|
|
|
|
"- Allocating memory with a negative size\n";
|
2009-06-12 12:19:37 +02:00
|
|
|
}
|
2009-01-31 20:29:27 +01:00
|
|
|
};
|
2009-07-17 10:49:01 +02:00
|
|
|
/// @}
|
2009-01-31 20:29:27 +01:00
|
|
|
//---------------------------------------------------------------------------
|
2013-09-04 20:59:49 +02:00
|
|
|
#endif // checkbufferoverrunH
|