Skip to content

Commit 1f0376b

Browse files
authored
ValueFlow: Limit the combinations of arguments passed to subfunctions in normal analysis (#4950)
1 parent afb9e43 commit 1f0376b

3 files changed

Lines changed: 22 additions & 6 deletions

File tree

lib/settings.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,12 @@ void Settings::setCheckLevelExhaustive()
229229
{
230230
// Checking can take a little while. ~ 10 times slower than normal analysis is OK.
231231
performanceValueFlowMaxIfCount = -1;
232+
performanceValueFlowMaxSubFunctionArgs = 256;
232233
}
233234

234235
void Settings::setCheckLevelNormal()
235236
{
236237
// Checking should finish in reasonable time.
238+
performanceValueFlowMaxSubFunctionArgs = 8;
237239
performanceValueFlowMaxIfCount = 100;
238240
}

lib/settings.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ class CPPCHECKLIB Settings {
252252
/** @brief --performance-valueflow-max-if-count=C */
253253
int performanceValueFlowMaxIfCount;
254254

255+
/** @brief max number of sets of arguments to pass to subfuncions in valueflow */
256+
int performanceValueFlowMaxSubFunctionArgs;
257+
255258
/** @brief plist output (--plist-output=<dir>) */
256259
std::string plistOutput;
257260

lib/valueflow.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7244,7 +7244,7 @@ struct MultiValueFlowAnalyzer : ValueFlowAnalyzer {
72447244
};
72457245

72467246
template<class Key, class F>
7247-
bool productParams(const std::unordered_map<Key, std::list<ValueFlow::Value>>& vars, F f)
7247+
bool productParams(const Settings* settings, const std::unordered_map<Key, std::list<ValueFlow::Value>>& vars, F f)
72487248
{
72497249
using Args = std::vector<std::unordered_map<Key, ValueFlow::Value>>;
72507250
Args args(1);
@@ -7254,9 +7254,15 @@ bool productParams(const std::unordered_map<Key, std::list<ValueFlow::Value>>& v
72547254
continue;
72557255
args.back()[p.first] = p.second.front();
72567256
}
7257+
bool bail = false;
7258+
int max = 8;
7259+
if (settings)
7260+
max = settings->performanceValueFlowMaxSubFunctionArgs;
72577261
for (const auto& p:vars) {
7258-
if (args.size() > 256)
7259-
return false;
7262+
if (args.size() > max) {
7263+
bail = true;
7264+
break;
7265+
}
72607266
if (p.second.empty())
72617267
continue;
72627268
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
72797285
});
72807286
}
72817287

7288+
if (args.size() > max) {
7289+
bail = true;
7290+
args.resize(max);
7291+
}
7292+
72827293
for (const auto& arg:args) {
72837294
if (arg.empty())
72847295
continue;
@@ -7290,7 +7301,7 @@ bool productParams(const std::unordered_map<Key, std::list<ValueFlow::Value>>& v
72907301
continue;
72917302
f(arg);
72927303
}
7293-
return true;
7304+
return !bail;
72947305
}
72957306

72967307
static void valueFlowInjectParameter(TokenList* tokenlist,
@@ -7300,7 +7311,7 @@ static void valueFlowInjectParameter(TokenList* tokenlist,
73007311
const Scope* functionScope,
73017312
const std::unordered_map<const Variable*, std::list<ValueFlow::Value>>& vars)
73027313
{
7303-
const bool r = productParams(vars, [&](const std::unordered_map<const Variable*, ValueFlow::Value>& arg) {
7314+
const bool r = productParams(&settings, vars, [&](const std::unordered_map<const Variable*, ValueFlow::Value>& arg) {
73047315
MultiValueFlowAnalyzer a(arg, tokenlist, &settings, symboldatabase);
73057316
valueFlowGenericForward(const_cast<Token*>(functionScope->bodyStart), functionScope->bodyEnd, a, settings);
73067317
});
@@ -7431,7 +7442,7 @@ static void valueFlowLibraryFunction(Token *tok, const std::string &returnValue,
74317442
}
74327443
if (returnValue.find("arg") != std::string::npos && argValues.empty())
74337444
return;
7434-
productParams(argValues, [&](const std::unordered_map<nonneg int, ValueFlow::Value>& arg) {
7445+
productParams(settings, argValues, [&](const std::unordered_map<nonneg int, ValueFlow::Value>& arg) {
74357446
ValueFlow::Value value = evaluateLibraryFunction(arg, returnValue, settings);
74367447
if (value.isUninitValue())
74377448
return;

0 commit comments

Comments
 (0)