From efeaac736dd15bb0d754e0188e3f544f9b79b4a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 19 Feb 2009 17:57:27 +0000 Subject: [PATCH] security: added simple gui checking --- src/checkvalidate.cpp | 46 +- src/checkvalidate.h | 3 + src/errorlogger.h | 958 +++++++++++++++++++++--------------------- src/settings.cpp | 1 + src/settings.h | 3 + test/testvalidate.cpp | 35 +- tools/errmsg.cpp | 13 +- 7 files changed, 568 insertions(+), 491 deletions(-) diff --git a/src/checkvalidate.cpp b/src/checkvalidate.cpp index 65800bfdb..d0feb2b45 100644 --- a/src/checkvalidate.cpp +++ b/src/checkvalidate.cpp @@ -43,7 +43,7 @@ void CheckValidate::readnum() while (tok) { unsigned int varId = 0; - + // Search for a variable declaration while (tok) { @@ -57,20 +57,54 @@ void CheckValidate::readnum() // Skip ahead a little with tok.. tok = tok->tokAt(2); - + // Now take a look at the variable usage.. if (varId == 0) continue; - + // Search for bad input.. for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { if (Token::Match(tok2, "cin >> %varid%", varId)) - _errorLogger->unvalidatedInput(_tokenizer, tok2, tok2->strAt(2)); + _errorLogger->unvalidatedInput(_tokenizer, tok2); if (Token::Match(tok2, "fscanf ( %var% , %str% , %varid%", varId)) - _errorLogger->unvalidatedInput(_tokenizer, tok2, tok2->strAt(6)); + _errorLogger->unvalidatedInput(_tokenizer, tok2); if (Token::Match(tok2, "scanf ( %str% , %varid%", varId)) - _errorLogger->unvalidatedInput(_tokenizer, tok2, tok2->strAt(4)); + _errorLogger->unvalidatedInput(_tokenizer, tok2); + } + } +} + + +/** + * Read data from Form/GUI + * Todo: This function must be more customizable to be usable + */ +void CheckValidate::gui() +{ + // input control classes whose values are insecure.. + const char *inputclass[] = {"TEdit", 0}; + + // functions that parse value without validating it.. + const std::string dangerousfunc("atoi|atof|strtol|strtoul"); + + for (unsigned int i = 0; inputclass[i]; ++i) + { + const std::string classname(inputclass[i]); + + for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) + { + // Declaration.. + if (Token::Match(tok, (classname + " * %var% ;|=").c_str())) + { + // Variable name.. + const std::string varname(tok->strAt(2)); + + // Getting the value.. + const Token *tok2 = Token::findmatch(tok, (dangerousfunc + " ( " + varname + " .").c_str()); + if (tok2) + _errorLogger->unvalidatedInput(_tokenizer, tok2); + } } } } diff --git a/src/checkvalidate.h b/src/checkvalidate.h index 5714ab128..ebb5d2533 100644 --- a/src/checkvalidate.h +++ b/src/checkvalidate.h @@ -36,6 +36,9 @@ public: /** Reading a number from a stream/FILE */ void readnum(); + /** Reading Form/GUI data */ + void gui(); + private: const Tokenizer *_tokenizer; ErrorLogger *_errorLogger; diff --git a/src/errorlogger.h b/src/errorlogger.h index da725ea38..6c47f5922 100644 --- a/src/errorlogger.h +++ b/src/errorlogger.h @@ -1,479 +1,479 @@ -/* - * 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 - * - * 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 -#include -#include "settings.h" -class Token; -class Tokenizer; - -/** - * This is an interface, which the class responsible of error logging - * should implement. - */ -class ErrorLogger -{ -public: - - /** - * Wrapper for error messages, provided by reportErr() - */ - class ErrorMessage - { - public: - /** - * File name and line number. - */ - class FileLocation - { - public: - std::string file; - unsigned int line; - }; - - ErrorMessage(const std::list &callStack, const std::string &severity, const std::string &msg, const std::string &id); - std::string toXML() const; - std::string toText() const; - private: - std::list _callStack; - std::string _severity; - std::string _msg; - std::string _id; - }; - - ErrorLogger() { } - virtual ~ErrorLogger() { } - - /** - * Information about progress is directed here. - * Override this to receive the progress messages. - * - * @param outmsg, E.g. "Checking main.cpp..." - */ - virtual void reportOut(const std::string &outmsg) = 0; - - /** - * Information about found errors and warnings is directed - * here. Override this to receive the errormessages. - * - * @param msg Location and other information about the found. - * error - */ - virtual void reportErr(const ErrorLogger::ErrorMessage &msg) = 0; - - void arrayIndexOutOfBounds(const Tokenizer *tokenizer, const std::list &Location) - { - _writemsg(tokenizer, Location, "all", "Array index out of bounds", "arrayIndexOutOfBounds"); - } - static bool arrayIndexOutOfBounds(const Settings &s) - { - return s._showAll; - } - - void bufferOverrun(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "all", "Buffer overrun", "bufferOverrun"); - } - static bool bufferOverrun(const Settings &s) - { - return s._showAll; - } - - void outOfBounds(const Tokenizer *tokenizer, const Token *Location, const std::string &what) - { - _writemsg(tokenizer, Location, "error", "" + what + " is out of bounds", "outOfBounds"); - } - static bool outOfBounds() - { - return true; - } - - void stlOutOfBounds(const Tokenizer *tokenizer, const Token *Location, const std::string &what) - { - _writemsg(tokenizer, Location, "error", "" + what + " is out of bounds", "stlOutOfBounds"); - } - static bool stlOutOfBounds() - { - return true; - } - - void noConstructor(const Tokenizer *tokenizer, const Token *Location, const std::string &classname) - { - _writemsg(tokenizer, Location, "style", "The class '" + classname + "' has no constructor", "noConstructor"); - } - static bool noConstructor(const Settings &s) - { - return s._checkCodingStyle; - } - - void uninitVar(const Tokenizer *tokenizer, const Token *Location, const std::string &classname, const std::string &varname) - { - _writemsg(tokenizer, Location, "style", "Member variable not initialized in the constructor '" + classname + "::" + varname + "'", "uninitVar"); - } - static bool uninitVar(const Settings &s) - { - return s._checkCodingStyle; - } - - void unusedPrivateFunction(const Tokenizer *tokenizer, const Token *Location, const std::string &classname, const std::string &funcname) - { - _writemsg(tokenizer, Location, "style", "Unused private function '" + classname + "::" + funcname + "'", "unusedPrivateFunction"); - } - static bool unusedPrivateFunction(const Settings &s) - { - return s._checkCodingStyle; - } - - void memsetClass(const Tokenizer *tokenizer, const Token *Location, const std::string &memfunc) - { - _writemsg(tokenizer, Location, "error", "Using '" + memfunc + "' on class", "memsetClass"); - } - static bool memsetClass() - { - return true; - } - - void memsetStruct(const Tokenizer *tokenizer, const Token *Location, const std::string &memfunc, const std::string &classname) - { - _writemsg(tokenizer, Location, "error", "Using '" + memfunc + "' on struct that contains a 'std::" + classname + "'", "memsetStruct"); - } - static bool memsetStruct() - { - return true; - } - - void operatorEq(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "style", "'operator=' should return something", "operatorEq"); - } - static bool operatorEq(const Settings &s) - { - return s._checkCodingStyle; - } - - void virtualDestructor(const Tokenizer *tokenizer, const Token *Location, const std::string &Base, const std::string &Derived) - { - _writemsg(tokenizer, Location, "error", "Class " + Base + " which is inherited by class " + Derived + " does not have a virtual destructor", "virtualDestructor"); - } - static bool virtualDestructor() - { - return true; - } - - void unusedFunction(const std::string &filename, const std::string &funcname) - { - _writemsg("[" + filename + "]: The function '" + funcname + "' is never used", "unusedFunction"); - } - static bool unusedFunction(const Settings &s) - { - return s._checkCodingStyle || s._showAll; - } - - void mismatchAllocDealloc(const Tokenizer *tokenizer, const std::list &Location, const std::string &varname) - { - _writemsg(tokenizer, Location, "error", "Mismatching allocation and deallocation: " + varname + "", "mismatchAllocDealloc"); - } - static bool mismatchAllocDealloc() - { - return true; - } - - void memleak(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) - { - _writemsg(tokenizer, Location, "error", "Memory leak: " + varname + "", "memleak"); - } - static bool memleak() - { - return true; - } - - void memleakall(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) - { - _writemsg(tokenizer, Location, "all", "Memory leak: " + varname + "", "memleakall"); - } - static bool memleakall(const Settings &s) - { - return s._showAll; - } - - void resourceLeak(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) - { - _writemsg(tokenizer, Location, "error", "Resource leak: " + varname + "", "resourceLeak"); - } - static bool resourceLeak() - { - return true; - } - - void deallocDealloc(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) - { - _writemsg(tokenizer, Location, "error", "Deallocating a deallocated pointer: " + varname + "", "deallocDealloc"); - } - static bool deallocDealloc() - { - return true; - } - - void deallocuse(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) - { - _writemsg(tokenizer, Location, "error", "Using '" + varname + "' after it is deallocated / released", "deallocuse"); - } - static bool deallocuse() - { - return true; - } - - void mismatchSize(const Tokenizer *tokenizer, const Token *Location, const std::string &sz) - { - _writemsg(tokenizer, Location, "error", "The given size " + sz + " is mismatching", "mismatchSize"); - } - static bool mismatchSize() - { - return true; - } - - void cstyleCast(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "style", "C-style pointer casting", "cstyleCast"); - } - static bool cstyleCast(const Settings &s) - { - return s._checkCodingStyle; - } - - void redundantIfDelete0(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "style", "Redundant condition. It is safe to deallocate a NULL pointer", "redundantIfDelete0"); - } - static bool redundantIfDelete0(const Settings &s) - { - return s._checkCodingStyle; - } - - void redundantIfRemove(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "style", "Redundant condition. The remove function in the STL will not do anything if element doesn't exist", "redundantIfRemove"); - } - static bool redundantIfRemove(const Settings &s) - { - return s._checkCodingStyle; - } - - void dangerousUsageStrtol(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "error", "Invalid radix in call to strtol or strtoul. Must be 0 or 2-36", "dangerousUsageStrtol"); - } - static bool dangerousUsageStrtol() - { - return true; - } - - void ifNoAction(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "style", "Found redundant if condition - 'if (condition);'", "ifNoAction"); - } - static bool ifNoAction(const Settings &s) - { - return s._checkCodingStyle; - } - - void sprintfOverlappingData(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) - { - _writemsg(tokenizer, Location, "error", "Overlapping data buffer " + varname + "", "sprintfOverlappingData"); - } - static bool sprintfOverlappingData() - { - return true; - } - - void udivError(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "error", "Unsigned division. The result will be wrong.", "udivError"); - } - static bool udivError() - { - return true; - } - - void udivWarning(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "all style", "Warning: Division with signed and unsigned operators", "udivWarning"); - } - static bool udivWarning(const Settings &s) - { - return s._checkCodingStyle || s._showAll; - } - - void unusedStructMember(const Tokenizer *tokenizer, const Token *Location, const std::string &structname, const std::string &varname) - { - _writemsg(tokenizer, Location, "style", "struct or union member '" + structname + "::" + varname + "' is never used", "unusedStructMember"); - } - static bool unusedStructMember(const Settings &s) - { - return s._checkCodingStyle; - } - - void passedByValue(const Tokenizer *tokenizer, const Token *Location, const std::string &parname) - { - _writemsg(tokenizer, Location, "style", "Function parameter '" + parname + "' is passed by value. It could be passed by reference instead.", "passedByValue"); - } - static bool passedByValue(const Settings &s) - { - return s._checkCodingStyle; - } - - void constStatement(const Tokenizer *tokenizer, const Token *Location, const std::string &type) - { - _writemsg(tokenizer, Location, "style", "Redundant code: Found a statement that begins with " + type + " constant", "constStatement"); - } - static bool constStatement(const Settings &s) - { - return s._checkCodingStyle; - } - - void charArrayIndex(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "style", "Warning - using char variable as array index", "charArrayIndex"); - } - static bool charArrayIndex(const Settings &s) - { - return s._checkCodingStyle; - } - - void charBitOp(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "style", "Warning - using char variable in bit operation", "charBitOp"); - } - static bool charBitOp(const Settings &s) - { - return s._checkCodingStyle; - } - - void variableScope(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) - { - _writemsg(tokenizer, Location, "never", "The scope of the variable " + varname + " can be limited", "variableScope"); - } - static bool variableScope() - { - return false; - } - - void conditionAlwaysTrueFalse(const Tokenizer *tokenizer, const Token *Location, const std::string &truefalse) - { - _writemsg(tokenizer, Location, "style", "Condition is always " + truefalse + "", "conditionAlwaysTrueFalse"); - } - static bool conditionAlwaysTrueFalse(const Settings &s) - { - return s._checkCodingStyle; - } - - void strPlusChar(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "error", "Unusual pointer arithmetic", "strPlusChar"); - } - static bool strPlusChar() - { - return true; - } - - void returnLocalVariable(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "error", "Returning pointer to local array variable", "returnLocalVariable"); - } - static bool returnLocalVariable() - { - return true; - } - - void dangerousFunctionmktemp(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "style", "Found 'mktemp'. You should use 'mkstemp' instead", "dangerousFunctionmktemp"); - } - static bool dangerousFunctionmktemp(const Settings &s) - { - return s._checkCodingStyle; - } - - void dangerousFunctiongets(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "style", "Found 'gets'. You should use 'fgets' instead", "dangerousFunctiongets"); - } - static bool dangerousFunctiongets(const Settings &s) - { - return s._checkCodingStyle; - } - - void dangerousFunctionscanf(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "style", "Found 'scanf'. You should use 'fgets' instead", "dangerousFunctionscanf"); - } - static bool dangerousFunctionscanf(const Settings &s) - { - return s._checkCodingStyle; - } - - void iteratorUsage(const Tokenizer *tokenizer, const Token *Location, const std::string &container1, const std::string &container2) - { - _writemsg(tokenizer, Location, "error", "Same iterator is used with both " + container1 + " and " + container2 + "", "iteratorUsage"); - } - static bool iteratorUsage() - { - return true; - } - - void erase(const Tokenizer *tokenizer, const Token *Location) - { - _writemsg(tokenizer, Location, "error", "Dangerous usage of erase", "erase"); - } - static bool erase() - { - return true; - } - - void pushback(const Tokenizer *tokenizer, const Token *Location, const std::string &iterator_name) - { - _writemsg(tokenizer, Location, "error", "After push_back or push_front, the iterator '" + iterator_name + "' may be invalid", "pushback"); - } - static bool pushback() - { - return true; - } - - void unvalidatedInput(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) - { - _writemsg(tokenizer, Location, "all", "Unvalidated input: " + varname + "", "unvalidatedInput"); - } - static bool unvalidatedInput(const Settings &s) - { - return s._showAll; - } - - - static std::string callStackToString(const std::list &callStack); - -private: - void _writemsg(const Tokenizer *tokenizer, const Token *tok, const char severity[], const std::string msg, const std::string &id); - void _writemsg(const Tokenizer *tokenizer, const std::list &callstack, const char severity[], const std::string msg, const std::string &id); - void _writemsg(const std::string msg, const std::string &id); -}; -#endif +/* + * 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 + * + * 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 +#include +#include "settings.h" +class Token; +class Tokenizer; + +/** + * This is an interface, which the class responsible of error logging + * should implement. + */ +class ErrorLogger +{ +public: + + /** + * Wrapper for error messages, provided by reportErr() + */ + class ErrorMessage + { + public: + /** + * File name and line number. + */ + class FileLocation + { + public: + std::string file; + unsigned int line; + }; + + ErrorMessage(const std::list &callStack, const std::string &severity, const std::string &msg, const std::string &id); + std::string toXML() const; + std::string toText() const; + private: + std::list _callStack; + std::string _severity; + std::string _msg; + std::string _id; + }; + + ErrorLogger() { } + virtual ~ErrorLogger() { } + + /** + * Information about progress is directed here. + * Override this to receive the progress messages. + * + * @param outmsg, E.g. "Checking main.cpp..." + */ + virtual void reportOut(const std::string &outmsg) = 0; + + /** + * Information about found errors and warnings is directed + * here. Override this to receive the errormessages. + * + * @param msg Location and other information about the found. + * error + */ + virtual void reportErr(const ErrorLogger::ErrorMessage &msg) = 0; + + void arrayIndexOutOfBounds(const Tokenizer *tokenizer, const std::list &Location) + { + _writemsg(tokenizer, Location, "all", "Array index out of bounds", "arrayIndexOutOfBounds"); + } + static bool arrayIndexOutOfBounds(const Settings &s) + { + return s._showAll; + } + + void bufferOverrun(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "all", "Buffer overrun", "bufferOverrun"); + } + static bool bufferOverrun(const Settings &s) + { + return s._showAll; + } + + void outOfBounds(const Tokenizer *tokenizer, const Token *Location, const std::string &what) + { + _writemsg(tokenizer, Location, "error", "" + what + " is out of bounds", "outOfBounds"); + } + static bool outOfBounds() + { + return true; + } + + void stlOutOfBounds(const Tokenizer *tokenizer, const Token *Location, const std::string &what) + { + _writemsg(tokenizer, Location, "error", "" + what + " is out of bounds", "stlOutOfBounds"); + } + static bool stlOutOfBounds() + { + return true; + } + + void noConstructor(const Tokenizer *tokenizer, const Token *Location, const std::string &classname) + { + _writemsg(tokenizer, Location, "style", "The class '" + classname + "' has no constructor", "noConstructor"); + } + static bool noConstructor(const Settings &s) + { + return s._checkCodingStyle; + } + + void uninitVar(const Tokenizer *tokenizer, const Token *Location, const std::string &classname, const std::string &varname) + { + _writemsg(tokenizer, Location, "style", "Member variable not initialized in the constructor '" + classname + "::" + varname + "'", "uninitVar"); + } + static bool uninitVar(const Settings &s) + { + return s._checkCodingStyle; + } + + void unusedPrivateFunction(const Tokenizer *tokenizer, const Token *Location, const std::string &classname, const std::string &funcname) + { + _writemsg(tokenizer, Location, "style", "Unused private function '" + classname + "::" + funcname + "'", "unusedPrivateFunction"); + } + static bool unusedPrivateFunction(const Settings &s) + { + return s._checkCodingStyle; + } + + void memsetClass(const Tokenizer *tokenizer, const Token *Location, const std::string &memfunc) + { + _writemsg(tokenizer, Location, "error", "Using '" + memfunc + "' on class", "memsetClass"); + } + static bool memsetClass() + { + return true; + } + + void memsetStruct(const Tokenizer *tokenizer, const Token *Location, const std::string &memfunc, const std::string &classname) + { + _writemsg(tokenizer, Location, "error", "Using '" + memfunc + "' on struct that contains a 'std::" + classname + "'", "memsetStruct"); + } + static bool memsetStruct() + { + return true; + } + + void operatorEq(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "style", "'operator=' should return something", "operatorEq"); + } + static bool operatorEq(const Settings &s) + { + return s._checkCodingStyle; + } + + void virtualDestructor(const Tokenizer *tokenizer, const Token *Location, const std::string &Base, const std::string &Derived) + { + _writemsg(tokenizer, Location, "error", "Class " + Base + " which is inherited by class " + Derived + " does not have a virtual destructor", "virtualDestructor"); + } + static bool virtualDestructor() + { + return true; + } + + void unusedFunction(const std::string &filename, const std::string &funcname) + { + _writemsg("[" + filename + "]: The function '" + funcname + "' is never used", "unusedFunction"); + } + static bool unusedFunction(const Settings &s) + { + return s._checkCodingStyle || s._showAll; + } + + void mismatchAllocDealloc(const Tokenizer *tokenizer, const std::list &Location, const std::string &varname) + { + _writemsg(tokenizer, Location, "error", "Mismatching allocation and deallocation: " + varname + "", "mismatchAllocDealloc"); + } + static bool mismatchAllocDealloc() + { + return true; + } + + void memleak(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) + { + _writemsg(tokenizer, Location, "error", "Memory leak: " + varname + "", "memleak"); + } + static bool memleak() + { + return true; + } + + void memleakall(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) + { + _writemsg(tokenizer, Location, "all", "Memory leak: " + varname + "", "memleakall"); + } + static bool memleakall(const Settings &s) + { + return s._showAll; + } + + void resourceLeak(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) + { + _writemsg(tokenizer, Location, "error", "Resource leak: " + varname + "", "resourceLeak"); + } + static bool resourceLeak() + { + return true; + } + + void deallocDealloc(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) + { + _writemsg(tokenizer, Location, "error", "Deallocating a deallocated pointer: " + varname + "", "deallocDealloc"); + } + static bool deallocDealloc() + { + return true; + } + + void deallocuse(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) + { + _writemsg(tokenizer, Location, "error", "Using '" + varname + "' after it is deallocated / released", "deallocuse"); + } + static bool deallocuse() + { + return true; + } + + void mismatchSize(const Tokenizer *tokenizer, const Token *Location, const std::string &sz) + { + _writemsg(tokenizer, Location, "error", "The given size " + sz + " is mismatching", "mismatchSize"); + } + static bool mismatchSize() + { + return true; + } + + void cstyleCast(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "style", "C-style pointer casting", "cstyleCast"); + } + static bool cstyleCast(const Settings &s) + { + return s._checkCodingStyle; + } + + void redundantIfDelete0(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "style", "Redundant condition. It is safe to deallocate a NULL pointer", "redundantIfDelete0"); + } + static bool redundantIfDelete0(const Settings &s) + { + return s._checkCodingStyle; + } + + void redundantIfRemove(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "style", "Redundant condition. The remove function in the STL will not do anything if element doesn't exist", "redundantIfRemove"); + } + static bool redundantIfRemove(const Settings &s) + { + return s._checkCodingStyle; + } + + void dangerousUsageStrtol(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "error", "Invalid radix in call to strtol or strtoul. Must be 0 or 2-36", "dangerousUsageStrtol"); + } + static bool dangerousUsageStrtol() + { + return true; + } + + void ifNoAction(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "style", "Found redundant if condition - 'if (condition);'", "ifNoAction"); + } + static bool ifNoAction(const Settings &s) + { + return s._checkCodingStyle; + } + + void sprintfOverlappingData(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) + { + _writemsg(tokenizer, Location, "error", "Overlapping data buffer " + varname + "", "sprintfOverlappingData"); + } + static bool sprintfOverlappingData() + { + return true; + } + + void udivError(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "error", "Unsigned division. The result will be wrong.", "udivError"); + } + static bool udivError() + { + return true; + } + + void udivWarning(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "all style", "Warning: Division with signed and unsigned operators", "udivWarning"); + } + static bool udivWarning(const Settings &s) + { + return s._checkCodingStyle || s._showAll; + } + + void unusedStructMember(const Tokenizer *tokenizer, const Token *Location, const std::string &structname, const std::string &varname) + { + _writemsg(tokenizer, Location, "style", "struct or union member '" + structname + "::" + varname + "' is never used", "unusedStructMember"); + } + static bool unusedStructMember(const Settings &s) + { + return s._checkCodingStyle; + } + + void passedByValue(const Tokenizer *tokenizer, const Token *Location, const std::string &parname) + { + _writemsg(tokenizer, Location, "style", "Function parameter '" + parname + "' is passed by value. It could be passed by reference instead.", "passedByValue"); + } + static bool passedByValue(const Settings &s) + { + return s._checkCodingStyle; + } + + void constStatement(const Tokenizer *tokenizer, const Token *Location, const std::string &type) + { + _writemsg(tokenizer, Location, "style", "Redundant code: Found a statement that begins with " + type + " constant", "constStatement"); + } + static bool constStatement(const Settings &s) + { + return s._checkCodingStyle; + } + + void charArrayIndex(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "style", "Warning - using char variable as array index", "charArrayIndex"); + } + static bool charArrayIndex(const Settings &s) + { + return s._checkCodingStyle; + } + + void charBitOp(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "style", "Warning - using char variable in bit operation", "charBitOp"); + } + static bool charBitOp(const Settings &s) + { + return s._checkCodingStyle; + } + + void variableScope(const Tokenizer *tokenizer, const Token *Location, const std::string &varname) + { + _writemsg(tokenizer, Location, "never", "The scope of the variable " + varname + " can be limited", "variableScope"); + } + static bool variableScope() + { + return false; + } + + void conditionAlwaysTrueFalse(const Tokenizer *tokenizer, const Token *Location, const std::string &truefalse) + { + _writemsg(tokenizer, Location, "style", "Condition is always " + truefalse + "", "conditionAlwaysTrueFalse"); + } + static bool conditionAlwaysTrueFalse(const Settings &s) + { + return s._checkCodingStyle; + } + + void strPlusChar(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "error", "Unusual pointer arithmetic", "strPlusChar"); + } + static bool strPlusChar() + { + return true; + } + + void returnLocalVariable(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "error", "Returning pointer to local array variable", "returnLocalVariable"); + } + static bool returnLocalVariable() + { + return true; + } + + void dangerousFunctionmktemp(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "style", "Found 'mktemp'. You should use 'mkstemp' instead", "dangerousFunctionmktemp"); + } + static bool dangerousFunctionmktemp(const Settings &s) + { + return s._checkCodingStyle; + } + + void dangerousFunctiongets(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "style", "Found 'gets'. You should use 'fgets' instead", "dangerousFunctiongets"); + } + static bool dangerousFunctiongets(const Settings &s) + { + return s._checkCodingStyle; + } + + void dangerousFunctionscanf(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "style", "Found 'scanf'. You should use 'fgets' instead", "dangerousFunctionscanf"); + } + static bool dangerousFunctionscanf(const Settings &s) + { + return s._checkCodingStyle; + } + + void iteratorUsage(const Tokenizer *tokenizer, const Token *Location, const std::string &container1, const std::string &container2) + { + _writemsg(tokenizer, Location, "error", "Same iterator is used with both " + container1 + " and " + container2 + "", "iteratorUsage"); + } + static bool iteratorUsage() + { + return true; + } + + void erase(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "error", "Dangerous usage of erase", "erase"); + } + static bool erase() + { + return true; + } + + void pushback(const Tokenizer *tokenizer, const Token *Location, const std::string &iterator_name) + { + _writemsg(tokenizer, Location, "error", "After push_back or push_front, the iterator '" + iterator_name + "' may be invalid", "pushback"); + } + static bool pushback() + { + return true; + } + + void unvalidatedInput(const Tokenizer *tokenizer, const Token *Location) + { + _writemsg(tokenizer, Location, "security", "Unvalidated input", "unvalidatedInput"); + } + static bool unvalidatedInput(const Settings &s) + { + return s._security; + } + + + static std::string callStackToString(const std::list &callStack); + +private: + void _writemsg(const Tokenizer *tokenizer, const Token *tok, const char severity[], const std::string msg, const std::string &id); + void _writemsg(const Tokenizer *tokenizer, const std::list &callstack, const char severity[], const std::string msg, const std::string &id); + void _writemsg(const std::string msg, const std::string &id); +}; +#endif diff --git a/src/settings.cpp b/src/settings.cpp index 637f58bcf..1a893041b 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -29,6 +29,7 @@ Settings::Settings() _force = false; _xml = false; _unusedFunctions = false; + _security = false; } Settings::~Settings() diff --git a/src/settings.h b/src/settings.h index a3d3afbaf..05803c4fe 100644 --- a/src/settings.h +++ b/src/settings.h @@ -45,6 +45,9 @@ public: /** Checking if there are unused functions */ bool _unusedFunctions; + + /** Security checks */ + bool _security; }; #endif // SETTINGS_H diff --git a/test/testvalidate.cpp b/test/testvalidate.cpp index 091af32b5..74d1c61b8 100644 --- a/test/testvalidate.cpp +++ b/test/testvalidate.cpp @@ -37,6 +37,7 @@ private: void run() { TEST_CASE(stdin1); + TEST_CASE(gui); } void check(const char code[]) @@ -63,7 +64,39 @@ private: " int i;\n" " std::cin >> i;\n" "}\n"); - ASSERT_EQUALS("[test.cpp:4]: (all) Unvalidated input: i\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (security) Unvalidated input\n", errout.str()); + } + + + + + + void checkGui(const char code[]) + { + // Tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + tokenizer.simplifyTokenList(); + + // Clear the error buffer.. + errout.str(""); + + // Check char variable usage.. + CheckValidate checkValidate(&tokenizer, this); + checkValidate.gui(); + } + + + void gui() + { + // Reading the value of a textbox and converting it into an int without any validation.. + checkGui("void onok()\n" + "{\n" + " TEdit *editAbc;\n" + " abc = atoi(editAbc->Text.c_str());\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (security) Unvalidated input\n", errout.str()); } }; diff --git a/tools/errmsg.cpp b/tools/errmsg.cpp index 992af1950..0b0bede38 100644 --- a/tools/errmsg.cpp +++ b/tools/errmsg.cpp @@ -25,7 +25,7 @@ class Message { public: - enum Settings {error, all, style, style_all, never}; + enum Settings {error, all, style, style_all, security, never}; Message(std::string funcname, Settings settings, std::string msg); Message(std::string funcname, Settings settings, std::string msg, std::string par1); @@ -118,7 +118,7 @@ int main() // checkvalidate.cpp - err.push_back(Message("unvalidatedInput", Message::all, "Unvalidated input: %1", "varname")); + err.push_back(Message("unvalidatedInput", Message::security, "Unvalidated input")); // Generate code.. @@ -223,10 +223,11 @@ int main() // Generate documentation.. std::cout << "Generate doc.." << std::endl; - for (unsigned int i = 0; i < 4; ++i) + const unsigned int NUMSUITE = 5; + for (unsigned int i = 0; i < NUMSUITE; ++i) { - const char *suite[4] = { "error", "all", "style", "all + style" }; - const Message::Settings settings[4] = { Message::error, Message::all, Message::style, Message::style_all }; + const char *suite[NUMSUITE] = { "error", "all", "style", "all + style", "security" }; + const Message::Settings settings[NUMSUITE] = { Message::error, Message::all, Message::style, Message::style_all, Message::security }; std::cout << " =" << suite[i] << "=" << std::endl; for (std::list::const_iterator it = err.begin(); it != err.end(); ++it) it->generateDoc(std::cout, settings[i]); @@ -374,6 +375,8 @@ std::string Message::stringifySettings(bool text) const return text ? "style" : "s._checkCodingStyle"; case style_all: return text ? "all style" : "s._checkCodingStyle || s._showAll"; + case security: + return text ? "security" : "s._security"; case never: return text ? "never" : "false"; }