Skip to content

Commit 8e830bc

Browse files
committed
RULE-1-3: Improve detection of standard compliant main functions
- Improve alert message to report the undefined behavior triggered. - 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`.
1 parent 2a805c0 commit 8e830bc

File tree

5 files changed

+76
-20
lines changed

5 files changed

+76
-20
lines changed

c/common/src/codingstandards/c/UndefinedBehavior.qll

+32-7
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,53 @@ import codingstandards.cpp.UndefinedBehavior
66
*/
77
abstract class CUndefinedBehavior extends UndefinedBehavior { }
88

9+
class PointerOrArrayType extends DerivedType {
10+
PointerOrArrayType() {
11+
this instanceof PointerType or
12+
this instanceof ArrayType
13+
}
14+
}
15+
16+
Type get(Function main) {
17+
main.getName() = "main" and
18+
main.getNumberOfParameters() = 2 and
19+
main.getType().getUnderlyingType() instanceof IntType and
20+
main.getParameter(0).getType().getUnderlyingType() instanceof IntType and
21+
result = main.getParameter(1).getType().getUnderlyingType().(PointerOrArrayType).getBaseType()
22+
}
23+
24+
/**
25+
* A function which has the signature - but not the name - of a main function.
26+
*/
927
class C99MainFunction extends Function {
1028
C99MainFunction() {
1129
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
30+
this.getType().getUnderlyingType() instanceof IntType and
31+
this.getParameter(0).getType().getUnderlyingType() instanceof IntType and
32+
this.getParameter(1)
33+
.getType()
34+
.getUnderlyingType()
35+
.(PointerOrArrayType)
36+
.getBaseType()
37+
.(PointerOrArrayType)
38+
.getBaseType() instanceof CharType
1639
or
1740
this.getNumberOfParameters() = 0 and
18-
this.getType() instanceof VoidType
41+
// Must be explicitly declared as `int main(void)`.
42+
this.getADeclarationEntry().hasVoidParamList() and
43+
this.getType().getUnderlyingType() instanceof IntType
1944
}
2045
}
2146

2247
class CUndefinedMainDefinition extends CUndefinedBehavior, Function {
2348
CUndefinedMainDefinition() {
2449
// for testing purposes, we use the prefix ____codeql_coding_standards`
25-
(this.getName() = "main" or this.getName().indexOf("____codeql_coding_standards") = 0) and
50+
(this.getName() = "main" or this.getName().indexOf("____codeql_coding_standards_main") = 0) and
2651
not this instanceof C99MainFunction
2752
}
2853

2954
override string getReason() {
3055
result =
31-
"The behavior of the program is undefined because the main function is not defined according to the C standard."
56+
"main function may trigger undefined behavior because it is not in one of the formats specified by the C standard."
3257
}
3358
}

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`.

0 commit comments

Comments
 (0)