[CPP-340] Add more test case; exclude K&R definitions of functions when looking

up ()-declarations; refactor QL code.
This commit is contained in:
Ziemowit Laski
2019-04-12 17:25:33 -07:00
parent d76138f189
commit b58f414ede
8 changed files with 118 additions and 63 deletions

View File

@@ -14,23 +14,26 @@
import cpp
predicate arithTypesMatch(Type arg, Type parm) {
arg instanceof ArithmeticType and
parm instanceof ArithmeticType and
arg.getSize() = parm.getSize() and
(
arg instanceof IntegralOrEnumType and
parm instanceof IntegralOrEnumType
or
arg instanceof FloatingPointType and
parm instanceof FloatingPointType
)
}
pragma[inline]
predicate pointerArgTypeMayBeUsed(Type arg, Type parm) {
arg = parm
or
// arithmetic types
arg instanceof ArithmeticType and
parm instanceof ArithmeticType and
arg.getSize() = parm.getSize() and
(
arg instanceof IntegralType and
parm instanceof IntegralType
or
arg instanceof FloatingPointType and
parm instanceof FloatingPointType
)
arithTypesMatch(arg, parm)
or
// pointers to void are ok
// conversion to/from pointers to void is allowed
arg instanceof VoidType
or
parm instanceof VoidType
@@ -40,23 +43,22 @@ pragma[inline]
predicate argTypeMayBeUsed(Type arg, Type parm) {
arg = parm
or
// float arguments will have been promoted to double,
// and the parameter must match this
arg instanceof DoubleType and
parm instanceof DoubleType
or
// integral arguments are promoted to int (but not long long).
arg instanceof IntegralType and
arg.getSize() = 4 and
parm instanceof IntegralType and
parm.getSize() = 4
// arithmetic types
arithTypesMatch(arg, parm)
or
// pointers to compatible types
pointerArgTypeMayBeUsed(arg.(PointerType).getBaseType().getUnspecifiedType(),
parm.(PointerType).getBaseType().getUnspecifiedType())
or
pointerArgTypeMayBeUsed(arg.(ArrayType).getBaseType().getUnspecifiedType(),
parm.(PointerType).getBaseType().getUnspecifiedType())
or
// C11 arrays
pointerArgTypeMayBeUsed(arg.(PointerType).getBaseType().getUnspecifiedType(),
parm.(ArrayType).getBaseType().getUnspecifiedType())
or
pointerArgTypeMayBeUsed(arg.(ArrayType).getBaseType().getUnspecifiedType(),
parm.(ArrayType).getBaseType().getUnspecifiedType())
}
// This predicate doesn't necessarily have to exist, but if it does exist
@@ -69,11 +71,17 @@ predicate argMayBeUsed(Expr arg, Parameter parm) {
parm.getType().getUnspecifiedType())
}
// True if function was ()-declared, but not (void)-declared
pragma[inline]
// True if function was ()-declared, but not (void)-declared or K&R-defined
predicate hasZeroParamDecl(Function f) {
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
not fde.hasVoidParamList() and fde.getNumberOfParameters() = 0
not fde.hasVoidParamList() and fde.getNumberOfParameters() = 0 and not fde.isDefinition()
)
}
// 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()
)
}
@@ -81,12 +89,14 @@ from FunctionCall fc, Function f, Parameter p
where
f = fc.getTarget() and
p = f.getAParameter() and
not f.isVarargs() and
p.getIndex() < fc.getNumberOfArguments() and
hasZeroParamDecl(f) and
isCompiledAsC(f) and
not f.isVarargs() and
not f instanceof BuiltInFunction and
p.getIndex() < fc.getNumberOfArguments() and
// Parameter p and its corresponding call argument must have mismatched types
not argMayBeUsed(fc.getArgument(p.getIndex()), p)
select fc, "Calling $@: argument $@ of type $@ is incompatible with parameter $@", f, f.toString(),
select fc, "Calling $@: argument $@ of type $@ is incompatible with parameter $@.", f, f.toString(),
fc.getArgument(p.getIndex()) as arg, arg.toString(),
arg.getFullyConverted().getType().getUnspecifiedType() as atype,
atype.toString(), p, p.getTypedName()
arg.getExplicitlyConverted().getType().getUnspecifiedType() as atype, atype.toString(), p,
p.getTypedName()

View File

@@ -15,17 +15,30 @@
import cpp
// True if function was ()-declared, but not (void)-declared or K&R-defined
predicate hasZeroParamDecl(Function f) {
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
not fde.hasVoidParamList() and fde.getNumberOfParameters() = 0 and not fde.isDefinition()
)
}
// 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()
)
}
from FunctionCall fc, Function f
where
f = fc.getTarget() and
not f.isVarargs() and
// There must be a zero-parameter declaration (explicit or implicit)
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
fde.getNumberOfParameters() = 0
) and
not f instanceof BuiltInFunction and
hasZeroParamDecl(f) and
isCompiledAsC(f) and
// There is an explicit declaration of the function whose parameter count is larger
// than the number of call arguments
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
not fde.isImplicit() and fde.getNumberOfParameters() > fc.getNumberOfArguments()
fde.getNumberOfParameters() > fc.getNumberOfArguments()
)
select fc, "This call has fewer arguments than required by $@.", f, f.toString()

View File

@@ -13,14 +13,27 @@
import cpp
// True if function was ()-declared, but not (void)-declared or K&R-defined
predicate hasZeroParamDecl(Function f) {
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
not fde.hasVoidParamList() and fde.getNumberOfParameters() = 0 and not fde.isDefinition()
)
}
// 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()
)
}
from FunctionCall fc, Function f
where
f = fc.getTarget() and
not f.isVarargs() and
// There must be a zero-parameter declaration (explicit or implicit)
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
fde.getNumberOfParameters() = 0
) and
not f instanceof BuiltInFunction and
hasZeroParamDecl(f) and
isCompiledAsC(f) and
// There must not exist a declaration with the number of parameters
// at least as large as the number of call arguments
not exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |