Library configuration: Enable configuring the direction of arguments. (#1717)

This enhances the library configuration so the direction of function
arguments can be specified (in, out, inout).
isVariableChangedByFunctionCall() uses this information now to avoid
guessing.
This commit is contained in:
Sebastian 2019-03-01 15:47:08 +01:00 committed by GitHub
parent aa4265978c
commit 9a5fcddb5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 9 deletions

View File

@ -163,6 +163,11 @@
<text/> <text/>
</attribute> </attribute>
</optional> </optional>
<optional>
<attribute name="direction">
<ref name="ARG-DIRECTION"/>
</attribute>
</optional>
<interleave> <interleave>
<optional> <optional>
@ -425,6 +430,14 @@
<param name="maxInclusive">20</param> <param name="maxInclusive">20</param>
</data> </data>
</define> </define>
<define name="ARG-DIRECTION">
<choice>
<value>in</value>
<value>out</value>
<value>inout</value>
</choice>
</define>
<define name="DATA-BOOL"> <define name="DATA-BOOL">
<choice> <choice>

View File

@ -52,7 +52,7 @@
<returnValue type="int">arg1&gt;0?arg1:-arg1</returnValue> <returnValue type="int">arg1&gt;0?arg1:-arg1</returnValue>
<noreturn>false</noreturn> <noreturn>false</noreturn>
<leak-ignore/> <leak-ignore/>
<arg nr="1"> <arg nr="1" direction="in">
<not-uninit/> <not-uninit/>
<not-bool/> <not-bool/>
</arg> </arg>
@ -448,10 +448,10 @@
<returnValue type="size_t"/> <returnValue type="size_t"/>
<noreturn>false</noreturn> <noreturn>false</noreturn>
<leak-ignore/> <leak-ignore/>
<arg nr="1"> <arg nr="1" direction="out">
<not-null/> <not-null/>
</arg> </arg>
<arg nr="2"> <arg nr="2" direction="in">
<not-uninit/> <not-uninit/>
</arg> </arg>
<arg nr="3"> <arg nr="3">
@ -4115,7 +4115,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<noreturn>false</noreturn> <noreturn>false</noreturn>
<leak-ignore/> <leak-ignore/>
<formatstr/> <formatstr/>
<arg nr="1"> <arg nr="1" direction="in">
<formatstr/> <formatstr/>
<not-uninit/> <not-uninit/>
</arg> </arg>
@ -4505,12 +4505,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<returnValue type="char *"/> <returnValue type="char *"/>
<noreturn>false</noreturn> <noreturn>false</noreturn>
<leak-ignore/> <leak-ignore/>
<arg nr="1"> <arg nr="1" direction="inout">
<not-null/> <not-null/>
<not-uninit/> <not-uninit/>
<strz/> <strz/>
</arg> </arg>
<arg nr="2"> <arg nr="2" direction="in">
<not-null/> <not-null/>
<not-uninit/> <not-uninit/>
<strz/> <strz/>
@ -5734,12 +5734,12 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<returnValue type="int"/> <returnValue type="int"/>
<noreturn>false</noreturn> <noreturn>false</noreturn>
<leak-ignore/> <leak-ignore/>
<arg nr="1"> <arg nr="1" direction="out">
<not-uninit/> <not-uninit/>
<minsize type="strlen" arg="2"/> <minsize type="strlen" arg="2"/>
</arg> </arg>
<formatstr/> <formatstr/>
<arg nr="2"> <arg nr="2" direction="in">
<formatstr/> <formatstr/>
<not-null/> <not-null/>
<not-uninit/> <not-uninit/>

View File

@ -880,6 +880,16 @@ bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings,
} }
if (!tok->function()) { if (!tok->function()) {
// Check if direction (in, out, inout) is specified in the library configuration and use that
if (!addressOf && settings) {
const Library::ArgumentChecks::Direction argDirection = settings->library.getArgDirection(tok, 1 + argnr);
if (argDirection == Library::ArgumentChecks::Direction::DIR_IN)
return false;
else if (argDirection == Library::ArgumentChecks::Direction::DIR_OUT ||
argDirection == Library::ArgumentChecks::Direction::DIR_INOUT)
return true;
}
// if the library says 0 is invalid // if the library says 0 is invalid
// => it is assumed that parameter is an in parameter (TODO: this is a bad heuristic) // => it is assumed that parameter is an in parameter (TODO: this is a bad heuristic)
if (!addressOf && settings && settings->library.isnullargbad(tok, 1+argnr)) if (!addressOf && settings && settings->library.isnullargbad(tok, 1+argnr))

View File

@ -581,6 +581,17 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
ArgumentChecks &ac = func.argumentChecks[nr]; ArgumentChecks &ac = func.argumentChecks[nr];
ac.optional = functionnode->Attribute("default") != nullptr; ac.optional = functionnode->Attribute("default") != nullptr;
ac.variadic = bVariadicArg; ac.variadic = bVariadicArg;
const char * const argDirection = functionnode->Attribute("direction");
if (argDirection) {
const size_t argDirLen = strlen(argDirection);
if (!strncmp(argDirection, "in", argDirLen)) {
ac.direction = ArgumentChecks::Direction::DIR_IN;
} else if (!strncmp(argDirection, "out", argDirLen)) {
ac.direction = ArgumentChecks::Direction::DIR_OUT;
} else if (!strncmp(argDirection, "inout", argDirLen)) {
ac.direction = ArgumentChecks::Direction::DIR_INOUT;
}
}
for (const tinyxml2::XMLElement *argnode = functionnode->FirstChildElement(); argnode; argnode = argnode->NextSiblingElement()) { for (const tinyxml2::XMLElement *argnode = functionnode->FirstChildElement(); argnode; argnode = argnode->NextSiblingElement()) {
const std::string argnodename = argnode->Name(); const std::string argnodename = argnode->Name();
if (argnodename == "not-bool") if (argnodename == "not-bool")

View File

@ -227,7 +227,8 @@ public:
strz(false), strz(false),
optional(false), optional(false),
variadic(false), variadic(false),
iteratorInfo() { iteratorInfo(),
direction(DIR_UNKNOWN) {
} }
bool notbool; bool notbool;
@ -259,6 +260,9 @@ public:
int arg2; int arg2;
}; };
std::vector<MinSize> minsizes; std::vector<MinSize> minsizes;
enum Direction { DIR_IN, DIR_OUT, DIR_INOUT, DIR_UNKNOWN };
Direction direction;
}; };
@ -320,6 +324,11 @@ public:
return arg ? &arg->minsizes : nullptr; return arg ? &arg->minsizes : nullptr;
} }
ArgumentChecks::Direction getArgDirection(const Token *ftok, int argnr) const {
const ArgumentChecks *arg = getarg(ftok, argnr);
return arg ? arg->direction : ArgumentChecks::Direction::DIR_UNKNOWN;
}
bool markupFile(const std::string &path) const; bool markupFile(const std::string &path) const;
bool processMarkupAfterCode(const std::string &path) const; bool processMarkupAfterCode(const std::string &path) const;