ValueFlow: Limit the combinations of arguments passed to subfunctions in normal analysis (#4950)
This commit is contained in:
parent
afb9e43f2a
commit
1f0376b32d
|
@ -229,10 +229,12 @@ void Settings::setCheckLevelExhaustive()
|
|||
{
|
||||
// Checking can take a little while. ~ 10 times slower than normal analysis is OK.
|
||||
performanceValueFlowMaxIfCount = -1;
|
||||
performanceValueFlowMaxSubFunctionArgs = 256;
|
||||
}
|
||||
|
||||
void Settings::setCheckLevelNormal()
|
||||
{
|
||||
// Checking should finish in reasonable time.
|
||||
performanceValueFlowMaxSubFunctionArgs = 8;
|
||||
performanceValueFlowMaxIfCount = 100;
|
||||
}
|
||||
|
|
|
@ -252,6 +252,9 @@ public:
|
|||
/** @brief --performance-valueflow-max-if-count=C */
|
||||
int performanceValueFlowMaxIfCount;
|
||||
|
||||
/** @brief max number of sets of arguments to pass to subfuncions in valueflow */
|
||||
int performanceValueFlowMaxSubFunctionArgs;
|
||||
|
||||
/** @brief plist output (--plist-output=<dir>) */
|
||||
std::string plistOutput;
|
||||
|
||||
|
|
|
@ -7244,7 +7244,7 @@ struct MultiValueFlowAnalyzer : ValueFlowAnalyzer {
|
|||
};
|
||||
|
||||
template<class Key, class F>
|
||||
bool productParams(const std::unordered_map<Key, std::list<ValueFlow::Value>>& vars, F f)
|
||||
bool productParams(const Settings* settings, const std::unordered_map<Key, std::list<ValueFlow::Value>>& vars, F f)
|
||||
{
|
||||
using Args = std::vector<std::unordered_map<Key, ValueFlow::Value>>;
|
||||
Args args(1);
|
||||
|
@ -7254,9 +7254,15 @@ bool productParams(const std::unordered_map<Key, std::list<ValueFlow::Value>>& v
|
|||
continue;
|
||||
args.back()[p.first] = p.second.front();
|
||||
}
|
||||
bool bail = false;
|
||||
int max = 8;
|
||||
if (settings)
|
||||
max = settings->performanceValueFlowMaxSubFunctionArgs;
|
||||
for (const auto& p:vars) {
|
||||
if (args.size() > 256)
|
||||
return false;
|
||||
if (args.size() > max) {
|
||||
bail = true;
|
||||
break;
|
||||
}
|
||||
if (p.second.empty())
|
||||
continue;
|
||||
std::for_each(std::next(p.second.begin()), p.second.end(), [&](const ValueFlow::Value& value) {
|
||||
|
@ -7279,6 +7285,11 @@ bool productParams(const std::unordered_map<Key, std::list<ValueFlow::Value>>& v
|
|||
});
|
||||
}
|
||||
|
||||
if (args.size() > max) {
|
||||
bail = true;
|
||||
args.resize(max);
|
||||
}
|
||||
|
||||
for (const auto& arg:args) {
|
||||
if (arg.empty())
|
||||
continue;
|
||||
|
@ -7290,7 +7301,7 @@ bool productParams(const std::unordered_map<Key, std::list<ValueFlow::Value>>& v
|
|||
continue;
|
||||
f(arg);
|
||||
}
|
||||
return true;
|
||||
return !bail;
|
||||
}
|
||||
|
||||
static void valueFlowInjectParameter(TokenList* tokenlist,
|
||||
|
@ -7300,7 +7311,7 @@ static void valueFlowInjectParameter(TokenList* tokenlist,
|
|||
const Scope* functionScope,
|
||||
const std::unordered_map<const Variable*, std::list<ValueFlow::Value>>& vars)
|
||||
{
|
||||
const bool r = productParams(vars, [&](const std::unordered_map<const Variable*, ValueFlow::Value>& arg) {
|
||||
const bool r = productParams(&settings, vars, [&](const std::unordered_map<const Variable*, ValueFlow::Value>& arg) {
|
||||
MultiValueFlowAnalyzer a(arg, tokenlist, &settings, symboldatabase);
|
||||
valueFlowGenericForward(const_cast<Token*>(functionScope->bodyStart), functionScope->bodyEnd, a, settings);
|
||||
});
|
||||
|
@ -7431,7 +7442,7 @@ static void valueFlowLibraryFunction(Token *tok, const std::string &returnValue,
|
|||
}
|
||||
if (returnValue.find("arg") != std::string::npos && argValues.empty())
|
||||
return;
|
||||
productParams(argValues, [&](const std::unordered_map<nonneg int, ValueFlow::Value>& arg) {
|
||||
productParams(settings, argValues, [&](const std::unordered_map<nonneg int, ValueFlow::Value>& arg) {
|
||||
ValueFlow::Value value = evaluateLibraryFunction(arg, returnValue, settings);
|
||||
if (value.isUninitValue())
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue