@@ -666,16 +666,20 @@ void CheckIOImpl::wrongfeofUsage(const Token * tok)
666666// printf("", 1); // Too much arguments
667667// ---------------------------------------------------------------------------
668668
669- static bool findFormat (nonneg int arg, const Token *firstArg,
669+ static bool findFormat (nonneg int arg, nonneg int argc, const Token *firstArg,
670670 const Token *&formatStringTok, const Token *&formatArgTok)
671671{
672+ formatArgTok = firstArg;
673+
674+ for (int i = 0 ; i < argc && formatArgTok; ++i)
675+ formatArgTok = formatArgTok->nextArgument ();
676+
672677 const Token* argTok = firstArg;
673678
674679 for (int i = 0 ; i < arg && argTok; ++i)
675680 argTok = argTok->nextArgument ();
676681
677682 if (Token::Match (argTok, " %str% [,)]" )) {
678- formatArgTok = argTok->nextArgument ();
679683 formatStringTok = argTok;
680684 return true ;
681685 }
@@ -686,7 +690,6 @@ static bool findFormat(nonneg int arg, const Token *firstArg,
686690 (argTok->variable ()->dimensions ().size () == 1 &&
687691 argTok->variable ()->dimensionKnown (0 ) &&
688692 argTok->variable ()->dimension (0 ) != 0 ))) {
689- formatArgTok = argTok->nextArgument ();
690693 if (!argTok->values ().empty ()) {
691694 const auto value = std::find_if (
692695 argTok->values ().cbegin (), argTok->values ().cend (), std::mem_fn (&ValueFlow::Value::isTokValue));
@@ -706,6 +709,17 @@ static inline bool typesMatch(const std::string& iToTest, const std::string& iTy
706709 return (iToTest == iTypename) || (iToTest == iOptionalPrefix + iTypename);
707710}
708711
712+ static int getMaxArgNo (const Library::Function *func)
713+ {
714+ const auto &checks = func->argumentChecks ;
715+ return std::max_element (checks.cbegin (), checks.cend (),
716+ [](const std::pair<int , Library::ArgumentChecks> &lhs,
717+ const std::pair<int , Library::ArgumentChecks> &rhs) {
718+ return lhs.first < rhs.first ;
719+ }
720+ )->first ;
721+ }
722+
709723void CheckIOImpl::checkWrongPrintfScanfArguments ()
710724{
711725 const SymbolDatabase *symbolDatabase = mTokenizer ->getSymbolDatabase ();
@@ -723,46 +737,48 @@ void CheckIOImpl::checkWrongPrintfScanfArguments()
723737 bool scan = false ;
724738 bool scanf_s = false ;
725739 int formatStringArgNo = -1 ;
740+ int argc = -1 ;
726741
727742 if (tok->strAt (1 ) == " (" && mSettings .library .formatstr_function (tok)) {
743+ argc = getMaxArgNo (mSettings .library .getFunction (tok));
728744 formatStringArgNo = mSettings .library .formatstr_argno (tok);
729745 scan = mSettings .library .formatstr_scan (tok);
730746 scanf_s = mSettings .library .formatstr_secure (tok);
731747 }
732748
733749 if (formatStringArgNo >= 0 ) {
734750 // formatstring found in library. Find format string and first argument belonging to format string.
735- if (!findFormat (formatStringArgNo, tok->tokAt (2 ), formatStringTok, argListTok))
751+ if (!findFormat (formatStringArgNo, argc, tok->tokAt (2 ), formatStringTok, argListTok))
736752 continue ;
737753 } else if (Token::simpleMatch (tok, " swprintf (" )) {
738754 if (Token::Match (tok->tokAt (2 )->nextArgument (), " %str%" )) {
739755 // Find third parameter and format string
740- if (!findFormat (1 , tok->tokAt (2 ), formatStringTok, argListTok))
756+ if (!findFormat (1 , 2 , tok->tokAt (2 ), formatStringTok, argListTok))
741757 continue ;
742758 } else {
743759 // Find fourth parameter and format string
744- if (!findFormat (2 , tok->tokAt (2 ), formatStringTok, argListTok))
760+ if (!findFormat (2 , 3 , tok->tokAt (2 ), formatStringTok, argListTok))
745761 continue ;
746762 }
747763 } else if (isWindows && Token::Match (tok, " sprintf_s|swprintf_s (" )) {
748764 // template <size_t size> int sprintf_s(char (&buffer)[size], const char *format, ...);
749- if (findFormat (1 , tok->tokAt (2 ), formatStringTok, argListTok)) {
765+ if (findFormat (1 , 2 , tok->tokAt (2 ), formatStringTok, argListTok)) {
750766 if (!formatStringTok)
751767 continue ;
752768 }
753769 // int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...);
754- else if (findFormat (2 , tok->tokAt (2 ), formatStringTok, argListTok)) {
770+ else if (findFormat (2 , 3 , tok->tokAt (2 ), formatStringTok, argListTok)) {
755771 if (!formatStringTok)
756772 continue ;
757773 }
758774 } else if (isWindows && Token::Match (tok, " _snprintf_s|_snwprintf_s (" )) {
759775 // template <size_t size> int _snprintf_s(char (&buffer)[size], size_t count, const char *format, ...);
760- if (findFormat (2 , tok->tokAt (2 ), formatStringTok, argListTok)) {
776+ if (findFormat (2 , 3 , tok->tokAt (2 ), formatStringTok, argListTok)) {
761777 if (!formatStringTok)
762778 continue ;
763779 }
764780 // int _snprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, ...);
765- else if (findFormat (3 , tok->tokAt (2 ), formatStringTok, argListTok)) {
781+ else if (findFormat (3 , 4 , tok->tokAt (2 ), formatStringTok, argListTok)) {
766782 if (!formatStringTok)
767783 continue ;
768784 }
0 commit comments