@@ -34,66 +34,87 @@ class AttributeFormattingFunction extends FormattingFunction {
3434
3535/**
3636 * A standard function such as `vprintf` that has a format parameter
37- * and a variable argument list of type `va_arg`.
37+ * and a variable argument list of type `va_arg`. `formatParamIndex` indicates
38+ * the format parameter and `type` indicates the type of `vprintf`:
39+ * - `""` is a `vprintf` variant, `outputParamIndex` is `-1`.
40+ * - `"f"` is a `vfprintf` variant, `outputParamIndex` indicates the output stream parameter.
41+ * - `"s"` is a `vsprintf` variant, `outputParamIndex` indicates the output buffer parameter.
42+ * - `"?"` if the type cannot be deteremined. `outputParamIndex` is `-1`.
3843 */
39- predicate primitiveVariadicFormatter ( TopLevelFunction f , int formatParamIndex ) {
40- f .getName ( ) .regexpMatch ( "_?_?va?[fs]?n?w?printf(_s)?(_p)?(_l)?" ) and
44+ predicate primitiveVariadicFormatter (
45+ TopLevelFunction f , string type , int formatParamIndex , int outputParamIndex
46+ ) {
47+ type = f .getName ( ) .regexpCapture ( "_?_?va?([fs]?)n?w?printf(_s)?(_p)?(_l)?" , 1 ) and
4148 (
4249 if f .getName ( ) .matches ( "%\\_l" )
4350 then formatParamIndex = f .getNumberOfParameters ( ) - 3
4451 else formatParamIndex = f .getNumberOfParameters ( ) - 2
45- )
52+ ) and
53+ if type = "" then outputParamIndex = - 1 else outputParamIndex = 0 // Conveniently, these buffer parameters are all at index 0.
4654}
4755
48- /**
49- * A standard function such as `vsprintf` that has an output parameter
50- * and a variable argument list of type `va_arg`.
51- */
52- private predicate primitiveVariadicFormatterOutput ( TopLevelFunction f , int outputParamIndex ) {
53- // note: this might look like the regular expression in `primitiveVariadicFormatter`, but
54- // there is one important difference: the [fs] part is not optional, as these classify
55- // the `printf` variants that write to a buffer.
56- // Conveniently, these buffer parameters are all at index 0.
57- f .getName ( ) .regexpMatch ( "_?_?va?[fs]n?w?printf(_s)?(_p)?(_l)?" ) and outputParamIndex = 0
58- }
59-
60- private predicate callsVariadicFormatter ( Function f , int formatParamIndex ) {
61- exists ( FunctionCall fc , int i |
62- variadicFormatter ( fc .getTarget ( ) , i ) and
56+ private predicate callsVariadicFormatter (
57+ Function f , string type , int formatParamIndex , int outputParamIndex
58+ ) {
59+ // calls a variadic formatter with `formatParamIndex`, `outputParamIndex` linked
60+ exists ( FunctionCall fc , int format , int output |
61+ variadicFormatter ( fc .getTarget ( ) , type , format , output ) and
6362 fc .getEnclosingFunction ( ) = f and
64- fc .getArgument ( i ) = f .getParameter ( formatParamIndex ) .getAnAccess ( )
63+ fc .getArgument ( format ) = f .getParameter ( formatParamIndex ) .getAnAccess ( ) and
64+ fc .getArgument ( output ) = f .getParameter ( outputParamIndex ) .getAnAccess ( )
6565 )
66- }
67-
68- private predicate callsVariadicFormatterOutput ( Function f , int outputParamIndex ) {
69- exists ( FunctionCall fc , int i |
66+ or
67+ // calls a variadic formatter with only `formatParamIndex` linked
68+ exists ( FunctionCall fc , string calledType , int format , int output |
69+ variadicFormatter ( fc . getTarget ( ) , calledType , format , output ) and
7070 fc .getEnclosingFunction ( ) = f and
71- variadicFormatterOutput ( fc .getTarget ( ) , i ) and
72- fc .getArgument ( i ) = f .getParameter ( outputParamIndex ) .getAnAccess ( )
71+ fc .getArgument ( format ) = f .getParameter ( formatParamIndex ) .getAnAccess ( ) and
72+ not fc .getArgument ( output ) = f .getParameter ( _) .getAnAccess ( ) and
73+ (
74+ calledType = "" and
75+ type = ""
76+ or
77+ calledType != "" and
78+ type = "?" // we probably should have an `outputParamIndex` link but have lost it.
79+ ) and
80+ outputParamIndex = - 1
7381 )
7482}
7583
7684/**
77- * Holds if `f` is a function such as `vprintf` that takes variable argument list
78- * of type `va_arg` and writes formatted output to a buffer given as a parameter at
79- * index `outputParamIndex`, if any.
85+ * Holds if `f` is a function such as `vprintf` that has a format parameter
86+ * and a variable argument list of type `va_arg`. `formatParamIndex` indicates
87+ * the format parameter and `type` indicates the type of `vprintf`:
88+ * - `""` is a `vprintf` variant, `outputParamIndex` is `-1`.
89+ * - `"f"` is a `vfprintf` variant, `outputParamIndex` indicates the output stream parameter.
90+ * - `"s"` is a `vsprintf` variant, `outputParamIndex` indicates the output buffer parameter.
91+ * - `"?"` if the type cannot be deteremined. `outputParamIndex` is `-1`.
8092 */
81- private predicate variadicFormatterOutput ( Function f , int outputParamIndex ) {
82- primitiveVariadicFormatterOutput ( f , outputParamIndex )
93+ predicate variadicFormatter ( Function f , string type , int formatParamIndex , int outputParamIndex ) {
94+ primitiveVariadicFormatter ( f , type , formatParamIndex , outputParamIndex )
8395 or
8496 not f .isVarargs ( ) and
85- callsVariadicFormatterOutput ( f , outputParamIndex )
97+ callsVariadicFormatter ( f , type , formatParamIndex , outputParamIndex )
98+ }
99+
100+ /**
101+ * A standard function such as `vprintf` that has a format parameter
102+ * and a variable argument list of type `va_arg`.
103+ *
104+ * DEPRECATED: Use the four argument version instead.
105+ */
106+ deprecated predicate primitiveVariadicFormatter ( TopLevelFunction f , int formatParamIndex ) {
107+ primitiveVariadicFormatter ( f , _, formatParamIndex , _)
86108}
87109
88110/**
89111 * Holds if `f` is a function such as `vprintf` that has a format parameter
90112 * (at `formatParamIndex`) and a variable argument list of type `va_arg`.
113+ *
114+ * DEPRECATED: Use the four argument version instead.
91115 */
92- predicate variadicFormatter ( Function f , int formatParamIndex ) {
93- primitiveVariadicFormatter ( f , formatParamIndex )
94- or
95- not f .isVarargs ( ) and
96- callsVariadicFormatter ( f , formatParamIndex )
116+ deprecated predicate variadicFormatter ( Function f , int formatParamIndex ) {
117+ variadicFormatter ( f , _, formatParamIndex , _)
97118}
98119
99120/**
@@ -103,11 +124,17 @@ predicate variadicFormatter(Function f, int formatParamIndex) {
103124class UserDefinedFormattingFunction extends FormattingFunction {
104125 override string getAPrimaryQlClass ( ) { result = "UserDefinedFormattingFunction" }
105126
106- UserDefinedFormattingFunction ( ) { isVarargs ( ) and callsVariadicFormatter ( this , _) }
127+ UserDefinedFormattingFunction ( ) { isVarargs ( ) and callsVariadicFormatter ( this , _, _, _) }
128+
129+ override int getFormatParameterIndex ( ) { callsVariadicFormatter ( this , _, result , _) }
107130
108- override int getFormatParameterIndex ( ) { callsVariadicFormatter ( this , result ) }
131+ override int getOutputParameterIndex ( boolean isStream ) {
132+ callsVariadicFormatter ( this , "f" , _, result ) and isStream = true
133+ or
134+ callsVariadicFormatter ( this , "s" , _, result ) and isStream = false
135+ }
109136
110- override int getOutputParameterIndex ( ) { callsVariadicFormatterOutput ( this , result ) }
137+ override predicate isOutputGlobal ( ) { callsVariadicFormatter ( this , "" , _ , _ ) }
111138}
112139
113140/**
0 commit comments