Skip to content

Commit bde048b

Browse files
authored
Merge pull request #771 from github/lcartey/rule-1-3-main
`RULE-1-3`: Improve detection of standard compliant main functions
2 parents f9070ca + 4b9d813 commit bde048b

File tree

6 files changed

+73
-21
lines changed

6 files changed

+73
-21
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,44 @@
11
import cpp
2+
import codingstandards.cpp.Pointers
23
import codingstandards.cpp.UndefinedBehavior
34

45
/**
56
* Library for modeling undefined behavior.
67
*/
78
abstract class CUndefinedBehavior extends UndefinedBehavior { }
89

10+
/**
11+
* A function which has the signature - but not the name - of a main function.
12+
*/
913
class C99MainFunction extends Function {
1014
C99MainFunction() {
1115
this.getNumberOfParameters() = 2 and
12-
this.getType() instanceof IntType and
13-
this.getParameter(0).getType() instanceof IntType and
14-
this.getParameter(1).getType().(PointerType).getBaseType().(PointerType).getBaseType()
15-
instanceof CharType
16+
this.getType().getUnderlyingType() instanceof IntType and
17+
this.getParameter(0).getType().getUnderlyingType() instanceof IntType and
18+
this.getParameter(1)
19+
.getType()
20+
.getUnderlyingType()
21+
.(UnspecifiedPointerOrArrayType)
22+
.getBaseType()
23+
.(UnspecifiedPointerOrArrayType)
24+
.getBaseType() instanceof CharType
1625
or
1726
this.getNumberOfParameters() = 0 and
18-
this.getType() instanceof VoidType
27+
// Must be explicitly declared as `int main(void)`.
28+
this.getADeclarationEntry().hasVoidParamList() and
29+
this.getType().getUnderlyingType() instanceof IntType
1930
}
2031
}
2132

2233
class CUndefinedMainDefinition extends CUndefinedBehavior, Function {
2334
CUndefinedMainDefinition() {
2435
// for testing purposes, we use the prefix ____codeql_coding_standards`
25-
(this.getName() = "main" or this.getName().indexOf("____codeql_coding_standards") = 0) and
36+
(this.getName() = "main" or this.getName().indexOf("____codeql_coding_standards_main") = 0) and
2637
not this instanceof C99MainFunction
2738
}
2839

2940
override string getReason() {
3041
result =
31-
"The behavior of the program is undefined because the main function is not defined according to the C standard."
42+
"main function may trigger undefined behavior because it is not in one of the formats specified by the C standard."
3243
}
3344
}

c/misra/src/rules/RULE-1-3/OccurrenceOfUndefinedBehavior.ql

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ import codingstandards.c.UndefinedBehavior
1818

1919
from CUndefinedBehavior c
2020
where not isExcluded(c, Language3Package::occurrenceOfUndefinedBehaviorQuery())
21-
select c, "May result in undefined behavior."
21+
select c, c.getReason()
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
| test.c:8:6:8:35 | ____codeql_coding_standards_m2 | May result in undefined behavior. |
2-
| test.c:11:5:11:34 | ____codeql_coding_standards_m3 | May result in undefined behavior. |
3-
| test.c:15:5:15:34 | ____codeql_coding_standards_m4 | May result in undefined behavior. |
4-
| test.c:19:5:19:34 | ____codeql_coding_standards_m5 | May result in undefined behavior. |
5-
| test.c:23:5:23:34 | ____codeql_coding_standards_m6 | May result in undefined behavior. |
1+
| test.c:4:6:4:38 | ____codeql_coding_standards_main1 | main function may trigger undefined behavior because it is not in one of the formats specified by the C standard. |
2+
| test.c:8:5:8:37 | ____codeql_coding_standards_main2 | main function may trigger undefined behavior because it is not in one of the formats specified by the C standard. |
3+
| test.c:27:5:27:37 | ____codeql_coding_standards_main6 | main function may trigger undefined behavior because it is not in one of the formats specified by the C standard. |
4+
| test.c:32:6:32:38 | ____codeql_coding_standards_main7 | main function may trigger undefined behavior because it is not in one of the formats specified by the C standard. |
5+
| test.c:36:5:36:37 | ____codeql_coding_standards_main8 | main function may trigger undefined behavior because it is not in one of the formats specified by the C standard. |
6+
| test.c:40:5:40:37 | ____codeql_coding_standards_main9 | main function may trigger undefined behavior because it is not in one of the formats specified by the C standard. |
7+
| test.c:44:5:44:38 | ____codeql_coding_standards_main10 | main function may trigger undefined behavior because it is not in one of the formats specified by the C standard. |
8+
| test.c:48:5:48:38 | ____codeql_coding_standards_main11 | main function may trigger undefined behavior because it is not in one of the formats specified by the C standard. |

c/misra/test/rules/RULE-1-3/test.c

+32-7
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,50 @@
1-
void main(void) { // COMPLIANT
1+
int main(void) { // COMPLIANT
22
}
33

4-
int ____codeql_coding_standards_m1(int argc, char **argv) { // NON_COMPLIANT
4+
void ____codeql_coding_standards_main1(void) { // NON_COMPLIANT
55
return 0;
66
}
77

8-
void ____codeql_coding_standards_m2(char *argc, char **argv) { // NON_COMPLIANT
8+
int ____codeql_coding_standards_main2() { // NON_COMPLIANT
9+
return 0;
10+
}
11+
12+
int ____codeql_coding_standards_main3(int argc, char **argv) { // COMPLIANT
13+
return 0;
14+
}
15+
16+
int ____codeql_coding_standards_main4(int argc, char argv[][]) { // COMPLIANT
17+
return 0;
18+
}
19+
20+
int ____codeql_coding_standards_main5(int argc, char *argv[]) { // COMPLIANT
21+
return 0;
22+
}
23+
24+
typedef int MY_INT;
25+
typedef char *MY_CHAR_PTR;
26+
27+
int ____codeql_coding_standards_main6(MY_INT argc,
28+
MY_CHAR_PTR argv[]) { // COMPLIANT
29+
return 0;
30+
}
31+
32+
void ____codeql_coding_standards_main7(char *argc,
33+
char **argv) { // NON_COMPLIANT
934
}
1035

11-
int ____codeql_coding_standards_m3(int argc, char *argv) { // NON_COMPLIANT
36+
int ____codeql_coding_standards_main8(int argc, char *argv) { // NON_COMPLIANT
1237
return 0;
1338
}
1439

15-
int ____codeql_coding_standards_m4() { // NON_COMPLIANT
40+
int ____codeql_coding_standards_main9() { // NON_COMPLIANT
1641
return 0;
1742
}
1843

19-
int ____codeql_coding_standards_m5(int argc, int *argv) { // NON_COMPLIANT
44+
int ____codeql_coding_standards_main10(int argc, int *argv) { // NON_COMPLIANT
2045
return 0;
2146
}
2247

23-
int ____codeql_coding_standards_m6(int argc, int **argv) { // NON_COMPLIANT
48+
int ____codeql_coding_standards_main11(int argc, int **argv) { // NON_COMPLIANT
2449
return 0;
2550
}
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- `RULE-1-3` - `OccurrenceOfUndefinedBehavior.ql`:
2+
- Improve alert message to report the undefined behavior triggered.
3+
- Address both false positives and false negatives in identifying standard compliant main methods. Previously, `void main()` was considered permitted and `int main(void)` banned. In addition, we now detect main methods as standard compliant if they use typedefs, and if arrays are used in the definition of `argv`.

cpp/common/src/codingstandards/cpp/Pointers.qll

+11-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import cpp
66
import codingstandards.cpp.Type
77

88
/**
9-
* A type that is a pointer or array type.
9+
* A type that is a pointer or array type after stripping top-level specifiers.
1010
*/
1111
class PointerOrArrayType extends DerivedType {
1212
PointerOrArrayType() {
@@ -15,6 +15,16 @@ class PointerOrArrayType extends DerivedType {
1515
}
1616
}
1717

18+
/**
19+
* A type that is a pointer or array type.
20+
*/
21+
class UnspecifiedPointerOrArrayType extends DerivedType {
22+
UnspecifiedPointerOrArrayType() {
23+
this instanceof PointerType or
24+
this instanceof ArrayType
25+
}
26+
}
27+
1828
/**
1929
* An expression which performs pointer arithmetic
2030
*/

0 commit comments

Comments
 (0)