diff --git a/cfg/cppcheck-cfg.rng b/cfg/cppcheck-cfg.rng index b87c07152..a6dba3351 100644 --- a/cfg/cppcheck-cfg.rng +++ b/cfg/cppcheck-cfg.rng @@ -474,11 +474,9 @@ - - malloc - calloc - strdup - + + malloc(:[1-5])?|calloc(:[1-5],[1-5])?|strdup(:[1-5])? + diff --git a/lib/library.cpp b/lib/library.cpp index 181d00294..53f4187cd 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -204,14 +204,25 @@ Library::Error Library::load(const tinyxml2::XMLDocument &doc) const char *bufferSize = memorynode->Attribute("buffer-size"); if (!bufferSize) temp.bufferSize = AllocFunc::BufferSize::none; - else if (std::strcmp(bufferSize, "malloc") == 0) - temp.bufferSize = AllocFunc::BufferSize::malloc; - else if (std::strcmp(bufferSize, "calloc") == 0) - temp.bufferSize = AllocFunc::BufferSize::calloc; - else if (std::strcmp(bufferSize, "strdup") == 0) - temp.bufferSize = AllocFunc::BufferSize::strdup; - else - return Error(BAD_ATTRIBUTE_VALUE, bufferSize); + else { + if (std::strncmp(bufferSize, "malloc", 6) == 0) + temp.bufferSize = AllocFunc::BufferSize::malloc; + else if (std::strncmp(bufferSize, "calloc", 6) == 0) + temp.bufferSize = AllocFunc::BufferSize::calloc; + else if (std::strncmp(bufferSize, "strdup", 6) == 0) + temp.bufferSize = AllocFunc::BufferSize::strdup; + else + return Error(BAD_ATTRIBUTE_VALUE, bufferSize); + if (bufferSize[6] == 0) { + temp.bufferSizeArg1 = 1; + temp.bufferSizeArg2 = 2; + } else if (bufferSize[6] == ':' && bufferSize[7] >= '1' && bufferSize[7] <= '5') { + temp.bufferSizeArg1 = bufferSize[7] - '0'; + if (bufferSize[8] == ',' && bufferSize[9] >= '1' && bufferSize[9] <= '5') + temp.bufferSizeArg2 = bufferSize[9] - '0'; + } else + return Error(BAD_ATTRIBUTE_VALUE, bufferSize); + } mAlloc[memorynode->GetText()] = temp; } else if (memorynodename == "dealloc") { diff --git a/lib/library.h b/lib/library.h index 204bebb7e..315215f1a 100644 --- a/lib/library.h +++ b/lib/library.h @@ -75,6 +75,8 @@ public: int arg; enum class BufferSize {none,malloc,calloc,strdup}; BufferSize bufferSize; + int bufferSizeArg1; + int bufferSizeArg2; }; /** get allocation info for function */ diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 6d35dce33..49bc3611c 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -5130,21 +5130,24 @@ static void valueFlowDynamicBufferSize(TokenList *tokenlist, SymbolDatabase *sym const std::vector args = getArguments(rhs->previous()); + const Token * const arg1 = (args.size() >= allocFunc->bufferSizeArg1) ? args[allocFunc->bufferSizeArg1 - 1] : nullptr; + const Token * const arg2 = (args.size() >= allocFunc->bufferSizeArg2) ? args[allocFunc->bufferSizeArg2 - 1] : nullptr; + MathLib::bigint sizeValue = -1; switch (allocFunc->bufferSize) { case Library::AllocFunc::BufferSize::none: break; case Library::AllocFunc::BufferSize::malloc: - if (args.size() == 1 && args[0]->hasKnownIntValue()) - sizeValue = args[0]->getKnownIntValue(); + if (arg1 && arg1->hasKnownIntValue()) + sizeValue = arg1->getKnownIntValue(); break; case Library::AllocFunc::BufferSize::calloc: - if (args.size() == 2 && args[0]->hasKnownIntValue() && args[1]->hasKnownIntValue()) - sizeValue = args[0]->getKnownIntValue() * args[1]->getKnownIntValue(); + if (arg1 && arg2 && arg1->hasKnownIntValue() && arg2->hasKnownIntValue()) + sizeValue = arg1->getKnownIntValue() * arg2->getKnownIntValue(); break; case Library::AllocFunc::BufferSize::strdup: - if (args.size() == 1 && args[0]->hasKnownValue()) { - const ValueFlow::Value &value = args[0]->values().back(); + if (arg1 && arg1->hasKnownValue()) { + const ValueFlow::Value &value = arg1->values().back(); if (value.isTokValue() && value.tokvalue->tokType() == Token::eString) sizeValue = Token::getStrLength(value.tokvalue); }