42 #include <unordered_set> 
   76             if (
Token::Match(tok, 
"std :: cout|cerr !!.") && tok->next()->astParent() && tok->next()->astParent()->astOperand1() == tok->next()) {
 
  102     if (str.find(
'+', 1) != std::string::npos)
 
  104     if (str.find(
'w') != std::string::npos || str.find(
'a') != std::string::npos)
 
  106     if (str.find(
'r') != std::string::npos)
 
  115         enum class Operation {NONE, UNIMPORTANT, READ, WRITE, POSITIONING, OPEN, CLOSE, UNKNOWN_OP} lastOperation = Operation::NONE;
 
  117         enum class AppendMode { UNKNOWN_AM, APPEND, APPEND_EX };
 
  118         AppendMode append_mode = AppendMode::UNKNOWN_AM;
 
  119         std::string filename;
 
  124     const std::unordered_set<std::string> whitelist = { 
"clearerr", 
"feof", 
"ferror", 
"fgetpos", 
"ftell", 
"setbuf", 
"setvbuf", 
"ungetc", 
"ungetwc" };
 
  133     std::map<int, Filepointer> filepointers;
 
  139         if (!var || !var->declarationId() || var->isArray() || !
Token::simpleMatch(var->typeStartToken(), 
"FILE *"))
 
  142         if (var->isLocal()) {
 
  143             if (var->nameToken()->strAt(1) == 
"(") 
 
  146                 filepointers.insert(std::make_pair(var->declarationId(), Filepointer(
OpenMode::CLOSED)));
 
  157                 tok = tok->linkAt(1);
 
  160             if (tok->str() == 
"{")
 
  162             else if (tok->str() == 
"}") {
 
  164                 for (std::pair<const int, Filepointer>& filepointer : filepointers) {
 
  165                     if (
indent < filepointer.second.mode_indent) {
 
  166                         filepointer.second.mode_indent = 0;
 
  169                     if (
indent < filepointer.second.op_indent) {
 
  170                         filepointer.second.op_indent = 0;
 
  171                         filepointer.second.lastOperation = Filepointer::Operation::UNKNOWN_OP;
 
  174             } 
else if (tok->str() == 
"return" || tok->str() == 
"continue" || tok->str() == 
"break" || 
mSettings->
library.
isnoreturn(tok)) { 
 
  175                 for (std::pair<const int, Filepointer>& filepointer : filepointers) {
 
  176                     filepointer.second.mode_indent = 0;
 
  178                     filepointer.second.op_indent = 0;
 
  179                     filepointer.second.lastOperation = Filepointer::Operation::UNKNOWN_OP;
 
  182                        (tok->strAt(2) != 
"fopen" && tok->strAt(2) != 
"freopen" && tok->strAt(2) != 
"tmpfile" &&
 
  183                         (windows ? (tok->str() != 
"_wfopen" && tok->str() != 
"_wfreopen") : 
true))) {
 
  184                 const std::map<int, Filepointer>::iterator i = filepointers.find(tok->varId());
 
  185                 if (i != filepointers.end()) {
 
  187                     i->second.lastOperation = Filepointer::Operation::UNKNOWN_OP;
 
  189             } 
else if (
Token::Match(tok, 
"%name% (") && tok->previous() && (!tok->previous()->isName() || 
Token::Match(tok->previous(), 
"return|throw"))) {
 
  191                 const Token* fileTok = 
nullptr;
 
  192                 const Token* fileNameTok = 
nullptr;
 
  193                 Filepointer::Operation operation = Filepointer::Operation::NONE;
 
  195                 if ((tok->str() == 
"fopen" || tok->str() == 
"freopen" || tok->str() == 
"tmpfile" ||
 
  196                      (windows && (tok->str() == 
"_wfopen" || tok->str() == 
"_wfreopen"))) &&
 
  197                     tok->strAt(-1) == 
"=") {
 
  198                     if (tok->str() != 
"tmpfile") {
 
  204                     fileTok = tok->
tokAt(-2);
 
  205                     operation = Filepointer::Operation::OPEN;
 
  207                         fileNameTok = tok->
tokAt(2);
 
  208                 } 
else if (windows && 
Token::Match(tok, 
"fopen_s|freopen_s|_wfopen_s|_wfreopen_s ( & %name%")) {
 
  212                     fileTok = tok->
tokAt(3);
 
  213                     operation = Filepointer::Operation::OPEN;
 
  214                 } 
else if ((tok->str() == 
"rewind" || tok->str() == 
"fseek" || tok->str() == 
"fsetpos" || tok->str() == 
"fflush") ||
 
  215                            (windows && tok->str() == 
"_fseeki64")) {
 
  216                     fileTok = tok->
tokAt(2);
 
  217                     if (printPortability && fileTok && tok->
str() == 
"fflush") {
 
  218                         if (fileTok->
str() == 
"stdin")
 
  221                             const Filepointer& f = filepointers[fileTok->
varId()];
 
  226                     operation = Filepointer::Operation::POSITIONING;
 
  227                 } 
else if (tok->str() == 
"fgetc" || tok->str() == 
"fgetwc" ||
 
  228                            tok->str() == 
"fgets" || tok->str() == 
"fgetws" || tok->str() == 
"fread" ||
 
  229                            tok->str() == 
"fscanf" || tok->str() == 
"fwscanf" || tok->str() == 
"getc" ||
 
  230                            (windows && (tok->str() == 
"fscanf_s" || tok->str() == 
"fwscanf_s"))) {
 
  231                     if (tok->str().find(
"scanf") != std::string::npos)
 
  232                         fileTok = tok->
tokAt(2);
 
  235                     operation = Filepointer::Operation::READ;
 
  236                 } 
else if (tok->str() == 
"fputc" || tok->str() == 
"fputwc" ||
 
  237                            tok->str() == 
"fputs" || tok->str() == 
"fputws" || tok->str() == 
"fwrite" ||
 
  238                            tok->str() == 
"fprintf" || tok->str() == 
"fwprintf" || tok->str() == 
"putcc" ||
 
  239                            (windows && (tok->str() == 
"fprintf_s" || tok->str() == 
"fwprintf_s"))) {
 
  240                     if (tok->str().find(
"printf") != std::string::npos)
 
  241                         fileTok = tok->
tokAt(2);
 
  244                     operation = Filepointer::Operation::WRITE;
 
  245                 } 
else if (tok->str() == 
"fclose") {
 
  246                     fileTok = tok->
tokAt(2);
 
  247                     operation = Filepointer::Operation::CLOSE;
 
  248                 } 
else if (whitelist.find(tok->str()) != whitelist.end()) {
 
  249                     fileTok = tok->
tokAt(2);
 
  250                     if ((tok->str() == 
"ungetc" || tok->str() == 
"ungetwc") && fileTok)
 
  252                     operation = Filepointer::Operation::UNIMPORTANT;
 
  256                         if (!tok->function() || (tok->function()->nestedIn && tok->function()->nestedIn->isClassOrStruct())) {
 
  257                             for (std::pair<const int, Filepointer>& filepointer : filepointers) {
 
  261                                     filepointer.second.mode_indent = 0;
 
  262                                     filepointer.second.op_indent = 
indent;
 
  263                                     filepointer.second.lastOperation = Filepointer::Operation::UNKNOWN_OP;
 
  269                     for (
const Token* tok2 = tok->
tokAt(2); tok2 != end2; tok2 = tok2->
next()) {
 
  270                         if (tok2->varId() && filepointers.find(tok2->varId()) != filepointers.end()) {
 
  272                             operation = Filepointer::Operation::UNKNOWN_OP; 
 
  279                     fileTok = fileTok->
tokAt(2);
 
  281                 if (!fileTok || !fileTok->
varId() || fileTok->
strAt(1) == 
"[")
 
  284                 if (filepointers.find(fileTok->
varId()) == filepointers.end()) { 
 
  288                 Filepointer& f = filepointers[fileTok->
varId()];
 
  291                 case Filepointer::Operation::OPEN:
 
  293                         for (std::map<int, Filepointer>::const_iterator it = filepointers.cbegin(); it != filepointers.cend(); ++it) {
 
  294                             const Filepointer &fptr = it->second;
 
  299                         f.filename = fileNameTok->
str();
 
  303                     if (mode.find(
'a') != std::string::npos) {
 
  305                             f.append_mode = Filepointer::AppendMode::APPEND_EX;
 
  307                             f.append_mode = Filepointer::AppendMode::APPEND;
 
  309                         f.append_mode = Filepointer::AppendMode::UNKNOWN_AM;
 
  312                 case Filepointer::Operation::POSITIONING:
 
  315                     else if (f.append_mode == Filepointer::AppendMode::APPEND && tok->str() != 
"fflush" && printWarnings)
 
  318                 case Filepointer::Operation::READ:
 
  323                     else if (f.lastOperation == Filepointer::Operation::WRITE)
 
  326                 case Filepointer::Operation::WRITE:
 
  331                     else if (f.lastOperation == Filepointer::Operation::READ)
 
  334                 case Filepointer::Operation::CLOSE:
 
  341                 case Filepointer::Operation::UNIMPORTANT:
 
  345                 case Filepointer::Operation::UNKNOWN_OP:
 
  352                 if (operation != Filepointer::Operation::NONE && operation != Filepointer::Operation::UNIMPORTANT) {
 
  354                     f.lastOperation = operation;
 
  358         for (std::pair<const int, Filepointer>& filepointer : filepointers) {
 
  359             filepointer.second.op_indent = 0;
 
  361             filepointer.second.lastOperation = Filepointer::Operation::UNKNOWN_OP;
 
  369                 "fflushOnInputStream", 
"fflush() called on input stream '" + varname + 
"' may result in undefined behaviour on non-linux systems.", 
CWE398, 
Certainty::normal);
 
  375                 "IOWithoutPositioning", 
"Read and write operations without a call to a positioning function (fseek, fsetpos or rewind) or fflush in between result in undefined behaviour.", 
CWE664, 
Certainty::normal);
 
  387                 "writeReadOnlyFile", 
"Write operation on a file that was opened only for reading.", 
CWE664, 
Certainty::normal);
 
  399                 "seekOnAppendedFile", 
"Repositioning operation performed on a file opened in append mode has no effect.", 
CWE398, 
Certainty::normal);
 
  405                 "incompatibleFileOpen", 
"The file '" + filename + 
"' is opened for read and write access at the same time on different streams", 
CWE664, 
Certainty::normal);
 
  422             const Token *formatToken = 
nullptr;
 
  424                 formatToken = tok->
tokAt(2);
 
  425             else if (
Token::Match(tok, 
"sscanf|vsscanf|fscanf|vfscanf (")) {
 
  428                     formatToken = nextArg;
 
  437             const std::string &formatstr(formatToken->
str());
 
  438             for (std::size_t i = 1; i < formatstr.length(); i++) {
 
  439                 if (formatstr[i] == 
'%')
 
  445                 else if (std::isdigit(formatstr[i]) || formatstr[i] == 
'*') {
 
  449                 else if (std::isalpha((
unsigned char)formatstr[i]) || formatstr[i] == 
'[') {
 
  450                     if (formatstr[i] == 
's' || formatstr[i] == 
'[' || formatstr[i] == 
'S' || (formatstr[i] == 
'l' && formatstr[i+1] == 
's'))  
 
  461     const std::string fname = (tok ? tok->
str() : std::string(
"scanf"));
 
  463                 "invalidscanf", fname + 
"() without field width limits can crash with huge input data.\n" +
 
  464                 fname + 
"() without field width limits can crash with huge input data. Add a field width " 
  465                 "specifier to fix this problem.\n" 
  467                 "Sample program that can crash:\n" 
  469                 "#include <stdio.h>\n" 
  473                 "    scanf(\"%s\", c);\n" 
  477                 "Typing in 5 or more characters may make the program crash. The correct usage " 
  478                 "here is 'scanf(\"%4s\", c);', as the maximum field width does not include the " 
  479                 "terminating null byte.\n" 
  480                 "Source: http://linux.die.net/man/3/scanf\n" 
  481                 "Source: http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/libkern/stdio/scanf.c",
 
  492                        const Token *&formatStringTok, 
const Token *&formatArgTok)
 
  494     const Token* argTok = firstArg;
 
  496     for (
int i = 0; i < arg && argTok; ++i)
 
  501         formatStringTok = argTok;
 
  508          (argTok->
variable()->dimensions().size() == 1 &&
 
  509           argTok->
variable()->dimensionKnown(0) &&
 
  510           argTok->
variable()->dimension(0) != 0))) {
 
  512         if (!argTok->
values().empty()) {
 
  513             const std::list<ValueFlow::Value>::const_iterator value = std::find_if(
 
  515             if (value != argTok->
values().cend() && value->isTokValue() && value->tokvalue &&
 
  517                 formatStringTok = value->tokvalue;
 
  526 static inline bool typesMatch(
const std::string& iToTest, 
const std::string& iTypename, 
const std::string& iOptionalPrefix = 
"std::")
 
  528     return (iToTest == iTypename) || (iToTest == iOptionalPrefix + iTypename);
 
  536     logChecker(
"CheckIO::checkWrongPrintfScanfArguments");
 
  540             if (!tok->isName()) 
continue;
 
  542             const Token* argListTok = 
nullptr; 
 
  543             const Token* formatStringTok = 
nullptr; 
 
  546             bool scanf_s = 
false;
 
  547             int formatStringArgNo = -1;
 
  555             if (formatStringArgNo >= 0) {
 
  557                 if (!
findFormat(formatStringArgNo, tok->tokAt(2), formatStringTok, argListTok))
 
  560                 if (
Token::Match(tok->tokAt(2)->nextArgument(), 
"%str%")) {
 
  562                     if (!
findFormat(1, tok->tokAt(2), formatStringTok, argListTok))
 
  566                     if (!
findFormat(2, tok->tokAt(2), formatStringTok, argListTok))
 
  569             } 
else if (isWindows && 
Token::Match(tok, 
"sprintf_s|swprintf_s (")) {
 
  571                 if (
findFormat(1, tok->tokAt(2), formatStringTok, argListTok)) {
 
  572                     if (!formatStringTok)
 
  576                 else if (
findFormat(2, tok->tokAt(2), formatStringTok, argListTok)) {
 
  577                     if (!formatStringTok)
 
  580             } 
else if (isWindows && 
Token::Match(tok, 
"_snprintf_s|_snwprintf_s (")) {
 
  582                 if (
findFormat(2, tok->tokAt(2), formatStringTok, argListTok)) {
 
  583                     if (!formatStringTok)
 
  587                 else if (
findFormat(3, tok->tokAt(2), formatStringTok, argListTok)) {
 
  588                     if (!formatStringTok)
 
  595             if (!formatStringTok)
 
  604                                 const Token * 
const formatStringTok,
 
  605                                 const Token *       argListTok,
 
  611     const std::string &formatString = formatStringTok->
str();
 
  616     bool percent = 
false;
 
  617     const Token* argListTok2 = argListTok;
 
  618     std::set<int> parameterPositionsUsed;
 
  619     for (std::string::const_iterator i = formatString.cbegin(); i != formatString.cend(); ++i) {
 
  622         } 
else if (percent && *i == 
'[') {
 
  623             while (i != formatString.cend()) {
 
  639             if (i == formatString.cend())
 
  641         } 
else if (percent) {
 
  644             bool _continue = 
false;
 
  647             int parameterPosition = 0;
 
  648             bool hasParameterPosition = 
false;
 
  649             while (i != formatString.cend() && *i != 
'[' && !std::isalpha((
unsigned char)*i)) {
 
  659                 } 
else if (std::isdigit(*i)) {
 
  661                 } 
else if (*i == 
'$') {
 
  662                     parameterPosition = strToInt<int>(width);
 
  663                     hasParameterPosition = 
true;
 
  668             auto bracketBeg = formatString.cend();
 
  669             if (i != formatString.cend() && *i == 
'[') {
 
  671                 while (i != formatString.cend()) {
 
  677                 if (scanf_s && !skip) {
 
  684             if (i == formatString.cend())
 
  689             if (scan || *i != 
'm') { 
 
  693                 if (hasParameterPosition) {
 
  694                     if (parameterPositionsUsed.find(parameterPosition) == parameterPositionsUsed.end())
 
  695                         parameterPositionsUsed.insert(parameterPosition);
 
  705                         std::string specifier;
 
  711                                 specifier += (*i == 
's' || bracketBeg == formatString.end()) ? std::string{ 
's' } : std::string{ bracketBeg, i + 1 };
 
  713                                     if (!width.empty()) {
 
  714                                         const int numWidth = strToInt<int>(width);
 
  736                                     if (!width.empty()) {
 
  737                                         const int numWidth = strToInt<int>(width);
 
  766                                         switch (specifier[0]) {
 
  768                                             if (specifier[1] == 
'h') {
 
  775                                             if (specifier[1] == 
'l') {
 
  790                                             if (specifier.find(
"I64") != std::string::npos) {
 
  793                                             } 
else if (specifier.find(
"I32") != std::string::npos) {
 
  846                                         switch (specifier[0]) {
 
  848                                             if (specifier[1] == 
'h') {
 
  855                                             if (specifier[1] == 
'l') {
 
  868                                             if (specifier.find(
"I64") != std::string::npos) {
 
  871                                             } 
else if (specifier.find(
"I32") != std::string::npos) {
 
  923                                         switch (specifier[0]) {
 
  942                                 if ((i+1 != formatString.cend() && *(i+1) == 
'6' &&
 
  943                                      i+2 != formatString.cend() && *(i+2) == 
'4') ||
 
  944                                     (i+1 != formatString.cend() && *(i+1) == 
'3' &&
 
  945                                      i+2 != formatString.cend() && *(i+2) == 
'2')) {
 
  948                                     if ((i+1) != formatString.cend() && !isalpha(*(i+1))) {
 
  956                                     if ((i+1) != formatString.cend() && !isalpha(*(i+1))) {
 
  967                                 if (i+1 != formatString.cend() && *(i+1) == *i)
 
  976                                 if ((i + 1) != formatString.end() && !isalpha(*(i+1))) {
 
  989                     } 
else if (printWarning) {
 
  990                         std::string specifier;
 
  993                             if (i == formatString.end()) {
 
 1027                                         switch (specifier[0]) {
 
 1029                                             if (specifier[1] == 
'h') {
 
 1036                                             if (specifier[1] == 
'l') {
 
 1061                                             if (specifier.find(
"I64") != std::string::npos) {
 
 1064                                             } 
else if (specifier.find(
"I32") != std::string::npos) {
 
 1100                                         switch (specifier[0]) {
 
 1102                                             if (specifier[1] == 
'h') {
 
 1109                                             if (specifier[1] == 
'l') {
 
 1130                                             if (specifier.find(
"I64") != std::string::npos) {
 
 1133                                             } 
else if (specifier.find(
"I32") != std::string::npos) {
 
 1175                                         switch (specifier[0]) {
 
 1177                                             if (specifier[1] == 
'h') {
 
 1184                                             if (specifier[1] == 
'l') {
 
 1209                                             if (specifier.find(
"I64") != std::string::npos) {
 
 1212                                             } 
else if (specifier.find(
"I32") != std::string::npos) {
 
 1265                                 if ((i + 1) != formatString.end() && *(i + 1) == *i) {
 
 1266                                     if ((i + 2) != formatString.end() && !isalpha(*(i + 2))) {
 
 1267                                         std::string modifier;
 
 1269                                         modifier += *(i + 1);
 
 1277                                     if ((i + 1) != formatString.end() && !isalpha(*(i + 1))) {
 
 1278                                         std::string modifier;
 
 1289                                 if ((*(i+1) == 
'3' && *(i+2) == 
'2') ||
 
 1290                                     (*(i+1) == 
'6' && *(i+2) == 
'4')) {
 
 1300                                 if ((i + 1) != formatString.end() && !isalpha(*(i+1))) {
 
 1323     int numFunction = 0;
 
 1324     while (argListTok2) {
 
 1333         for (
const int i : parameterPositionsUsed) {
 
 1334             if ((i == 0) || (i > numFormat))
 
 1340     if ((numFormat + numSecure) != numFunction)
 
 1356         const Token *top = arg;
 
 1357         while (top->
str() == 
"(" && !top->
isCast())
 
 1362         if (valuetype && valuetype->
type >= ValueType::Type::BOOL) {
 
 1393                 if (valuetype->
sign == ValueType::Sign::UNSIGNED)
 
 1395                 else if (valuetype->
sign == ValueType::Sign::SIGNED)
 
 1400             for (
int p = 0; p < valuetype->
pointer; p++)
 
 1416         (
Token::Match(arg, 
"static_cast|reinterpret_cast|const_cast <") &&
 
 1419         if (
Token::Match(arg, 
"static_cast|reinterpret_cast|const_cast")) {
 
 1425         if (arg->
str() == 
"&") {
 
 1430             arg = arg->
tokAt(2);
 
 1433         const Token *varTok = 
nullptr;
 
 1435         for (; tok1; tok1 = tok1->
next()) {
 
 1436             if (tok1->
str() == 
"," || tok1->
str() == 
")") {
 
 1440                         const Function * 
function = varTok->
link()->previous()->function();
 
 1441                         if (
function && function->retType && function->retType->isEnumType()) {
 
 1442                             if (function->retType->classScope->enumType)
 
 1443                                 typeToken = 
function->retType->classScope->enumType;
 
 1449                         } 
else if (
function && function->retDef) {
 
 1460                     if (
function && function->retType && function->retType->isEnumType()) {
 
 1461                         if (function->retType->classScope->enumType)
 
 1462                             typeToken = 
function->retType->classScope->enumType;
 
 1468                     } 
else if (
function && function->retDef) {
 
 1480             if (tok1->
str() == 
"(" || tok1->
str() == 
"{" || tok1->
str() == 
"[")
 
 1481                 tok1 = tok1->
link();
 
 1482             else if (tok1->
link() && tok1->
str() == 
"<")
 
 1483                 tok1 = tok1->
link();
 
 1489                 if (tok1->
next()->
str() == 
"size") {
 
 1505                 } 
else if (tok1->
next()->
str() == 
"empty") {
 
 1507                 } 
else if (tok1->
next()->
str() == 
"c_str") {
 
 1563         while (tempToken->next())
 
 1564             tempToken->deleteNext();
 
 1571     const std::set<std::string> stl_vector = { 
"array", 
"vector" };
 
 1572     const std::set<std::string> stl_string = { 
"string", 
"u16string", 
"u32string", 
"wstring" };
 
 1579     if (variableInfo->isStlType(stl_vector)) {
 
 1580         typeToken = variableInfo->typeStartToken()->tokAt(4);
 
 1584     if (variableInfo->isStlType(stl_string)) {
 
 1585         tempToken = 
new Token(variableInfo->typeStartToken());
 
 1586         if (variableInfo->typeStartToken()->strAt(2) == 
"string")
 
 1587             tempToken->str(
"char");
 
 1589             tempToken->str(
"wchar_t");
 
 1590         typeToken = tempToken;
 
 1593     if (variableInfo->type() && !variableInfo->type()->derivedFrom.empty()) {
 
 1594         const std::vector<Type::BaseInfo>& derivedFrom = variableInfo->type()->derivedFrom;
 
 1596             const Token* nameTok = i.nameTok;
 
 1598                 typeToken = nameTok->
tokAt(4);
 
 1603                 tempToken = 
new Token(variableInfo->typeStartToken());
 
 1604                 if (nameTok->
strAt(2) == 
"string")
 
 1605                     tempToken->str(
"char");
 
 1607                     tempToken->str(
"wchar_t");
 
 1608                 typeToken = tempToken;
 
 1612     } 
else if (variableInfo->type()) {
 
 1613         const Scope * classScope = variableInfo->
type()->classScope;
 
 1616                 if (func.
name() == 
"operator[]") {
 
 1630     "array", 
"bitset", 
"deque", 
"forward_list",
 
 1631     "hash_map", 
"hash_multimap", 
"hash_set",
 
 1632     "list", 
"map", 
"multimap", 
"multiset",
 
 1633     "priority_queue", 
"queue", 
"set", 
"stack",
 
 1634     "unordered_map", 
"unordered_multimap", 
"unordered_multiset", 
"unordered_set", 
"vector" 
 1653                 const Token* nameTok = baseInfo.nameTok;
 
 1654                 if (
Token::Match(nameTok, 
"std :: vector|array|bitset|deque|list|forward_list|map|multimap|multiset|priority_queue|queue|set|stack|hash_map|hash_multimap|hash_set|unordered_map|unordered_multimap|unordered_set|unordered_multiset <")) {
 
 1655                     typeToken = nameTok->
tokAt(4);
 
 1659                     typeToken = nameTok;
 
 1673     if (variableInfo && !_template)
 
 1674         return variableInfo->isArrayOrPointer();
 
 1676     const Token *tok = typeToken;
 
 1679     return tok && tok->
strAt(1) == 
"*";
 
 1684     if (variableInfo->type())
 
 1687     const Token* varTypeTok = typeToken;
 
 1688     if (varTypeTok->
str() == 
"std")
 
 1689         varTypeTok = varTypeTok->
tokAt(2);
 
 1691     return ((variableInfo->isStlStringType() || (varTypeTok->
strAt(1) == 
"<" && varTypeTok->
linkAt(1) && varTypeTok->
linkAt(1)->
strAt(1) != 
"::")) && !variableInfo->isArrayOrPointer());
 
 1697         return (typeToken->isStandardType() || typeToken->next()->isStandardType() || isComplexType());
 
 1699         return (typeToken->isStandardType() || functionInfo->retType || 
Token::Match(typeToken, 
"std :: string|wstring"));
 
 1701     return typeToken->isStandardType() || 
Token::Match(typeToken, 
"std :: string|wstring");
 
 1706     return typeToken && typeToken->isStandardType() && settings.
library.
podtype(typeToken->str());
 
 1710                                              const std::string &functionName,
 
 1718     std::ostringstream errmsg;
 
 1719     errmsg << functionName
 
 1720            << 
" format string requires " 
 1722            << 
" parameter" << (numFormat != 1 ? 
"s" : 
"") << 
" but " 
 1723            << (numFormat > numFunction ? 
"only " : 
"")
 
 1725            << (numFunction != 1 ? 
" are" : 
" is")
 
 1736     std::ostringstream errmsg;
 
 1737     errmsg << functionName << 
": ";
 
 1739         errmsg << 
"parameter positions start at 1, not 0";
 
 1741         errmsg << 
"referencing parameter " << index << 
" while " << numFunction << 
" arguments given";
 
 1751     std::ostringstream errmsg;
 
 1752     errmsg << 
"%" << specifier << 
" in format string (no. " << numFormat << 
") requires a \'";
 
 1753     if (specifier[0] == 
's')
 
 1755     else if (specifier[0] == 
'S')
 
 1756         errmsg << 
"wchar_t";
 
 1757     errmsg << 
" *\' but the argument type is ";
 
 1767     std::ostringstream errmsg;
 
 1768     errmsg << 
"%" << specifier << 
" in format string (no. " << numFormat << 
") requires \'";
 
 1769     if (specifier[0] == 
'h') {
 
 1770         if (specifier[1] == 
'h')
 
 1771             errmsg << (isUnsigned ? 
"unsigned " : 
"") << 
"char";
 
 1773             errmsg << (isUnsigned ? 
"unsigned " : 
"") << 
"short";
 
 1774     } 
else if (specifier[0] == 
'l') {
 
 1775         if (specifier[1] == 
'l')
 
 1776             errmsg << (isUnsigned ? 
"unsigned " : 
"") << 
"long long";
 
 1778             errmsg << (isUnsigned ? 
"unsigned " : 
"") << 
"long";
 
 1779     } 
else if (specifier.find(
"I32") != std::string::npos) {
 
 1780         errmsg << (isUnsigned ? 
"unsigned " : 
"") << 
"__int32";
 
 1781     } 
else if (specifier.find(
"I64") != std::string::npos) {
 
 1782         errmsg << (isUnsigned ? 
"unsigned " : 
"") << 
"__int64";
 
 1783     } 
else if (specifier[0] == 
'I') {
 
 1784         errmsg << (isUnsigned ? 
"size_t" : 
"ptrdiff_t");
 
 1785     } 
else if (specifier[0] == 
'j') {
 
 1787             errmsg << 
"uintmax_t";
 
 1789             errmsg << 
"intmax_t";
 
 1790     } 
else if (specifier[0] == 
'z') {
 
 1791         if (specifier[1] == 
'd' || specifier[1] == 
'i')
 
 1792             errmsg << 
"ssize_t";
 
 1795     } 
else if (specifier[0] == 
't') {
 
 1796         errmsg << (isUnsigned ? 
"unsigned " : 
"") << 
"ptrdiff_t";
 
 1797     } 
else if (specifier[0] == 
'L') {
 
 1798         errmsg << (isUnsigned ? 
"unsigned " : 
"") << 
"long long";
 
 1800         errmsg << (isUnsigned ? 
"unsigned " : 
"") << 
"int";
 
 1802     errmsg << 
" *\' but the argument type is ";
 
 1812     std::ostringstream errmsg;
 
 1813     errmsg << 
"%" << specifier << 
" in format string (no. " << numFormat << 
") requires \'";
 
 1814     if (specifier[0] == 
'l' && specifier[1] != 
'l')
 
 1816     else if (specifier[0] == 
'L')
 
 1817         errmsg << 
"long double";
 
 1820     errmsg << 
" *\' but the argument type is ";
 
 1831     std::ostringstream errmsg;
 
 1832     errmsg << 
"%s in format string (no. " << numFormat << 
") requires \'char *\' but the argument type is ";
 
 1842     std::ostringstream errmsg;
 
 1843     errmsg << 
"%n in format string (no. " << numFormat << 
") requires \'int *\' but the argument type is ";
 
 1853     std::ostringstream errmsg;
 
 1854     errmsg << 
"%p in format string (no. " << numFormat << 
") requires an address but the argument type is ";
 
 1862     if (specifier[0] == 
'l') {
 
 1863         if (specifier[1] == 
'l')
 
 1864             os << (isUnsigned ? 
"unsigned " : 
"") << 
"long long";
 
 1866             os << (isUnsigned ? 
"unsigned " : 
"") << 
"long";
 
 1867     } 
else if (specifier[0] == 
'h') {
 
 1868         if (specifier[1] == 
'h')
 
 1869             os << (isUnsigned ? 
"unsigned " : 
"") << 
"char";
 
 1871             os << (isUnsigned ? 
"unsigned " : 
"") << 
"short";
 
 1872     } 
else if (specifier.find(
"I32") != std::string::npos) {
 
 1873         os << (isUnsigned ? 
"unsigned " : 
"") << 
"__int32";
 
 1874     } 
else if (specifier.find(
"I64") != std::string::npos) {
 
 1875         os << (isUnsigned ? 
"unsigned " : 
"") << 
"__int64";
 
 1876     } 
else if (specifier[0] == 
'I') {
 
 1877         os << (isUnsigned ? 
"size_t" : 
"ptrdiff_t");
 
 1878     } 
else if (specifier[0] == 
'j') {
 
 1883     } 
else if (specifier[0] == 
'z') {
 
 1884         if (specifier[1] == 
'd' || specifier[1] == 
'i')
 
 1888     } 
else if (specifier[0] == 
't') {
 
 1889         os << (isUnsigned ? 
"unsigned " : 
"") << 
"ptrdiff_t";
 
 1890     } 
else if (specifier[0] == 
'L') {
 
 1891         os << (isUnsigned ? 
"unsigned " : 
"") << 
"long long";
 
 1893         os << (isUnsigned ? 
"unsigned " : 
"") << 
"int";
 
 1903     std::ostringstream errmsg;
 
 1904     errmsg << 
"%" << specifier << 
" in format string (no. " << numFormat << 
") requires ";
 
 1906     errmsg << 
" but the argument type is ";
 
 1917     std::ostringstream errmsg;
 
 1918     errmsg << 
"%" << specifier << 
" in format string (no. " << numFormat << 
") requires ";
 
 1920     errmsg << 
" but the argument type is ";
 
 1930     std::ostringstream errmsg;
 
 1931     errmsg << 
"%" << specifier << 
" in format string (no. " << numFormat << 
") requires \'";
 
 1932     if (specifier[0] == 
'L')
 
 1934     errmsg << 
"double\' but the argument type is ";
 
 1952                 os << 
"const wchar_t *";
 
 1954                 os << 
"const char *";
 
 1957                 if (type->
strAt(-1) == 
"const")
 
 1960                     os << type->
str() << 
" ";
 
 1961                     type = type->
next();
 
 1964                     os << type->
str() << 
"::";
 
 1965                     type = type->
tokAt(2);
 
 1967                 os << type->
stringify(
false, 
true, 
false);
 
 1984                 os << 
" {aka " << type->
stringify(
false, 
true, 
false);
 
 1999     std::ostringstream errmsg;
 
 2000     errmsg << 
"'" << modifier << 
"' in format string (no. " << numFormat << 
") is a length modifier and cannot be used without a conversion specifier.";
 
 2007     std::string varname;
 
 2011         varname = var->
name();
 
 2014     std::ostringstream errmsg;
 
 2015     if (arrlen > width) {
 
 2018         errmsg << 
"Width " << width << 
" given in format string (no. " << numFormat << 
") is smaller than destination buffer" 
 2019                << 
" '" << varname << 
"[" << arrlen << 
"]'.";
 
 2022         errmsg << 
"Width " << width << 
" given in format string (no. " << numFormat << 
") is larger than destination buffer '" 
 2023                << varname << 
"[" << arrlen << 
"]', use %" << (specifier == 
"c" ? arrlen : (arrlen - 1)) << specifier << 
" to prevent overflowing it.";
 
bool isUnevaluated(const Token *tok)
static void printfFormatType(std::ostream &os, const std::string &specifier, bool isUnsigned)
static bool findFormat(nonneg int arg, const Token *firstArg, const Token *&formatStringTok, const Token *&formatArgTok)
static const CWE CWE398(398U)
static const CWE CWE704(704U)
static const std::set< std::string > stl_container
static const CWE CWE687(687U)
static const CWE CWE119(119U)
static const CWE CWE910(910U)
static const CWE CWE685(685U)
static bool typesMatch(const std::string &iToTest, const std::string &iTypename, const std::string &iOptionalPrefix="std::")
static const CWE CWE686(686U)
static OpenMode getMode(const std::string &str)
static const CWE CWE664(664U)
const Variable * variableInfo
bool isArrayOrPointer() const
const Function * functionInfo
bool isLibraryType(const Settings &settings) const
bool isStdContainer(const Token *tok)
ArgumentInfo(const Token *arg, const Settings &settings, bool _isCPP)
bool isComplexType() const
bool isStdVectorOrString()
Check input output operations.
void invalidPrintfArgTypeError_uint(const Token *tok, nonneg int numFormat, const std::string &specifier, const ArgumentInfo *argInfo)
void invalidScanf()
scanf can crash if width specifiers are not used
void invalidPrintfArgTypeError_n(const Token *tok, nonneg int numFormat, const ArgumentInfo *argInfo)
void seekOnAppendedFileError(const Token *tok)
void incompatibleFileOpenError(const Token *tok, const std::string &filename)
void invalidPrintfArgTypeError_s(const Token *tok, nonneg int numFormat, const ArgumentInfo *argInfo)
void writeReadOnlyFileError(const Token *tok)
void readWriteOnlyFileError(const Token *tok)
void invalidLengthModifierError(const Token *tok, nonneg int numFormat, const std::string &modifier)
void checkCoutCerrMisusage()
Check for missusage of std::cout
void fflushOnInputStreamError(const Token *tok, const std::string &varname)
void invalidScanfArgTypeError_float(const Token *tok, nonneg int numFormat, const std::string &specifier, const ArgumentInfo *argInfo)
void invalidScanfError(const Token *tok)
static void argumentType(std::ostream &os, const ArgumentInfo *argInfo)
void checkFormatString(const Token *const tok, const Token *const formatStringTok, const Token *argListTok, const bool scan, const bool scanf_s)
void wrongPrintfScanfPosixParameterPositionError(const Token *tok, const std::string &functionName, nonneg int index, nonneg int numFunction)
static Severity getSeverity(const ArgumentInfo *argInfo)
void invalidScanfFormatWidthError(const Token *tok, nonneg int numFormat, int width, const Variable *var, const std::string &specifier)
void invalidPrintfArgTypeError_sint(const Token *tok, nonneg int numFormat, const std::string &specifier, const ArgumentInfo *argInfo)
void coutCerrMisusageError(const Token *tok, const std::string &streamName)
void checkFileUsage()
Check usage of files
void checkWrongPrintfScanfArguments()
Checks type and number of arguments given to functions like printf or scanf
void invalidScanfArgTypeError_int(const Token *tok, nonneg int numFormat, const std::string &specifier, const ArgumentInfo *argInfo, bool isUnsigned)
void invalidPrintfArgTypeError_p(const Token *tok, nonneg int numFormat, const ArgumentInfo *argInfo)
void ioWithoutPositioningError(const Token *tok)
void invalidPrintfArgTypeError_float(const Token *tok, nonneg int numFormat, const std::string &specifier, const ArgumentInfo *argInfo)
void invalidScanfArgTypeError_s(const Token *tok, nonneg int numFormat, const std::string &specifier, const ArgumentInfo *argInfo)
void useClosedFileError(const Token *tok)
void wrongPrintfScanfArgumentsError(const Token *tok, const std::string &functionName, nonneg int numFormat, nonneg int numFunction)
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
const Settings *const mSettings
const Tokenizer *const mTokenizer
void logChecker(const char id[])
log checker
const std::string & name() const
const Token * retDef
function return type token
bool formatstr_function(const Token *ftok) const
bool formatstr_secure(const Token *ftok) const
bool isnoreturn(const Token *ftok) const
int formatstr_argno(const Token *ftok) const
const PodType * podtype(const std::string &name) const
bool isFunctionConst(const std::string &functionName, bool pure) const
bool formatstr_scan(const Token *ftok) const
std::list< Function > functionList
Function * function
function info for this function
const Token * bodyStart
'{' token
const Token * bodyEnd
'}' token
const Scope * functionOf
scope this function belongs to
bool isClassOrStruct() const
This is just a container for general settings so that we don't need to pass individual values to func...
bool isPremiumEnabled(const char id[]) const
Is checker id enabled by premiumArgs.
SimpleEnableGroup< Certainty > certainty
SimpleEnableGroup< Severity > severity
bool isEnabled(T flag) const
const Variable * getVariableFromVarId(nonneg int varId) const
const std::vector< const Variable * > & variableList() const
std::vector< const Scope * > functionScopes
Fast access to function scopes.
The token list that the TokenList generates is a linked-list of this class.
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
const std::string & originalName() const
std::string stringify(const stringifyOptions &options) const
const std::string & strAt(int index) const
void function(const Function *f)
Associate this token with given function.
const ValueType * argumentType() const
const Token * tokAt(int index) const
Token * insertToken(const std::string &tokenStr, const std::string &originalNameStr=emptyString, const std::string ¯oNameStr=emptyString, bool prepend=false)
Insert new token after this token.
Token::Type tokType() const
void astOperand2(Token *tok)
void link(Token *linkToToken)
Create link to given token.
const Token * linkAt(int index) const
std::string strValue() const
This can be called only for tokens that are strings, else the assert() is called.
bool isStandardType() const
void variable(const Variable *v)
Associate this token with given variable.
const std::list< ValueFlow::Value > & values() const
const Token * nextArgument() const
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
void astParent(Token *tok)
bool isC() const
Is the code C.
const SymbolDatabase * getSymbolDatabase() const
bool isCPP() const
Is the code CPP.
std::vector< BaseInfo > derivedFrom
enum ValueType::Type type
nonneg int constness
bit 0=data, bit 1=*, bit 2=**
nonneg int pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
std::string originalTypeName
original type name as written in the source code.
enum ValueType::Sign sign
Information about a member variable.
bool isEnumType() const
Determine whether it's an enumeration type.
bool isStlType() const
Checks if the variable is an STL type ('std::') E.g.
bool isLocal() const
Is variable local.
const Type * type() const
Get Type pointer of known type.
bool isGlobal() const
Is variable global.
const std::string & name() const
Get name string.
MathLib::bigint dimension(nonneg int index_) const
Get array dimension length.
bool isArray() const
Is variable an array.
const Token * typeStartToken() const
Get type start token.
const std::vector< Dimension > & dimensions() const
Get array dimensions.
bool isStatic() const
Is variable static.
Severity
enum class for severity.
@ portability
Portability warning.
@ error
Programming error.
static void indent(std::string &str, const nonneg int indent1, const nonneg int indent2)