Rename safeValues to unknownValues

This commit is contained in:
Daniel Marjamäki 2019-07-11 16:05:34 +02:00
parent 30f49b2fbd
commit 783f7f1648
9 changed files with 35 additions and 48 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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),

View File

@ -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;

View File

@ -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);

View File

@ -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);