Library: allowed values for the buffer-size attribute: malloc/calloc/strdup

This commit is contained in:
Daniel Marjamäki 2019-03-20 06:46:55 +01:00
parent 031362ae01
commit 14528bcf25
7 changed files with 47 additions and 21 deletions

View File

@ -474,9 +474,11 @@
</define>
<define name="DATA-BUFFER-SIZE">
<data type="string">
<param name="pattern">arg-value:[1-3]</param>
</data>
<choice>
<value>malloc</value>
<value>calloc</value>
<value>strdup</value>
</choice>
</define>
<define name="CONTAINER-ACTION">

View File

@ -9,7 +9,7 @@
<dealloc>free</dealloc>
</memory>
<memory>
<alloc init="false" buffer-size="arg-value:1">xmalloc</alloc>
<alloc init="false" buffer-size="malloc">xmalloc</alloc>
<alloc init="true">xcalloc</alloc>
<dealloc>free</dealloc>
</memory>
@ -19,7 +19,7 @@
<dealloc>free</dealloc>
</memory>
<memory>
<alloc init="false" buffer-size="arg-value:1">pvalloc</alloc>
<alloc init="false" buffer-size="malloc">pvalloc</alloc>
<dealloc>free</dealloc>
</memory>
<!-- https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html -->

View File

@ -4364,7 +4364,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
<dealloc>free</dealloc>
</memory>
<memory>
<alloc init="true">strdup</alloc>
<alloc init="true" buffer-size="strdup">strdup</alloc>
<alloc init="true">strndup</alloc>
<alloc init="true">wcsdup</alloc>
<dealloc>free</dealloc>

View File

@ -7320,10 +7320,10 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<arg nr="2"/>
</function>
<memory>
<alloc init="false" buffer-size="arg-value:1">malloc</alloc>
<alloc init="true">calloc</alloc>
<alloc init="false" buffer-size="malloc">malloc</alloc>
<alloc init="true" buffer-size="calloc">calloc</alloc>
<alloc init="false">aligned_alloc</alloc>
<alloc init="false">valloc</alloc>
<alloc init="false" buffer-size="malloc">valloc</alloc>
<dealloc>free</dealloc>
</memory>
<resource>

View File

@ -202,10 +202,16 @@ Library::Error Library::load(const tinyxml2::XMLDocument &doc)
temp.arg = -1;
const char *bufferSize = memorynode->Attribute("buffer-size");
if (bufferSize && std::strncmp(bufferSize, "arg-value:", 10) == 0)
temp.bufferSizeArgValue = bufferSize[10] - '0';
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
temp.bufferSizeArgValue = -1;
return Error(BAD_ATTRIBUTE_VALUE, bufferSize);
mAlloc[memorynode->GetText()] = temp;
} else if (memorynodename == "dealloc") {

View File

@ -73,7 +73,8 @@ public:
struct AllocFunc {
int groupId;
int arg;
int bufferSizeArgValue;
enum class BufferSize {none,malloc,calloc,strdup};
BufferSize bufferSize;
};
/** get allocation info for function */

View File

@ -5125,19 +5125,36 @@ static void valueFlowDynamicBufferSize(TokenList *tokenlist, SymbolDatabase *sym
continue;
const Library::AllocFunc *allocFunc = settings->library.alloc(rhs->previous());
if (!allocFunc || allocFunc->bufferSizeArgValue < 1)
if (!allocFunc || allocFunc->bufferSize == Library::AllocFunc::BufferSize::none)
continue;
const std::vector<const Token *> args = getArguments(rhs->previous());
if (args.size() < allocFunc->bufferSizeArgValue)
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();
break;
case Library::AllocFunc::BufferSize::calloc:
if (args.size() == 2 && args[0]->hasKnownIntValue() && args[1]->hasKnownIntValue())
sizeValue = args[0]->getKnownIntValue() * args[1]->getKnownIntValue();
break;
case Library::AllocFunc::BufferSize::strdup:
if (args.size() == 1 && args[0]->hasKnownValue()) {
const ValueFlow::Value &value = args[0]->values().back();
if (value.isTokValue() && value.tokvalue->tokType() == Token::eString)
sizeValue = Token::getStrLength(value.tokvalue);
}
break;
};
if (sizeValue < 0)
continue;
const Token *sizeArg = args[allocFunc->bufferSizeArgValue - 1];
if (!sizeArg || !sizeArg->hasKnownIntValue())
continue;
ValueFlow::Value value(sizeArg->getKnownIntValue());
value.errorPath.emplace_back(tok->tokAt(2), "Assign " + tok->strAt(1) + ", buffer with size " + MathLib::toString(value.intvalue));
ValueFlow::Value value(sizeValue);
value.errorPath.emplace_back(tok->tokAt(2), "Assign " + tok->strAt(1) + ", buffer with size " + MathLib::toString(sizeValue));
value.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE;
value.setKnown();
const std::list<ValueFlow::Value> values{value};