@@ -15,13 +15,22 @@ import codingstandards.c.cert
15
15
import codingstandards.cpp.Macro
16
16
import semmle.code.cpp.dataflow.DataFlow
17
17
18
+ abstract class VaAccess extends Expr { }
19
+
18
20
/**
19
21
* The argument of a call to `va_arg`
20
22
*/
21
- class VaArgArg extends Expr {
23
+ class VaArgArg extends VaAccess {
22
24
VaArgArg ( ) { this = any ( MacroInvocation m | m .getMacroName ( ) = [ "va_arg" ] ) .getExpr ( ) .getChild ( 0 ) }
23
25
}
24
26
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
+
25
34
/**
26
35
* Dataflow configuration for flow from a library function
27
36
* to a call of function `asctime`
@@ -34,13 +43,13 @@ class VaArgConfig extends DataFlow::Configuration {
34
43
any ( VariableDeclarationEntry m | m .getType ( ) .hasName ( "va_list" ) ) .getVariable ( )
35
44
}
36
45
37
- override predicate isSink ( DataFlow:: Node sink ) { sink .asExpr ( ) instanceof VaArgArg }
46
+ override predicate isSink ( DataFlow:: Node sink ) { sink .asExpr ( ) instanceof VaAccess }
38
47
}
39
48
40
49
/**
41
50
* Controlflow nodes preceeding a call to `va_arg`
42
51
*/
43
- ControlFlowNode preceedsFC ( VaArgArg va_arg ) {
52
+ ControlFlowNode preceedsFC ( VaAccess va_arg ) {
44
53
result = va_arg
45
54
or
46
55
exists ( ControlFlowNode mid |
@@ -49,25 +58,25 @@ ControlFlowNode preceedsFC(VaArgArg va_arg) {
49
58
// stop recursion on va_end on the same object
50
59
not result =
51
60
any ( MacroInvocation m |
52
- m .getMacroName ( ) = [ "va_end " ] and
61
+ m .getMacroName ( ) = [ "va_start " ] and
53
62
m .getExpr ( ) .getChild ( 0 ) .( VariableAccess ) .getTarget ( ) = va_arg .( VariableAccess ) .getTarget ( )
54
63
) .getExpr ( )
55
64
)
56
65
}
57
66
58
- predicate sameSource ( VaArgArg va_arg1 , VaArgArg va_arg2 ) {
67
+ predicate sameSource ( VaAccess e1 , VaAccess e2 ) {
59
68
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 ) )
62
71
)
63
72
}
64
73
65
- from VaArgArg va_arg1 , VaArgArg va_arg2 , FunctionCall fc
74
+ from VaAccess va_acc , VaArgArg va_arg , FunctionCall fc
66
75
where
67
- not isExcluded ( va_arg1 ,
76
+ not isExcluded ( va_acc ,
68
77
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 ,
73
82
fc .toString ( )
0 commit comments