/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2026 Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
//---------------------------------------------------------------------------
#include "checkio.h"
#include "astutils.h"
#include "errortypes.h"
#include "library.h"
#include "mathlib.h"
#include "platform.h"
#include "settings.h"
#include "symboldatabase.h"
#include "token.h"
#include "tokenize.h"
#include "utils.h"
#include "vfvalue.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//---------------------------------------------------------------------------
// CVE ID used:
static const CWE CWE119(119U); // Improper Restriction of Operations within the Bounds of a Memory Buffer
static const CWE CWE398(398U); // Indicator of Poor Code Quality
static const CWE CWE474(474U); // Use of Function with Inconsistent Implementations
static const CWE CWE664(664U); // Improper Control of a Resource Through its Lifetime
static const CWE CWE685(685U); // Function Call With Incorrect Number of Arguments
static const CWE CWE686(686U); // Function Call With Incorrect Argument Type
static const CWE CWE687(687U); // Function Call With Incorrectly Specified Argument Value
static const CWE CWE704(704U); // Incorrect Type Conversion or Cast
static const CWE CWE910(910U); // Use of Expired File Descriptor
//---------------------------------------------------------------------------
// std::cout isC())
return;
logChecker("CheckIO::checkCoutCerrMisusage"); // c
const SymbolDatabase * const symbolDatabase = mTokenizer->getSymbolDatabase();
for (const Scope * scope : symbolDatabase->functionScopes) {
for (const Token *tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) {
if (Token::Match(tok, "std :: cout|cerr !!.") && tok->next()->astParent() && tok->next()->astParent()->astOperand1() == tok->next()) {
const Token* tok2 = tok->next();
while (tok2->astParent() && tok2->astParent()->str() == " (") &&
Token::Match(arg->linkAt(1)->linkAt(1), ") ,|)"))) {
if (Token::Match(arg, "static_cast|reinterpret_cast|const_cast")) {
typeToken = arg->tokAt(2);
while (typeToken->str() == "const" || typeToken->str() == "extern")
typeToken = typeToken->next();
return;
}
if (arg->str() == "&") {
address = true;
arg = arg->next();
}
while (Token::Match(arg, "%type% ::"))
arg = arg->tokAt(2);
if (!arg || !(arg->tokType() == Token::eVariable || arg->tokType() == Token::eFunction))
return;
const Token *varTok = nullptr;
const Token *tok1 = arg->next();
for (; tok1; tok1 = tok1->next()) {
if (tok1->str() == "," || tok1->str() == ")") {
if (tok1->strAt(-1) == "]") {
varTok = tok1->linkAt(-1)->previous();
if (varTok->str() == ")" && varTok->link()->previous()->tokType() == Token::eFunction) {
const Function * function = varTok->link()->previous()->function();
if (function && function->retType && function->retType->isEnumType()) {
if (function->retType->classScope->enumType)
typeToken = function->retType->classScope->enumType;
else {
tempToken = new Token(tok1);
tempToken->str("int");
typeToken = tempToken;
}
} else if (function && function->retDef) {
typeToken = function->retDef;
while (typeToken->str() == "const" || typeToken->str() == "extern")
typeToken = typeToken->next();
functionInfo = function;
element = true;
}
return;
}
} else if (tok1->strAt(-1) == ")" && tok1->linkAt(-1)->previous()->tokType() == Token::eFunction) {
const Function * function = tok1->linkAt(-1)->previous()->function();
if (function && function->retType && function->retType->isEnumType()) {
if (function->retType->classScope->enumType)
typeToken = function->retType->classScope->enumType;
else {
tempToken = new Token(tok1);
tempToken->str("int");
typeToken = tempToken;
}
} else if (function && function->retDef) {
typeToken = function->retDef;
while (typeToken->str() == "const" || typeToken->str() == "extern")
typeToken = typeToken->next();
functionInfo = function;
element = false;
}
return;
} else
varTok = tok1->previous();
break;
}
if (tok1->str() == "(" || tok1->str() == "{" || tok1->str() == "[")
tok1 = tok1->link();
else if (tok1->link() && tok1->str() == "