@@ -15,13 +15,22 @@ import codingstandards.c.cert
1515import codingstandards.cpp.Macro
1616import 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
6675where
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 ( )
0 commit comments