/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2019 Cppcheck team. * * 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 . */ //--------------------------------------------------------------------------- #ifndef exprengineH #define exprengineH //--------------------------------------------------------------------------- #include "config.h" #include #include #include #include #include #include #include class ErrorLogger; class Tokenizer; class Scope; class Settings; class Token; #ifdef __GNUC__ typedef __int128_t int128_t; #else typedef long long int128_t; #ifdef _MSC_VER #pragma message(__FILE__ "(" _CRT_STRINGIZE(__LINE__) ")" ": warning: TODO No 128-bit integer type is available => Limited analysis of large integers...") #else #warning TODO No 128-bit integer type is available => Limited analysis of large integers #endif #endif namespace ExprEngine { std::string str(int128_t); // TODO we need to handle floats, containers, pointers, aliases and structs and stuff enum class ValueType { UninitValue, IntRange, PointerValue, ArrayValue, StructValue, AddressOfValue, BinOpResult }; class Value; typedef std::shared_ptr ValuePtr; class Value { public: Value(const std::string &name) : name(name) {} virtual ~Value() {} virtual ValueType type() const = 0; virtual std::string getRange() const = 0; virtual bool isIntValueInRange(int value) const { (void)value; return false; } const std::string name; }; class UninitValue: public Value { public: UninitValue() : Value("?") {} ValueType type() const override { return ValueType::UninitValue; } std::string getRange() const override { return "?"; } }; class IntRange : public Value { public: IntRange(const std::string &name, int128_t minValue, int128_t maxValue) : Value(name) , minValue(minValue) , maxValue(maxValue) { } ~IntRange() {} ValueType type() const override { return ValueType::IntRange; } std::string getRange() const override { return "[" + str(minValue) + ":" + str(maxValue) + "]"; } bool isIntValueInRange(int value) const override { return value >= minValue && value <= maxValue; } int128_t minValue; int128_t maxValue; }; class PointerValue: public Value { public: PointerValue(const std::string &name, ValuePtr data) : Value(name), data(data) {} ValueType type() const override { return ValueType::PointerValue; } std::string getRange() const override { return "*" + data->getRange(); } ValuePtr data; }; class ArrayValue: public Value { public: const int MAXSIZE = 0x100000; ArrayValue(const std::string &name, size_t size) : Value(name) { data.resize((size < MAXSIZE) ? size : MAXSIZE, std::make_shared()); } ValueType type() const override { return ValueType::ArrayValue; } std::string getRange() const override { return "[" + std::to_string(data.size()) + "]"; } void assign(ValuePtr index, ValuePtr value); ValuePtr read(ValuePtr index); std::vector data; }; class StructValue: public Value { public: explicit StructValue(const std::string &name) : Value(name) {} ValueType type() const override { return ValueType::StructValue; } std::string getRange() const override { return name; } ValuePtr getValueOfMember(const std::string &name) const { auto it = member.find(name); return (it == member.end()) ? ValuePtr() : it->second; } std::map member; }; class AddressOfValue: public Value { public: AddressOfValue(const std::string &name, int varId) : Value(name) , varId(varId) {} ValueType type() const override { return ValueType::AddressOfValue; } std::string getRange() const override { return "(&@" + std::to_string(varId); } int varId; }; class BinOpResult : public Value { public: BinOpResult(const std::string &binop, ValuePtr op1, ValuePtr op2) : Value("(" + op1->name + ")" + binop + "(" + op2->name + ")") , binop(binop) , op1(op1) , op2(op2) { auto b1 = std::dynamic_pointer_cast(op1); if (b1) mLeafs = b1->mLeafs; else mLeafs.insert(op1); auto b2 = std::dynamic_pointer_cast(op2); if (b2) mLeafs.insert(b2->mLeafs.begin(), b2->mLeafs.end()); else mLeafs.insert(op2); } ValueType type() const override { return ValueType::BinOpResult; } std::string getRange() const override; void getRange(int128_t *minValue, int128_t *maxValue) const; bool isIntValueInRange(int value) const override; std::string binop; ValuePtr op1; ValuePtr op2; private: int128_t evaluate(int test, const std::map &valueBit) const; int128_t evaluateOperand(int test, const std::map &valueBit, ValuePtr value) const; std::set mLeafs; }; typedef std::function Callback; /** Execute all functions */ void CPPCHECKLIB executeAllFunctions(const Tokenizer *tokenizer, const Settings *settings, const std::vector &callbacks); void executeFunction(const Scope *functionScope, const Tokenizer *tokenizer, const Settings *settings, const std::vector &callbacks); void runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer, const Settings *settings); } #endif // exprengineH