Library: allowed values for the buffer-size attribute: malloc/calloc/strdup
This commit is contained in:
parent
031362ae01
commit
14528bcf25
|
@ -474,9 +474,11 @@
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
<define name="DATA-BUFFER-SIZE">
|
<define name="DATA-BUFFER-SIZE">
|
||||||
<data type="string">
|
<choice>
|
||||||
<param name="pattern">arg-value:[1-3]</param>
|
<value>malloc</value>
|
||||||
</data>
|
<value>calloc</value>
|
||||||
|
<value>strdup</value>
|
||||||
|
</choice>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
<define name="CONTAINER-ACTION">
|
<define name="CONTAINER-ACTION">
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<dealloc>free</dealloc>
|
<dealloc>free</dealloc>
|
||||||
</memory>
|
</memory>
|
||||||
<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>
|
<alloc init="true">xcalloc</alloc>
|
||||||
<dealloc>free</dealloc>
|
<dealloc>free</dealloc>
|
||||||
</memory>
|
</memory>
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
<dealloc>free</dealloc>
|
<dealloc>free</dealloc>
|
||||||
</memory>
|
</memory>
|
||||||
<memory>
|
<memory>
|
||||||
<alloc init="false" buffer-size="arg-value:1">pvalloc</alloc>
|
<alloc init="false" buffer-size="malloc">pvalloc</alloc>
|
||||||
<dealloc>free</dealloc>
|
<dealloc>free</dealloc>
|
||||||
</memory>
|
</memory>
|
||||||
<!-- https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html -->
|
<!-- https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html -->
|
||||||
|
|
|
@ -4364,7 +4364,7 @@ The function 'mktemp' is considered to be dangerous due to race conditions and s
|
||||||
<dealloc>free</dealloc>
|
<dealloc>free</dealloc>
|
||||||
</memory>
|
</memory>
|
||||||
<memory>
|
<memory>
|
||||||
<alloc init="true">strdup</alloc>
|
<alloc init="true" buffer-size="strdup">strdup</alloc>
|
||||||
<alloc init="true">strndup</alloc>
|
<alloc init="true">strndup</alloc>
|
||||||
<alloc init="true">wcsdup</alloc>
|
<alloc init="true">wcsdup</alloc>
|
||||||
<dealloc>free</dealloc>
|
<dealloc>free</dealloc>
|
||||||
|
|
|
@ -7320,10 +7320,10 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
||||||
<arg nr="2"/>
|
<arg nr="2"/>
|
||||||
</function>
|
</function>
|
||||||
<memory>
|
<memory>
|
||||||
<alloc init="false" buffer-size="arg-value:1">malloc</alloc>
|
<alloc init="false" buffer-size="malloc">malloc</alloc>
|
||||||
<alloc init="true">calloc</alloc>
|
<alloc init="true" buffer-size="calloc">calloc</alloc>
|
||||||
<alloc init="false">aligned_alloc</alloc>
|
<alloc init="false">aligned_alloc</alloc>
|
||||||
<alloc init="false">valloc</alloc>
|
<alloc init="false" buffer-size="malloc">valloc</alloc>
|
||||||
<dealloc>free</dealloc>
|
<dealloc>free</dealloc>
|
||||||
</memory>
|
</memory>
|
||||||
<resource>
|
<resource>
|
||||||
|
|
|
@ -202,10 +202,16 @@ Library::Error Library::load(const tinyxml2::XMLDocument &doc)
|
||||||
temp.arg = -1;
|
temp.arg = -1;
|
||||||
|
|
||||||
const char *bufferSize = memorynode->Attribute("buffer-size");
|
const char *bufferSize = memorynode->Attribute("buffer-size");
|
||||||
if (bufferSize && std::strncmp(bufferSize, "arg-value:", 10) == 0)
|
if (!bufferSize)
|
||||||
temp.bufferSizeArgValue = bufferSize[10] - '0';
|
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
|
else
|
||||||
temp.bufferSizeArgValue = -1;
|
return Error(BAD_ATTRIBUTE_VALUE, bufferSize);
|
||||||
|
|
||||||
mAlloc[memorynode->GetText()] = temp;
|
mAlloc[memorynode->GetText()] = temp;
|
||||||
} else if (memorynodename == "dealloc") {
|
} else if (memorynodename == "dealloc") {
|
||||||
|
|
|
@ -73,7 +73,8 @@ public:
|
||||||
struct AllocFunc {
|
struct AllocFunc {
|
||||||
int groupId;
|
int groupId;
|
||||||
int arg;
|
int arg;
|
||||||
int bufferSizeArgValue;
|
enum class BufferSize {none,malloc,calloc,strdup};
|
||||||
|
BufferSize bufferSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** get allocation info for function */
|
/** get allocation info for function */
|
||||||
|
|
|
@ -5125,19 +5125,36 @@ static void valueFlowDynamicBufferSize(TokenList *tokenlist, SymbolDatabase *sym
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Library::AllocFunc *allocFunc = settings->library.alloc(rhs->previous());
|
const Library::AllocFunc *allocFunc = settings->library.alloc(rhs->previous());
|
||||||
if (!allocFunc || allocFunc->bufferSizeArgValue < 1)
|
if (!allocFunc || allocFunc->bufferSize == Library::AllocFunc::BufferSize::none)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const std::vector<const Token *> args = getArguments(rhs->previous());
|
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;
|
continue;
|
||||||
|
|
||||||
const Token *sizeArg = args[allocFunc->bufferSizeArgValue - 1];
|
ValueFlow::Value value(sizeValue);
|
||||||
if (!sizeArg || !sizeArg->hasKnownIntValue())
|
value.errorPath.emplace_back(tok->tokAt(2), "Assign " + tok->strAt(1) + ", buffer with size " + MathLib::toString(sizeValue));
|
||||||
continue;
|
|
||||||
|
|
||||||
ValueFlow::Value value(sizeArg->getKnownIntValue());
|
|
||||||
value.errorPath.emplace_back(tok->tokAt(2), "Assign " + tok->strAt(1) + ", buffer with size " + MathLib::toString(value.intvalue));
|
|
||||||
value.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE;
|
value.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE;
|
||||||
value.setKnown();
|
value.setKnown();
|
||||||
const std::list<ValueFlow::Value> values{value};
|
const std::list<ValueFlow::Value> values{value};
|
||||||
|
|
Loading…
Reference in New Issue