| 822 | //--------------------------------------------------------------------------- |
| 823 | |
| 824 | void CheckBufferOverrunImpl::argumentSize() |
| 825 | { |
| 826 | // Check '%type% x[10]' arguments |
| 827 | if (!mSettings.severity.isEnabled(Severity::warning) && !mSettings.isPremiumEnabled("argumentSize")) |
| 828 | return; |
| 829 | |
| 830 | logChecker("CheckBufferOverrun::argumentSize"); // warning |
| 831 | |
| 832 | const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 833 | for (const Scope * const scope : symbolDatabase->functionScopes) { |
| 834 | for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { |
| 835 | if (!tok->function() || !Token::Match(tok, "%name% (")) |
| 836 | continue; |
| 837 | |
| 838 | // If argument is '%type% a[num]' then check bounds against num |
| 839 | const Function *callfunc = tok->function(); |
| 840 | const std::vector<const Token *> callargs = getArguments(tok); |
| 841 | for (nonneg int paramIndex = 0; paramIndex < callargs.size() && paramIndex < callfunc->argCount(); ++paramIndex) { |
| 842 | const Variable* const argument = callfunc->getArgumentVar(paramIndex); |
| 843 | if (!argument || !argument->nameToken() || !argument->isArray()) |
| 844 | continue; |
| 845 | if (!argument->valueType() || !callargs[paramIndex]->valueType()) |
| 846 | continue; |
| 847 | if (argument->valueType()->type != callargs[paramIndex]->valueType()->type) |
| 848 | continue; |
| 849 | const Token * calldata = callargs[paramIndex]; |
| 850 | while (Token::Match(calldata, "::|.")) |
| 851 | calldata = calldata->astOperand2(); |
| 852 | if (!calldata->variable() || !calldata->variable()->isArray()) |
| 853 | continue; |
| 854 | if (calldata->variable()->dimensions().size() != argument->dimensions().size()) |
| 855 | continue; |
| 856 | bool err = false; |
| 857 | for (std::size_t d = 0; d < argument->dimensions().size(); ++d) { |
| 858 | const auto& dim1 = calldata->variable()->dimensions()[d]; |
| 859 | const auto& dim2 = argument->dimensions()[d]; |
| 860 | if (!dim1.known || !dim2.known) |
| 861 | break; |
| 862 | if (dim1.num < dim2.num) |
| 863 | err = true; |
| 864 | } |
| 865 | if (err) |
| 866 | argumentSizeError(tok, tok->str(), paramIndex, callargs[paramIndex]->expressionString(), calldata->variable(), argument); |
| 867 | } |
| 868 | } |
| 869 | } |
| 870 | } |
| 871 | |
| 872 | void CheckBufferOverrunImpl::argumentSizeError(const Token *tok, const std::string &functionName, nonneg int paramIndex, const std::string ¶mExpression, const Variable *paramVar, const Variable *functionArg) |
| 873 | { |
no test coverage detected