| 6909 | }; |
| 6910 | |
| 6911 | static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings) |
| 6912 | { |
| 6913 | auto getBufferSizeFromAllocFunc = [&](const Token* funcTok) -> MathLib::bigint { |
| 6914 | MathLib::bigint sizeValue = -1; |
| 6915 | const Library::AllocFunc* allocFunc = settings.library.getAllocFuncInfo(funcTok); |
| 6916 | if (!allocFunc) |
| 6917 | allocFunc = settings.library.getReallocFuncInfo(funcTok); |
| 6918 | if (!allocFunc || allocFunc->bufferSize == Library::AllocFunc::BufferSize::none) |
| 6919 | return sizeValue; |
| 6920 | |
| 6921 | const std::vector<const Token*> args = getArguments(funcTok); |
| 6922 | |
| 6923 | const Token* const arg1 = (args.size() >= allocFunc->bufferSizeArg1) ? args[allocFunc->bufferSizeArg1 - 1] : nullptr; |
| 6924 | const Token* const arg2 = (args.size() >= allocFunc->bufferSizeArg2) ? args[allocFunc->bufferSizeArg2 - 1] : nullptr; |
| 6925 | |
| 6926 | switch (allocFunc->bufferSize) { |
| 6927 | case Library::AllocFunc::BufferSize::none: |
| 6928 | break; |
| 6929 | case Library::AllocFunc::BufferSize::malloc: |
| 6930 | if (arg1 && arg1->hasKnownIntValue()) |
| 6931 | sizeValue = arg1->getKnownIntValue(); |
| 6932 | break; |
| 6933 | case Library::AllocFunc::BufferSize::calloc: |
| 6934 | if (arg1 && arg2 && arg1->hasKnownIntValue() && arg2->hasKnownIntValue()) |
| 6935 | sizeValue = arg1->getKnownIntValue() * arg2->getKnownIntValue(); |
| 6936 | break; |
| 6937 | case Library::AllocFunc::BufferSize::strdup: |
| 6938 | if (arg1 && arg1->hasKnownValue()) { |
| 6939 | const ValueFlow::Value& value = arg1->values().back(); |
| 6940 | if (value.isTokValue() && value.tokvalue->tokType() == Token::eString) |
| 6941 | sizeValue = Token::getStrLength(value.tokvalue) + 1; // Add one for the null terminator |
| 6942 | } |
| 6943 | break; |
| 6944 | } |
| 6945 | return sizeValue; |
| 6946 | }; |
| 6947 | |
| 6948 | auto getBufferSizeFromNew = [&](const Token* newTok) -> MathLib::bigint { |
| 6949 | MathLib::bigint sizeValue = -1, numElem = -1; |
| 6950 | |
| 6951 | if (newTok && newTok->astOperand1()) { // number of elements |
| 6952 | const Token* bracTok = nullptr, *typeTok = nullptr; |
| 6953 | if (newTok->astOperand1()->str() == "[") |
| 6954 | bracTok = newTok->astOperand1(); |
| 6955 | else if (Token::Match(newTok->astOperand1(), "(|{")) { |
| 6956 | if (newTok->astOperand1()->astOperand1() && newTok->astOperand1()->astOperand1()->str() == "[") |
| 6957 | bracTok = newTok->astOperand1()->astOperand1(); |
| 6958 | else |
| 6959 | typeTok = newTok->astOperand1()->astOperand1(); |
| 6960 | } |
| 6961 | else |
| 6962 | typeTok = newTok->astOperand1(); |
| 6963 | if (bracTok && bracTok->astOperand2() && bracTok->astOperand2()->hasKnownIntValue()) |
| 6964 | numElem = bracTok->astOperand2()->getKnownIntValue(); |
| 6965 | else if (Token::Match(typeTok, "%type%")) |
| 6966 | numElem = 1; |
| 6967 | } |
| 6968 |
no test coverage detected