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/>
</attribute>
</optional>
<optional>
<attribute name="direction">
<ref name="ARG-DIRECTION"/>
</attribute>
</optional>
<interleave>
<optional>
@ -426,6 +431,14 @@
</data>
</define>
<define name="ARG-DIRECTION">
<choice>
<value>in</value>
<value>out</value>
<value>inout</value>
</choice>
</define>
<define name="DATA-BOOL">
<choice>
<value>true</value>

View File

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

View File

@ -880,6 +880,16 @@ bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings,
}
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
// => it is assumed that parameter is an in parameter (TODO: this is a bad heuristic)
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];
ac.optional = functionnode->Attribute("default") != nullptr;
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()) {
const std::string argnodename = argnode->Name();
if (argnodename == "not-bool")

View File

@ -227,7 +227,8 @@ public:
strz(false),
optional(false),
variadic(false),
iteratorInfo() {
iteratorInfo(),
direction(DIR_UNKNOWN) {
}
bool notbool;
@ -259,6 +260,9 @@ public:
int arg2;
};
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;
}
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 processMarkupAfterCode(const std::string &path) const;