| 1265 | } |
| 1266 | |
| 1267 | void CheckStlImpl::stlOutOfBounds() |
| 1268 | { |
| 1269 | logChecker("CheckStl::stlOutOfBounds"); |
| 1270 | |
| 1271 | const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 1272 | |
| 1273 | // Scan through all scopes.. |
| 1274 | for (const Scope &scope : symbolDatabase->scopeList) { |
| 1275 | const Token* tok = scope.classDef; |
| 1276 | // only interested in conditions |
| 1277 | if ((!scope.isLoopScope() && scope.type != ScopeType::eIf) || !tok) |
| 1278 | continue; |
| 1279 | |
| 1280 | const Token *condition = nullptr; |
| 1281 | if (scope.type == ScopeType::eFor) { |
| 1282 | if (Token::simpleMatch(tok->next()->astOperand2(), ";") && Token::simpleMatch(tok->next()->astOperand2()->astOperand2(), ";")) |
| 1283 | condition = tok->next()->astOperand2()->astOperand2()->astOperand1(); |
| 1284 | } else if (Token::simpleMatch(tok, "do {") && Token::simpleMatch(tok->linkAt(1), "} while (")) |
| 1285 | condition = tok->linkAt(1)->tokAt(2)->astOperand2(); |
| 1286 | else |
| 1287 | condition = tok->next()->astOperand2(); |
| 1288 | |
| 1289 | if (!condition) |
| 1290 | continue; |
| 1291 | |
| 1292 | std::vector<const Token *> conds; |
| 1293 | |
| 1294 | visitAstNodes(condition, |
| 1295 | [&](const Token *cond) { |
| 1296 | if (Token::Match(cond, "%oror%|&&")) |
| 1297 | return ChildrenToVisit::op1_and_op2; |
| 1298 | if (cond->isComparisonOp()) |
| 1299 | conds.emplace_back(cond); |
| 1300 | return ChildrenToVisit::none; |
| 1301 | }); |
| 1302 | |
| 1303 | for (const Token *cond : conds) { |
| 1304 | const Token *vartok; |
| 1305 | const Token *containerToken; |
| 1306 | // check in the ast that cond is of the form "%var% <= %var% . %name% ( )" |
| 1307 | if (cond->str() == "<=" && Token::Match(cond->astOperand1(), "%var%") && |
| 1308 | cond->astOperand2()->str() == "(" && cond->astOperand2()->astOperand1()->str() == "." && |
| 1309 | Token::Match(cond->astOperand2()->astOperand1()->astOperand1(), "%var%") && |
| 1310 | Token::Match(cond->astOperand2()->astOperand1()->astOperand2(), "%name%")) { |
| 1311 | vartok = cond->astOperand1(); |
| 1312 | containerToken = cond->next(); |
| 1313 | } else { |
| 1314 | continue; |
| 1315 | } |
| 1316 | |
| 1317 | if (containerToken->hasKnownValue(ValueFlow::Value::ValueType::CONTAINER_SIZE)) |
| 1318 | continue; |
| 1319 | |
| 1320 | // Is it a array like container? |
| 1321 | const Library::Container* container = containerToken->valueType() ? containerToken->valueType()->container : nullptr; |
| 1322 | if (!container) |
| 1323 | continue; |
| 1324 | if (container->getYield(containerToken->strAt(2)) != Library::Container::Yield::SIZE) |
no test coverage detected