@@ -37,6 +37,9 @@ static const CWE CWE252(252U); // Unchecked Return Value
3737static const CWE CWE477 (477U ); // Use of Obsolete Functions
3838static const CWE CWE758 (758U ); // Reliance on Undefined, Unspecified, or Implementation-Defined Behavior
3939static const CWE CWE628 (628U ); // Function Call with Incorrectly Specified Arguments
40+ static const CWE CWE686 (686U ); // Function Call With Incorrect Argument Type
41+ static const CWE CWE687 (687U ); // Function Call With Incorrectly Specified Argument Value
42+ static const CWE CWE688 (688U ); // Function Call With Incorrect Variable or Reference as Argument
4043
4144void CheckFunctions::checkProhibitedFunctions ()
4245{
@@ -284,6 +287,95 @@ void CheckFunctions::mathfunctionCallWarning(const Token *tok, const std::string
284287 reportError (tok, Severity::style, " unpreciseMathCall" , " Expression '" + oldexp + " ' can be replaced by '" + newexp + " ' to avoid loss of precision." , CWE758, false );
285288}
286289
290+ // ---------------------------------------------------------------------------
291+ // memset(p, y, 0 /* bytes to fill */) <- 2nd and 3rd arguments inverted
292+ // ---------------------------------------------------------------------------
293+ void CheckFunctions::memsetZeroBytes ()
294+ {
295+ if (!_settings->isEnabled (Settings::WARNING))
296+ return ;
297+
298+ const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase ();
299+ const std::size_t functions = symbolDatabase->functionScopes .size ();
300+ for (std::size_t i = 0 ; i < functions; ++i) {
301+ const Scope * scope = symbolDatabase->functionScopes [i];
302+ for (const Token* tok = scope->classStart ->next (); tok != scope->classEnd ; tok = tok->next ()) {
303+ if (Token::Match (tok, " memset|wmemset (" ) && (numberOfArguments (tok)==3 )) {
304+ const Token* lastParamTok = getArguments (tok)[2 ];
305+ if (lastParamTok->str () == " 0" )
306+ memsetZeroBytesError (tok);
307+ }
308+ }
309+ }
310+ }
311+
312+ void CheckFunctions::memsetZeroBytesError (const Token *tok)
313+ {
314+ const std::string summary (" memset() called to fill 0 bytes." );
315+ const std::string verbose (summary + " The second and third arguments might be inverted."
316+ " The function memset ( void * ptr, int value, size_t num ) sets the"
317+ " first num bytes of the block of memory pointed by ptr to the specified value." );
318+ reportError (tok, Severity::warning, " memsetZeroBytes" , summary + " \n " + verbose, CWE687, false );
319+ }
320+
321+ void CheckFunctions::memsetInvalid2ndParam ()
322+ {
323+ const bool printPortability = _settings->isEnabled (Settings::PORTABILITY);
324+ const bool printWarning = _settings->isEnabled (Settings::WARNING);
325+ if (!printWarning && !printPortability)
326+ return ;
327+
328+ const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase ();
329+ const std::size_t functions = symbolDatabase->functionScopes .size ();
330+ for (std::size_t i = 0 ; i < functions; ++i) {
331+ const Scope * scope = symbolDatabase->functionScopes [i];
332+ for (const Token* tok = scope->classStart ->next (); tok && (tok != scope->classEnd ); tok = tok->next ()) {
333+ if (!Token::simpleMatch (tok, " memset (" ))
334+ continue ;
335+
336+ const std::vector<const Token *> args = getArguments (tok);
337+ if (args.size () != 3 )
338+ continue ;
339+
340+ // Second parameter is zero literal, i.e. 0.0f
341+ const Token * const secondParamTok = args[1 ];
342+ if (Token::Match (secondParamTok, " %num% ," ) && MathLib::isNullValue (secondParamTok->str ()))
343+ continue ;
344+
345+ // Check if second parameter is a float variable or a float literal != 0.0f
346+ if (printPortability && astIsFloat (secondParamTok,false )) {
347+ memsetFloatError (secondParamTok, secondParamTok->expressionString ());
348+ }
349+
350+ if (printWarning && secondParamTok->isNumber ()) { // Check if the second parameter is a literal and is out of range
351+ const long long int value = MathLib::toLongNumber (secondParamTok->str ());
352+ if (value < -128 || value > 255 ) // FIXME: Use platform char_bits
353+ memsetValueOutOfRangeError (secondParamTok, secondParamTok->str ());
354+ }
355+ }
356+ }
357+ }
358+
359+ void CheckFunctions::memsetFloatError (const Token *tok, const std::string &var_value)
360+ {
361+ const std::string message (" The 2nd memset() argument '" + var_value +
362+ " ' is a float, its representation is implementation defined." );
363+ const std::string verbose (message + " memset() is used to set each byte of a block of memory to a specific value and"
364+ " the actual representation of a floating-point value is implementation defined." );
365+ reportError (tok, Severity::portability, " memsetFloat" , message + " \n " + verbose, CWE688, false );
366+ }
367+
368+ void CheckFunctions::memsetValueOutOfRangeError (const Token *tok, const std::string &value)
369+ {
370+ const std::string message (" The 2nd memset() argument '" + value + " ' doesn't fit into an 'unsigned char'." );
371+ const std::string verbose (message + " The 2nd parameter is passed as an 'int', but the function fills the block of memory using the 'unsigned char' conversion of this value." );
372+ reportError (tok, Severity::warning, " memsetValueOutOfRange" , message + " \n " + verbose, CWE686, false );
373+ }
374+
375+ // ---------------------------------------------------------------------------
376+ // --check-library => warn for unconfigured functions
377+ // ---------------------------------------------------------------------------
378+
287379void CheckFunctions::checkLibraryMatchFunctions ()
288380{
289381 if (!_settings->checkLibrary || !_settings->isEnabled (Settings::INFORMATION))
0 commit comments