Rename safeValues to unknownValues
This commit is contained in:
parent
30f49b2fbd
commit
783f7f1648
|
@ -133,7 +133,7 @@
|
||||||
</attribute>
|
</attribute>
|
||||||
</optional>
|
</optional>
|
||||||
<optional>
|
<optional>
|
||||||
<attribute name="safeValues">
|
<attribute name="unknownValues">
|
||||||
<data type="string">
|
<data type="string">
|
||||||
<param name="pattern">all|([0-9]*:[0-9]*)</param>
|
<param name="pattern">all|([0-9]*:[0-9]*)</param>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
@ -3054,7 +3054,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
||||||
<!-- int rand(void); -->
|
<!-- int rand(void); -->
|
||||||
<function name="rand">
|
<function name="rand">
|
||||||
<use-retval/>
|
<use-retval/>
|
||||||
<returnValue type="int" safeValues="all"/>
|
<returnValue type="int" unknownValues="all"/>
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
</function>
|
</function>
|
||||||
|
|
|
@ -186,11 +186,6 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
|
||||||
else if (std::strcmp(argv[i], "--all-functions-are-safe") == 0)
|
else if (std::strcmp(argv[i], "--all-functions-are-safe") == 0)
|
||||||
mSettings->allFunctionsAreSafe = true;
|
mSettings->allFunctionsAreSafe = true;
|
||||||
|
|
||||||
// Experimental: this flag says that all "safe output values" from functions should be checked.
|
|
||||||
// todo: add proper configuration options
|
|
||||||
else if (std::strcmp(argv[i], "--check-all-safe-return-values") == 0)
|
|
||||||
mSettings->checkAllSafeFunctionReturnValues = true;
|
|
||||||
|
|
||||||
// Enforce language (--language=, -x)
|
// Enforce language (--language=, -x)
|
||||||
else if (std::strncmp(argv[i], "--language=", 11) == 0 || std::strcmp(argv[i], "-x") == 0) {
|
else if (std::strncmp(argv[i], "--language=", 11) == 0 || std::strcmp(argv[i], "-x") == 0) {
|
||||||
std::string str;
|
std::string str;
|
||||||
|
|
|
@ -618,10 +618,11 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
|
||||||
mReturnValueType[name] = type;
|
mReturnValueType[name] = type;
|
||||||
if (const char *container = functionnode->Attribute("container"))
|
if (const char *container = functionnode->Attribute("container"))
|
||||||
mReturnValueContainer[name] = std::atoi(container);
|
mReturnValueContainer[name] = std::atoi(container);
|
||||||
if (const char *safeValues = functionnode->Attribute("safeValues")) {
|
if (const char *unknownReturnValues = functionnode->Attribute("unknownValues")) {
|
||||||
SafeValues sf{LLONG_MIN, LLONG_MAX};
|
if (std::strcmp(unknownReturnValues, "all") == 0) {
|
||||||
if (std::strcmp(safeValues, "all") == 0)
|
std::vector<MathLib::bigint> values{LLONG_MIN, LLONG_MAX};
|
||||||
mReturnSafeValues[name] = sf;
|
mUnknownReturnValues[name] = values;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (functionnodename == "arg") {
|
} else if (functionnodename == "arg") {
|
||||||
const char* argNrString = functionnode->Attribute("nr");
|
const char* argNrString = functionnode->Attribute("nr");
|
||||||
|
@ -1200,17 +1201,12 @@ int Library::returnValueContainer(const Token *ftok) const
|
||||||
return it != mReturnValueContainer.end() ? it->second : -1;
|
return it != mReturnValueContainer.end() ? it->second : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Library::returnValueSafeValues(const Token *ftok, MathLib::bigint *v1, MathLib::bigint *v2) const
|
std::vector<MathLib::bigint> Library::unknownReturnValues(const Token *ftok) const
|
||||||
{
|
{
|
||||||
if (isNotLibraryFunction(ftok))
|
if (isNotLibraryFunction(ftok))
|
||||||
return false;
|
return std::vector<MathLib::bigint>();
|
||||||
const std::map<std::string, SafeValues>::const_iterator it = mReturnSafeValues.find(getFunctionName(ftok));
|
const std::map<std::string, std::vector<MathLib::bigint>>::const_iterator it = mUnknownReturnValues.find(getFunctionName(ftok));
|
||||||
if (it == mReturnSafeValues.end())
|
return (it == mUnknownReturnValues.end()) ? std::vector<MathLib::bigint>() : it->second;
|
||||||
return false;
|
|
||||||
*v1 = it->second.minValue;
|
|
||||||
*v2 = it->second.maxValue;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Library::hasminsize(const Token *ftok) const
|
bool Library::hasminsize(const Token *ftok) const
|
||||||
|
|
|
@ -181,7 +181,7 @@ public:
|
||||||
const std::string& returnValue(const Token *ftok) const;
|
const std::string& returnValue(const Token *ftok) const;
|
||||||
const std::string& returnValueType(const Token *ftok) const;
|
const std::string& returnValueType(const Token *ftok) const;
|
||||||
int returnValueContainer(const Token *ftok) const;
|
int returnValueContainer(const Token *ftok) const;
|
||||||
bool returnValueSafeValues(const Token *ftok, MathLib::bigint *v1, MathLib::bigint *v2) const;
|
std::vector<MathLib::bigint> unknownReturnValues(const Token *ftok) const;
|
||||||
|
|
||||||
bool isnoreturn(const Token *ftok) const;
|
bool isnoreturn(const Token *ftok) const;
|
||||||
bool isnotnoreturn(const Token *ftok) const;
|
bool isnotnoreturn(const Token *ftok) const;
|
||||||
|
@ -542,11 +542,7 @@ private:
|
||||||
std::map<std::string, std::string> mReturnValue;
|
std::map<std::string, std::string> mReturnValue;
|
||||||
std::map<std::string, std::string> mReturnValueType;
|
std::map<std::string, std::string> mReturnValueType;
|
||||||
std::map<std::string, int> mReturnValueContainer;
|
std::map<std::string, int> mReturnValueContainer;
|
||||||
struct SafeValues {
|
std::map<std::string, std::vector<MathLib::bigint>> mUnknownReturnValues;
|
||||||
MathLib::bigint minValue;
|
|
||||||
MathLib::bigint maxValue;
|
|
||||||
};
|
|
||||||
std::map<std::string, SafeValues> mReturnSafeValues;
|
|
||||||
std::map<std::string, bool> mReportErrors;
|
std::map<std::string, bool> mReportErrors;
|
||||||
std::map<std::string, bool> mProcessAfterCode;
|
std::map<std::string, bool> mProcessAfterCode;
|
||||||
std::set<std::string> mMarkupExtensions; // file extensions of markup files
|
std::set<std::string> mMarkupExtensions; // file extensions of markup files
|
||||||
|
|
|
@ -40,7 +40,6 @@ Settings::Settings()
|
||||||
force(false),
|
force(false),
|
||||||
inconclusive(false),
|
inconclusive(false),
|
||||||
allFunctionsAreSafe(false),
|
allFunctionsAreSafe(false),
|
||||||
checkAllSafeFunctionReturnValues(false),
|
|
||||||
inlineSuppressions(false),
|
inlineSuppressions(false),
|
||||||
jobs(1),
|
jobs(1),
|
||||||
jointSuppressionReport(false),
|
jointSuppressionReport(false),
|
||||||
|
|
|
@ -149,8 +149,8 @@ public:
|
||||||
/** @brief Experimental flag that says all functions are "safe" */
|
/** @brief Experimental flag that says all functions are "safe" */
|
||||||
bool allFunctionsAreSafe;
|
bool allFunctionsAreSafe;
|
||||||
|
|
||||||
/** @brief Experimental flag to safety check function output */
|
/** @brief check unknown function return values */
|
||||||
bool checkAllSafeFunctionReturnValues;
|
std::set<std::string> checkUnknownFunctionReturn;
|
||||||
|
|
||||||
/** @brief Is --inline-suppr given? */
|
/** @brief Is --inline-suppr given? */
|
||||||
bool inlineSuppressions;
|
bool inlineSuppressions;
|
||||||
|
|
|
@ -5442,17 +5442,19 @@ static void valueFlowSafeFunctions(TokenList *tokenlist, SymbolDatabase *symbold
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowSafeFunctionReturn(TokenList *tokenlist, const Settings *settings)
|
static void valueFlowUnknownFunctionReturn(TokenList *tokenlist, const Settings *settings)
|
||||||
{
|
{
|
||||||
if (!settings->checkAllSafeFunctionReturnValues)
|
if (settings->checkUnknownFunctionReturn.empty())
|
||||||
return;
|
return;
|
||||||
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
|
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
|
||||||
if (!tok->astParent() || tok->str() != "(")
|
if (!tok->astParent() || tok->str() != "(")
|
||||||
continue;
|
continue;
|
||||||
if (!Token::Match(tok->previous(), "%name%"))
|
if (!Token::Match(tok->previous(), "%name%"))
|
||||||
continue;
|
continue;
|
||||||
MathLib::bigint v1,v2;
|
if (settings->checkUnknownFunctionReturn.find(tok->previous()->str()) == settings->checkUnknownFunctionReturn.end())
|
||||||
if (!settings->library.returnValueSafeValues(tok->previous(), &v1, &v2))
|
continue;
|
||||||
|
std::vector<MathLib::bigint> unknownValues = settings->library.unknownReturnValues(tok->astOperand1());
|
||||||
|
if (unknownValues.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Get min/max values for return type
|
// Get min/max values for return type
|
||||||
|
@ -5461,16 +5463,13 @@ static void valueFlowSafeFunctionReturn(TokenList *tokenlist, const Settings *se
|
||||||
if (!getMinMaxValues(typestr, settings, &minvalue, &maxvalue))
|
if (!getMinMaxValues(typestr, settings, &minvalue, &maxvalue))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto value = [](MathLib::bigint v, MathLib::bigint minvalue, MathLib::bigint maxvalue) {
|
for (MathLib::bigint value : unknownValues) {
|
||||||
if (v < minvalue)
|
if (value < minvalue)
|
||||||
return ValueFlow::Value(minvalue);
|
value = minvalue;
|
||||||
if (v > maxvalue)
|
else if (value > maxvalue)
|
||||||
return ValueFlow::Value(maxvalue);
|
value = maxvalue;
|
||||||
return ValueFlow::Value(v);
|
setTokenValue(const_cast<Token *>(tok), ValueFlow::Value(value), settings);
|
||||||
};
|
}
|
||||||
|
|
||||||
setTokenValue(const_cast<Token *>(tok), value(v1, minvalue, maxvalue), settings);
|
|
||||||
setTokenValue(const_cast<Token *>(tok), value(v2, minvalue, maxvalue), settings);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5540,7 +5539,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase,
|
||||||
valueFlowNumber(tokenlist);
|
valueFlowNumber(tokenlist);
|
||||||
valueFlowString(tokenlist);
|
valueFlowString(tokenlist);
|
||||||
valueFlowArray(tokenlist);
|
valueFlowArray(tokenlist);
|
||||||
valueFlowSafeFunctionReturn(tokenlist, settings);
|
valueFlowUnknownFunctionReturn(tokenlist, settings);
|
||||||
valueFlowGlobalConstVar(tokenlist, settings);
|
valueFlowGlobalConstVar(tokenlist, settings);
|
||||||
valueFlowGlobalStaticVar(tokenlist, settings);
|
valueFlowGlobalStaticVar(tokenlist, settings);
|
||||||
valueFlowPointerAlias(tokenlist);
|
valueFlowPointerAlias(tokenlist);
|
||||||
|
|
|
@ -120,7 +120,8 @@ private:
|
||||||
|
|
||||||
TEST_CASE(valueFlowDynamicBufferSize);
|
TEST_CASE(valueFlowDynamicBufferSize);
|
||||||
|
|
||||||
TEST_CASE(valueFlowSafeFunctions);
|
TEST_CASE(valueFlowAllFunctionParameterValues);
|
||||||
|
TEST_CASE(valueFlowUnknownFunctionReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isNotTokValue(const ValueFlow::Value &val) {
|
static bool isNotTokValue(const ValueFlow::Value &val) {
|
||||||
|
@ -3905,7 +3906,7 @@ private:
|
||||||
ASSERT_EQUALS(true, testValueOfX(code, 4U, 100, ValueFlow::Value::BUFFER_SIZE));
|
ASSERT_EQUALS(true, testValueOfX(code, 4U, 100, ValueFlow::Value::BUFFER_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
void valueFlowSafeFunctions() {
|
void valueFlowAllFunctionParameterValues() {
|
||||||
const char *code;
|
const char *code;
|
||||||
std::list<ValueFlow::Value> values;
|
std::list<ValueFlow::Value> values;
|
||||||
Settings s;
|
Settings s;
|
||||||
|
@ -3921,11 +3922,12 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void valueFlowSafeFunctionReturn() {
|
void valueFlowUnknownFunctionReturn() {
|
||||||
const char *code;
|
const char *code;
|
||||||
std::list<ValueFlow::Value> values;
|
std::list<ValueFlow::Value> values;
|
||||||
Settings s;
|
Settings s;
|
||||||
s.checkAllSafeFunctionReturnValues = true;
|
LOAD_LIB_2(s.library, "std.cfg");
|
||||||
|
s.checkUnknownFunctionReturn.insert("rand");
|
||||||
|
|
||||||
code = "x = rand();";
|
code = "x = rand();";
|
||||||
values = tokenValues(code, "(", &s);
|
values = tokenValues(code, "(", &s);
|
||||||
|
|
Loading…
Reference in New Issue