diff --git a/man/writing-rules-3.docbook b/man/writing-rules-3.docbook
index 787ff9910..29e369d98 100644
--- a/man/writing-rules-3.docbook
+++ b/man/writing-rules-3.docbook
@@ -73,7 +73,10 @@ void CheckOther::divisionByZero()
// Report error
void CheckOther::divisionByZeroError()
{
- reportError(tok, Severity::error, "divisionByZero", "Division by zero");
+ reportError(tok, // location
+ Severity::error, // severity
+ "divisionByZero", // id
+ "Division by zero"); // message
}
The Token::Match matches tokens against
@@ -111,7 +114,8 @@ void CheckOther::divisionByZeroError()
if ( %var% ) { free ( %var% ) ; }
- Any variable name is matched by %var%.
+ The %var% pattern is used to match any variable
+ name.
Here is a C++ function:
@@ -143,10 +147,105 @@ void CheckOther::dealloc()
// Report warning
void CheckOther::deallocWarning()
{
- reportError(tok, Severity::warning, "dealloc", "Redundant condition before deallocation");
+ reportError(tok, // location
+ Severity::warning, // severity
+ "dealloc", // id
+ "Redundant condition"); // message
}
The strAt function is used to fetch strings from the token list. The
- parameter specifies the token offset.
+ parameter specifies the token offset. The result for "tok->tokAt(1)" is
+ the same as for "tok->next()".
+
+
+
+ Validate function parameters
+
+ Sometimes it is known that a function can't handle certain
+ parameters. Here is an example rule that checks that the parameters for
+ strtol or strtoul are valid:
+
+ //---------------------------------------------------------------------------
+// strtol(str, 0, radix) <- radix must be 0 or 2-36
+//---------------------------------------------------------------------------
+
+void CheckOther::invalidFunctionUsage()
+{
+ // Loop through all tokens
+ for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
+ {
+ // Is there a function call for strtol or strtoul?
+ if (!Token::Match(tok, "strtol|strtoul ("))
+ continue;
+
+ // Locate the third parameter of the function call..
+
+ // Counter that counts the parameters.
+ int param = 1;
+
+ // Scan the function call tokens. The "tok->tokAt(2)" returns
+ // the token after the "("
+ for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next())
+ {
+ // If a "(" is found then jump to the corresponding ")"
+ if (tok2->str() == "(")
+ tok2 = tok2->link();
+
+ // End of function call.
+ else if (tok2->str() == ")")
+ break;
+
+ // Found a ",". increment param counter
+ else if (tok2->str() == ",")
+ {
+ ++param;
+
+ // If the param is 3 then check if the parameter is valid
+ if (param == 3)
+ {
+ if (Token::Match(tok2, ", %num% )"))
+ {
+ // convert next token into a number
+ MathLib::bigint radix;
+ radix = MathLib::toLongNumber(tok2->strAt(1));
+
+ // invalid radix?
+ if (!(radix == 0 || (radix >= 2 && radix <= 36)))
+ {
+ dangerousUsageStrtolError(tok2);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+void CheckOther::dangerousUsageStrtolError(const Token *tok)
+{
+ reportError(tok, // location
+ Severity::error, // severity
+ "dangerousUsageStrtol", // id
+ "Invalid radix"); // message
+}
+
+ The link() member function is used to find the corresponding ( ) [ ]
+ or { } token.
+
+ The inner loop is not necessary if you just want to get the last
+ parameter. This code will check if the last parameter is
+ numerical..
+
+ ..
+ // Is there a function call?
+ if (!Token::Match(tok, "do_something ("))
+ continue;
+
+ if (Token::Match(tok->next()->link()->tokAt(-2), "(|, %num% )"))
+ ...
+
+ The pattern (|, can also be written as
+ [(,].