Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 29af56d

Browse files
committed
[CPP-340] Refine the test query for mismatching args/params by applying
C promotion rules. The following issues are now flagged: (1) passing a larger type than the receiver can accept (e.g., long long -> int) (2) passing a type of different signedness than the parameter specified.
1 parent 5a092d0 commit 29af56d

9 files changed

Lines changed: 103 additions & 14 deletions

File tree

cpp/ql/src/Likely Bugs/UnderspecifiedFunctions/MistypedFunctionArguments.ql

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,91 @@
1414

1515
import cpp
1616

17+
predicate argTypeMayBePromoted(Type arg, Type parm) {
18+
arg = parm
19+
or
20+
// floating-point and integral promotions
21+
arg instanceof FloatType and parm instanceof DoubleType
22+
or
23+
arg instanceof FloatType and parm instanceof LongDoubleType
24+
or
25+
arg instanceof DoubleType and parm instanceof LongDoubleType
26+
or
27+
arg instanceof CharType and parm instanceof IntType
28+
or
29+
arg instanceof CharType and parm instanceof IntType
30+
or
31+
arg instanceof CharType and parm instanceof LongType
32+
or
33+
arg instanceof CharType and parm instanceof LongLongType
34+
or
35+
arg instanceof ShortType and parm instanceof IntType
36+
or
37+
arg instanceof ShortType and parm instanceof LongType
38+
or
39+
arg instanceof ShortType and parm instanceof LongLongType
40+
or
41+
arg instanceof IntType and parm instanceof LongType
42+
or
43+
arg instanceof IntType and parm instanceof LongLongType
44+
or
45+
arg instanceof LongType and parm instanceof LongLongType
46+
or
47+
arg instanceof Enum and parm instanceof IntType
48+
or
49+
arg instanceof Enum and parm instanceof LongType
50+
or
51+
arg instanceof Enum and parm instanceof LongLongType
52+
or
53+
// enums are usually sized as ints
54+
arg instanceof IntType and parm instanceof Enum
55+
or
56+
// pointer types
57+
arg.(PointerType).getBaseType().getUnspecifiedType() = parm
58+
.getUnspecifiedType()
59+
.(PointerType)
60+
.getBaseType()
61+
.getUnspecifiedType()
62+
or
63+
// void * parameters accept arbitrary pointer arguments
64+
arg instanceof PointerType and
65+
parm.(PointerType).getBaseType().getUnspecifiedType() instanceof VoidType
66+
or
67+
// handle reference types
68+
argTypeMayBePromoted(arg.(ReferenceType).getBaseType().getUnspecifiedType(), parm)
69+
or
70+
argTypeMayBePromoted(arg, parm.(ReferenceType).getBaseType().getUnspecifiedType())
71+
or
72+
// array-to-pointer decay
73+
argTypeMayBePromoted(arg.(ArrayType).getBaseType().getUnspecifiedType(),
74+
parm.(PointerType).getBaseType().getUnspecifiedType())
75+
or
76+
// pointer-to-array promotion (C99)
77+
argTypeMayBePromoted(arg.(PointerType).getBaseType().getUnspecifiedType(),
78+
parm.(ArrayType).getBaseType().getUnspecifiedType())
79+
}
80+
81+
// This predicate doesn't necessarily have to exist, but if it does exist
82+
// then it must be inline to make sure we don't enumerate all pairs of
83+
// compatible types.
84+
// Its body could also just be hand-inlined where it's used.
85+
pragma[inline]
86+
predicate argMayBePromoted(Expr arg, Parameter parm) {
87+
argTypeMayBePromoted(arg.getExplicitlyConverted().getType().getUnspecifiedType(),
88+
parm.getType().getUnspecifiedType())
89+
or
90+
// The value 0 is often passed in to indicate NULL, or to initialize an arbitrary integer type.
91+
// we will allow all literal values for simplicity. Pointer parameters are sometime passed
92+
// special-case literals such as -1, -2, etc.
93+
arg.(Literal).getType() instanceof IntegralType and
94+
(
95+
parm.getType().getUnspecifiedType() instanceof PointerType
96+
or
97+
parm.getType().getUnspecifiedType() instanceof IntegralType and
98+
arg.(Literal).getType().getSize() <= parm.getType().getUnspecifiedType().getSize()
99+
)
100+
}
101+
17102
from FunctionCall fc, Function f, Parameter p
18103
where
19104
f = fc.getTarget() and
@@ -25,6 +110,8 @@ where
25110
fde.getNumberOfParameters() = 0
26111
) and
27112
// Parameter p and its corresponding call argument must have mismatched types
28-
p.getType() != fc.getArgument(p.getIndex()).getType()
29-
select fc, "Calling $@: $@ is incompatible with $@.", f, f.toString(), fc.getArgument(p.getIndex()),
30-
fc.getArgument(p.getIndex()).toString(), p, p.getTypedName()
113+
not argMayBePromoted(fc.getArgument(p.getIndex()), p)
114+
select fc, "Calling $@: argument $@ of type $@ is incompatible with parameter $@.", f, f.toString(),
115+
fc.getArgument(p.getIndex()), fc.getArgument(p.getIndex()).toString(),
116+
fc.getArgument(p.getIndex()).getType(), fc.getArgument(p.getIndex()).getType().toString(), p,
117+
p.getTypedName()

cpp/ql/src/Likely Bugs/UnderspecifiedFunctions/TooFewArguments.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* @id cpp/too-few-arguments
1111
* @tags correctness
1212
* maintainability
13+
* security
1314
*/
1415

1516
import cpp
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
| test.c:23:3:23:29 | call to declared_empty_defined_with | Calling $@: $@ is incompatible with $@. | test.c:31:6:31:32 | declared_empty_defined_with | declared_empty_defined_with | test.c:23:31:23:32 | & ... | & ... | test.c:31:38:31:38 | x | int x |
2-
| test.c:24:3:24:29 | call to declared_empty_defined_with | Calling $@: $@ is incompatible with $@. | test.c:31:6:31:32 | declared_empty_defined_with | declared_empty_defined_with | test.c:24:31:24:34 | 3.0 | 3.0 | test.c:31:38:31:38 | x | int x |
3-
| test.c:26:3:26:27 | call to not_declared_defined_with | Calling $@: $@ is incompatible with $@. | test.c:34:6:34:30 | not_declared_defined_with | not_declared_defined_with | test.c:26:29:26:31 | 1.0 | 1.0 | test.c:34:36:34:36 | x | int x |
4-
| test.c:26:3:26:27 | call to not_declared_defined_with | Calling $@: $@ is incompatible with $@. | test.c:34:6:34:30 | not_declared_defined_with | not_declared_defined_with | test.c:26:37:26:38 | 2 | 2 | test.c:34:50:34:50 | z | int z |
1+
| test.c:23:3:23:29 | call to declared_empty_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:32:6:32:32 | declared_empty_defined_with | declared_empty_defined_with | test.c:23:31:23:32 | & ... | & ... | file://:0:0:0:0 | int * | int * | test.c:32:38:32:38 | x | int x |
2+
| test.c:24:3:24:29 | call to declared_empty_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:32:6:32:32 | declared_empty_defined_with | declared_empty_defined_with | test.c:24:31:24:34 | 3.0 | 3.0 | file://:0:0:0:0 | float | float | test.c:32:38:32:38 | x | int x |
3+
| test.c:26:3:26:27 | call to not_declared_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:35:6:35:30 | not_declared_defined_with | not_declared_defined_with | test.c:26:29:26:31 | 1.0 | 1.0 | file://:0:0:0:0 | double | double | test.c:35:36:35:36 | x | int x |
4+
| test.c:27:3:27:27 | call to not_declared_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:35:6:35:30 | not_declared_defined_with | not_declared_defined_with | test.c:27:29:27:31 | 4 | 4 | file://:0:0:0:0 | long long | long long | test.c:35:36:35:36 | x | int x |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Likely Bugs/Underspecified Functions/MistypedFunctionArguments.ql
1+
Likely Bugs/UnderspecifiedFunctions/MistypedFunctionArguments.ql
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
| test.c:17:3:17:19 | call to not_yet_declared2 | This call has fewer arguments than required by $@. | test.c:16:3:16:3 | not_yet_declared2 | not_yet_declared2 |
2-
| test.c:17:3:17:19 | call to not_yet_declared2 | This call has fewer arguments than required by $@. | test.c:30:6:30:22 | not_yet_declared2 | not_yet_declared2 |
3-
| test.c:19:3:19:29 | call to declared_empty_defined_with | This call has fewer arguments than required by $@. | test.c:31:6:31:32 | declared_empty_defined_with | declared_empty_defined_with |
2+
| test.c:17:3:17:19 | call to not_yet_declared2 | This call has fewer arguments than required by $@. | test.c:31:6:31:22 | not_yet_declared2 | not_yet_declared2 |
3+
| test.c:19:3:19:29 | call to declared_empty_defined_with | This call has fewer arguments than required by $@. | test.c:32:6:32:32 | declared_empty_defined_with | declared_empty_defined_with |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Likely Bugs/Underspecified Functions/TooFewArguments.ql
1+
Likely Bugs/UnderspecifiedFunctions/TooFewArguments.ql
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
| test.c:8:3:8:16 | call to declared_empty | This call has more arguments than required by $@. | test.c:1:6:1:19 | declared_empty | declared_empty |
22
| test.c:13:3:13:12 | call to undeclared | This call has more arguments than required by $@. | test.c:12:3:12:3 | undeclared | undeclared |
33
| test.c:15:3:15:19 | call to not_yet_declared1 | This call has more arguments than required by $@. | test.c:15:3:15:3 | not_yet_declared1 | not_yet_declared1 |
4-
| test.c:15:3:15:19 | call to not_yet_declared1 | This call has more arguments than required by $@. | test.c:29:6:29:22 | not_yet_declared1 | not_yet_declared1 |
5-
| test.c:24:3:24:29 | call to declared_empty_defined_with | This call has more arguments than required by $@. | test.c:31:6:31:32 | declared_empty_defined_with | declared_empty_defined_with |
4+
| test.c:15:3:15:19 | call to not_yet_declared1 | This call has more arguments than required by $@. | test.c:30:6:30:22 | not_yet_declared1 | not_yet_declared1 |
5+
| test.c:24:3:24:29 | call to declared_empty_defined_with | This call has more arguments than required by $@. | test.c:32:6:32:32 | declared_empty_defined_with | declared_empty_defined_with |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Likely Bugs/Underspecified Functions/TooManyArguments.ql
1+
Likely Bugs/UnderspecifiedFunctions/TooManyArguments.ql

cpp/ql/test/query-tests/Likely Bugs/UnderspecifiedFunctions/test.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ void test() {
2424
declared_empty_defined_with(3.0f, &x); // BAD (type mismatch)
2525

2626
not_declared_defined_with(1.0, 0, 2U); // GOOD (type mismatch)
27+
not_declared_defined_with(4LL, 0, 2); // GOOD (type mismatch)
2728
}
2829

2930
void not_yet_declared1();

0 commit comments

Comments
 (0)