[CPP-340] Create QL query for function call argument count mismatches.

Update QHELP file, test and test results.
This commit is contained in:
Ziemowit Laski
2019-03-18 16:10:35 -07:00
parent 241994d1f8
commit 0c350dc504
4 changed files with 32 additions and 19 deletions

View File

@@ -5,18 +5,25 @@
<overview>
<p>A function is called with arguments despite having an empty parameter list. This may indicate
that the incorrect function is being called, or that the author misunderstood the function.</p>
<p>A function is called with arguments despite having been <i>declared</i> with an empty parameter list.
In addition, we were either unable to find a <i>definition</i> of the function, or found one with
an incompatible number of parameters.</p>
<p>This may indicate that an incorrect function is being called, or that the signature (parameter list)
of the called function is not known to the author.</p>
<p>In C, a function declared with an empty parameter list <code>()</code> is considered to have an unknown
parameter list, and therefore can be called with any set of arguments. To declare a function
which takes no arguments, you must use <code>(void)</code> as the parameter list in any forward declarations.
In C++, either style of declaration indicates that the function accepts no arguments.</p>
In C++, <code>()</code> means the same as <code>(void)</code>, i.e., indicates that the function accepts no
arguments.</p>
</overview>
<recommendation>
<p>Call the function without arguments, or call a different function that expects the arguments
being passed.</p>
being passed. If possible, change the forward declaration of the <code>()</code>-function to reflect the
arguments being passed, or change the <code>()</code> to <code>(void)</code> to indicate that no arguments
shall be passed.</p>
</recommendation>
<example><sample src="FutileParams.c" />

View File

@@ -12,11 +12,14 @@
import cpp
from Function f, FunctionCall fc
where fc.getTarget() = f
and f.getNumberOfParameters() = 0
and not f.isVarargs()
and fc.getNumberOfArguments() != 0
and not f instanceof BuiltInFunction
and exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() | not fde.isImplicit())
select fc, "This call has arguments, but $@ is not declared with any parameters.", f, f.toString()
from FunctionCall fc, Function f
where f = fc.getTarget() and not f.isVarargs()
/* There must be a mismatch between number of call arguments and number of parameters in some
* non-implicit declaration of Function f
*/
and exists ( FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() | not fde.isImplicit() and fde.getNumberOfParameters() != fc.getNumberOfArguments())
/* There must be no _definition_ of Function f whose number of parameters matches number of call arguments */
and not exists ( FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() | fde.isDefinition() and fde.getNumberOfParameters() = fc.getNumberOfArguments())
select fc

View File

@@ -1,3 +1,4 @@
| test.c:8:3:8:16 | call to declared_empty | This call has arguments, but $@ is not declared with any parameters. | test.c:1:6:1:19 | declared_empty | declared_empty |
| test.c:14:3:14:19 | call to not_yet_declared1 | This call has arguments, but $@ is not declared with any parameters. | test.c:14:3:14:3 | not_yet_declared1 | not_yet_declared1 |
| test.c:14:3:14:19 | call to not_yet_declared1 | This call has arguments, but $@ is not declared with any parameters. | test.c:25:6:25:22 | not_yet_declared1 | not_yet_declared1 |
| test.c:7:3:7:16 | call to declared_empty |
| test.c:16:3:16:19 | call to not_yet_declared1 |
| test.c:19:3:19:29 | call to declared_empty_defined_with |
| test.c:24:3:24:29 | call to declared_empty_defined_with |

View File

@@ -1,7 +1,6 @@
void declared_empty();
void declared_void(void);
void declared_with(int);
void declared_empty_defined_with();
void test() {
declared_empty(); // GOOD
@@ -9,17 +8,20 @@ void test() {
declared_void(); // GOOD
declared_with(1); // GOOD
declared_ellipsis(); // GOOD
declared_ellipsis(2); // GOOD
undeclared(1); // GOOD
not_yet_declared1(1); // BAD
not_yet_declared2(1); // GOOD
declared_empty_defined_with(); // BAD [NOT DETECTED]
declared_empty_defined_with(); // BAD
declared_empty_defined_with(1); // GOOD
int x;
declared_empty_defined_with(&x); // BAD [NOT DETECTED]
declared_empty_defined_with(x, x); // BAD [NOT DETECTED]
declared_empty_defined_with(&x); // GOOD
declared_empty_defined_with(x, x); // BAD
}
void not_yet_declared1();