Skip to content

Commit f6686d1

Browse files
committed
Fix MSC39-C after review
1 parent fee555c commit f6686d1

File tree

3 files changed

+34
-21
lines changed

3 files changed

+34
-21
lines changed

c/cert/src/rules/MSC39-C/DoNotCallVaArgOnAVaListThatHasAnIndeterminateValue.ql

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,22 @@ import codingstandards.c.cert
1515
import codingstandards.cpp.Macro
1616
import semmle.code.cpp.dataflow.DataFlow
1717

18+
abstract class VaAccess extends Expr { }
19+
1820
/**
1921
* The argument of a call to `va_arg`
2022
*/
21-
class VaArgArg extends Expr {
23+
class VaArgArg extends VaAccess {
2224
VaArgArg() { this = any(MacroInvocation m | m.getMacroName() = ["va_arg"]).getExpr().getChild(0) }
2325
}
2426

27+
/**
28+
* The argument of a call to `va_end`
29+
*/
30+
class VaEndArg extends VaAccess {
31+
VaEndArg() { this = any(MacroInvocation m | m.getMacroName() = ["va_end"]).getExpr().getChild(0) }
32+
}
33+
2534
/**
2635
* Dataflow configuration for flow from a library function
2736
* to a call of function `asctime`
@@ -34,13 +43,13 @@ class VaArgConfig extends DataFlow::Configuration {
3443
any(VariableDeclarationEntry m | m.getType().hasName("va_list")).getVariable()
3544
}
3645

37-
override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof VaArgArg }
46+
override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof VaAccess }
3847
}
3948

4049
/**
4150
* Controlflow nodes preceeding a call to `va_arg`
4251
*/
43-
ControlFlowNode preceedsFC(VaArgArg va_arg) {
52+
ControlFlowNode preceedsFC(VaAccess va_arg) {
4453
result = va_arg
4554
or
4655
exists(ControlFlowNode mid |
@@ -49,25 +58,25 @@ ControlFlowNode preceedsFC(VaArgArg va_arg) {
4958
// stop recursion on va_end on the same object
5059
not result =
5160
any(MacroInvocation m |
52-
m.getMacroName() = ["va_end"] and
61+
m.getMacroName() = ["va_start"] and
5362
m.getExpr().getChild(0).(VariableAccess).getTarget() = va_arg.(VariableAccess).getTarget()
5463
).getExpr()
5564
)
5665
}
5766

58-
predicate sameSource(VaArgArg va_arg1, VaArgArg va_arg2) {
67+
predicate sameSource(VaAccess e1, VaAccess e2) {
5968
exists(VaArgConfig config, DataFlow::Node source |
60-
config.hasFlow(source, DataFlow::exprNode(va_arg1)) and
61-
config.hasFlow(source, DataFlow::exprNode(va_arg2))
69+
config.hasFlow(source, DataFlow::exprNode(e1)) and
70+
config.hasFlow(source, DataFlow::exprNode(e2))
6271
)
6372
}
6473

65-
from VaArgArg va_arg1, VaArgArg va_arg2, FunctionCall fc
74+
from VaAccess va_acc, VaArgArg va_arg, FunctionCall fc
6675
where
67-
not isExcluded(va_arg1,
76+
not isExcluded(va_acc,
6877
Contracts7Package::doNotCallVaArgOnAVaListThatHasAnIndeterminateValueQuery()) and
69-
sameSource(va_arg1, va_arg2) and
70-
fc = preceedsFC(va_arg1) and
71-
fc.getTarget().calls*(va_arg2.getEnclosingFunction())
72-
select va_arg1, "The value of " + va_arg1.toString() + " is indeterminate after the $@.", fc,
78+
sameSource(va_acc, va_arg) and
79+
fc = preceedsFC(va_acc) and
80+
fc.getTarget().calls*(va_arg.getEnclosingFunction())
81+
select va_acc, "The value of " + va_acc.toString() + " is indeterminate after the $@.", fc,
7382
fc.toString()
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
| test.c:23:32:23:33 | ap | The value of ap is indeterminate after the $@. | test.c:17:7:17:19 | call to contains_zero | call to contains_zero |
2+
| test.c:26:10:26:11 | ap | The value of ap is indeterminate after the $@. | test.c:17:7:17:19 | call to contains_zero | call to contains_zero |
3+
| test.c:39:12:39:13 | ap | The value of ap is indeterminate after the $@. | test.c:35:7:35:19 | call to contains_zero | call to contains_zero |
4+
| test.c:48:10:48:11 | ap | The value of ap is indeterminate after the $@. | test.c:35:7:35:19 | call to contains_zero | call to contains_zero |
25
| test.c:65:34:65:35 | ap | The value of ap is indeterminate after the $@. | test.c:58:7:58:19 | call to contains_zero | call to contains_zero |
6+
| test.c:71:10:71:11 | ap | The value of ap is indeterminate after the $@. | test.c:58:7:58:19 | call to contains_zero | call to contains_zero |

c/cert/test/rules/MSC39-C/test.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ int f1a(size_t count, ...) {
1515
va_start(ap, count);
1616

1717
if (contains_zero(count, ap)) {
18-
va_end(ap);
18+
va_start(ap, count);
1919
return 1;
2020
}
2121

2222
for (size_t i = 0; i < count; ++i) {
2323
printf("%f ", 1.0 / va_arg(ap, double)); // NON_COMPLIANT
2424
}
2525

26-
va_end(ap);
26+
va_end(ap); // NON_COMPLIANT
2727
return 0;
2828
}
2929

@@ -36,7 +36,7 @@ int f1b(size_t count, ...) {
3636
printf("0 in arguments!\n");
3737
status = 1;
3838
} else {
39-
va_end(ap);
39+
va_end(ap); // NON_COMPLIANT
4040
va_start(ap, count);
4141
for (size_t i = 0; i < count; i++) {
4242
printf("%f ", 1.0 / va_arg(ap, double)); // COMPLIANT
@@ -45,7 +45,7 @@ int f1b(size_t count, ...) {
4545
status = 0;
4646
}
4747

48-
va_end(ap);
48+
va_end(ap); // NON_COMPLIANT
4949
return status;
5050
}
5151

@@ -59,7 +59,7 @@ int f1c(size_t count, ...) {
5959
printf("0 in arguments!\n");
6060
status = 1;
6161
} else {
62-
va_end(ap1); // ending the wrong va_list object
62+
va_end(ap1); // COMPLIANT
6363
va_start(ap1, count);
6464
for (size_t i = 0; i < count; i++) {
6565
printf("%f ", 1.0 / va_arg(ap, double)); // NON_COMPLIANT
@@ -68,7 +68,7 @@ int f1c(size_t count, ...) {
6868
status = 0;
6969
}
7070

71-
va_end(ap);
71+
va_end(ap); // NON_COMPLIANT
7272
return status;
7373
}
7474

@@ -80,7 +80,7 @@ int contains_zero_ok(size_t count, va_list *ap) {
8080
return 1;
8181
}
8282
}
83-
va_end(ap1);
83+
va_end(ap1); // COMPLIANT
8484
return 0;
8585
}
8686

@@ -100,6 +100,6 @@ int print_reciprocals_ok(size_t count, ...) {
100100
status = 0;
101101
}
102102

103-
va_end(ap);
103+
va_end(ap); // COMPLIANT
104104
return status;
105105
}

0 commit comments

Comments
 (0)