1919#include " checkvaarg.h"
2020
2121#include " astutils.h"
22+ #include " checkimpl.h"
2223#include " errortypes.h"
2324#include " settings.h"
2425#include " symboldatabase.h"
@@ -45,7 +46,23 @@ static const struct CWE CWE664(664U); // Improper Control of a Resource Throug
4546static const struct CWE CWE688 (688U ); // Function Call With Incorrect Variable or Reference as Argument
4647static const struct CWE CWE758 (758U ); // Reliance on Undefined, Unspecified, or Implementation-Defined Behavior
4748
48- void CheckVaarg::va_start_argument ()
49+ class CheckVaargImpl : public CheckImpl
50+ {
51+ public:
52+ CheckVaargImpl (const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
53+ : CheckImpl(tokenizer, settings, errorLogger) {}
54+
55+ void va_start_argument ();
56+ void va_list_usage ();
57+
58+ void wrongParameterTo_va_start_error (const Token *tok, const std::string& paramIsName, const std::string& paramShouldName);
59+ void referenceAs_va_start_error (const Token *tok, const std::string& paramName);
60+ void va_end_missingError (const Token *tok, const std::string& varname);
61+ void va_list_usedBeforeStartedError (const Token *tok, const std::string& varname);
62+ void va_start_subsequentCallsError (const Token *tok, const std::string& varname);
63+ };
64+
65+ void CheckVaargImpl::va_start_argument ()
4966{
5067 const SymbolDatabase* const symbolDatabase = mTokenizer ->getSymbolDatabase ();
5168 const std::size_t functions = symbolDatabase->functionScopes .size ();
@@ -75,13 +92,13 @@ void CheckVaarg::va_start_argument()
7592 }
7693}
7794
78- void CheckVaarg ::wrongParameterTo_va_start_error (const Token *tok, const std::string& paramIsName, const std::string& paramShouldName)
95+ void CheckVaargImpl ::wrongParameterTo_va_start_error (const Token *tok, const std::string& paramIsName, const std::string& paramShouldName)
7996{
8097 reportError (tok, Severity::warning,
8198 " va_start_wrongParameter" , " '" + paramIsName + " ' given to va_start() is not last named argument of the function. Did you intend to pass '" + paramShouldName + " '?" , CWE688, Certainty::normal);
8299}
83100
84- void CheckVaarg ::referenceAs_va_start_error (const Token *tok, const std::string& paramName)
101+ void CheckVaargImpl ::referenceAs_va_start_error (const Token *tok, const std::string& paramName)
85102{
86103 reportError (tok, Severity::error,
87104 " va_start_referencePassed" , " Using reference '" + paramName + " ' as parameter for va_start() results in undefined behaviour." , CWE758, Certainty::normal);
@@ -92,7 +109,7 @@ void CheckVaarg::referenceAs_va_start_error(const Token *tok, const std::string&
92109// Detect va_list usage after va_end()
93110// ---------------------------------------------------------------------------
94111
95- void CheckVaarg ::va_list_usage ()
112+ void CheckVaargImpl ::va_list_usage ()
96113{
97114 if (mSettings ->clang )
98115 return ;
@@ -154,20 +171,37 @@ void CheckVaarg::va_list_usage()
154171 }
155172}
156173
157- void CheckVaarg ::va_end_missingError (const Token *tok, const std::string& varname)
174+ void CheckVaargImpl ::va_end_missingError (const Token *tok, const std::string& varname)
158175{
159176 reportError (tok, Severity::error,
160177 " va_end_missing" , " va_list '" + varname + " ' was opened but not closed by va_end()." , CWE664, Certainty::normal);
161178}
162179
163- void CheckVaarg ::va_list_usedBeforeStartedError (const Token *tok, const std::string& varname)
180+ void CheckVaargImpl ::va_list_usedBeforeStartedError (const Token *tok, const std::string& varname)
164181{
165182 reportError (tok, Severity::error,
166183 " va_list_usedBeforeStarted" , " va_list '" + varname + " ' used before va_start() was called." , CWE664, Certainty::normal);
167184}
168185
169- void CheckVaarg ::va_start_subsequentCallsError (const Token *tok, const std::string& varname)
186+ void CheckVaargImpl ::va_start_subsequentCallsError (const Token *tok, const std::string& varname)
170187{
171188 reportError (tok, Severity::error,
172189 " va_start_subsequentCalls" , " va_start() or va_copy() called subsequently on '" + varname + " ' without va_end() in between." , CWE664, Certainty::normal);
173190}
191+
192+ void CheckVaarg::runChecks (const Tokenizer &tokenizer, ErrorLogger *errorLogger)
193+ {
194+ CheckVaargImpl check (&tokenizer, tokenizer.getSettings (), errorLogger);
195+ check.va_start_argument ();
196+ check.va_list_usage ();
197+ }
198+
199+ void CheckVaarg::getErrorMessages (ErrorLogger *errorLogger, const Settings *settings) const
200+ {
201+ CheckVaargImpl c (nullptr , settings, errorLogger);
202+ c.wrongParameterTo_va_start_error (nullptr , " arg1" , " arg2" );
203+ c.referenceAs_va_start_error (nullptr , " arg1" );
204+ c.va_end_missingError (nullptr , " vl" );
205+ c.va_list_usedBeforeStartedError (nullptr , " vl" );
206+ c.va_start_subsequentCallsError (nullptr , " vl" );
207+ }
0 commit comments