[CPP-340] Add a fourth query, ArgumentsToImplicit.ql, to deal strictly with implicitly declared

functions.  TooManyArguments.ql will now deal with explicitly declared/prototyped functions.
This commit is contained in:
Ziemowit Laski
2019-04-18 17:56:41 -07:00
parent 65130c40ab
commit 62b030d27f
7 changed files with 94 additions and 2 deletions

View File

@@ -0,0 +1,9 @@
void calls() {
undeclared(); // GOOD
undeclared(1); // BAD
undeclared(1, 2); // BAD
}

View File

@@ -0,0 +1,29 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>An implicitly-declared function is called with arguments.</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, an implicitly declared function is assumed to accept no arguments. Providing
these arguments incurs an unneeded computational overhead, both
in terms of time and of additional stack space.</p>
</overview>
<recommendation>
<p>Call the function without any arguments.</p>
</recommendation>
<example><sample src="ArgumentsToImplicit.c" />
</example>
<references>
<li>SEI CERT C Coding Standard: <a href="https://wiki.sei.cmu.edu/confluence/display/c/DCL20-C.+Explicitly+specify+void+when+a+function+accepts+no+arguments"> DCL20-C. Explicitly specify void when a function accepts no arguments </a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,49 @@
/**
* @name Call with arguments to an implicitly declared function
* @description A function call passed arguments even though the
* function in question is only implicitly declared (and
* hence accepting no arguments). This may indicate
* that the code does not follow the author's intent.
* @kind problem
* @problem.severity warning
* @precision very-high
* @id cpp/arguments-to-implicit
* @tags correctness
* maintainability
*/
import cpp
// True if there is no explicit definition of the function
predicate hasNoExplicitDecl(Function f) {
not exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
not fde.isImplicit()
)
}
// True if this file (or header) was compiled as a C file
predicate isCompiledAsC(Function f) {
exists(File file | file.compiledAsC() |
file = f.getFile() or file.getAnIncludedFile+() = f.getFile()
)
}
predicate isWhitelisted(Function f) {
f instanceof BuiltInFunction
or
// The following list can be expanded as the need arises
exists(string name | name = f.getName() |
name = "static_assert" or
name = "_Static_assert" or
name = "strptime"
)
}
from FunctionCall fc, Function f
where
f = fc.getTarget() and
hasNoExplicitDecl(f) and
isCompiledAsC(f) and
not isWhitelisted(f) and
fc.getNumberOfArguments() > 0
select fc, "This call to an implicitly declared function $@ has arguments.", f, f.toString()

View File

@@ -14,9 +14,13 @@
import cpp
// True if function was ()-declared, but not (void)-declared or K&R-defined
// or implicitly declared (i.e., lacking a prototype)
predicate hasZeroParamDecl(Function f) {
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
not fde.hasVoidParamList() and fde.getNumberOfParameters() = 0 and not fde.isDefinition()
not fde.isImplicit() and
not fde.hasVoidParamList() and
fde.getNumberOfParameters() = 0 and
not fde.isDefinition()
)
}