@@ -34,66 +34,77 @@ 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- )
46- }
47-
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
52+ ) and
53+ if type = "" then outputParamIndex = - 1 else outputParamIndex = 0 // Conveniently, these buffer parameters are all at index 0.
5854}
5955
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+ (
75+ calledType = "" and
76+ type = ""
77+ ) or (
78+ calledType != "" and
79+ type = "?" // we probably should have an `outputParamIndex` link but have lost it.
80+ )
81+ ) and
82+ outputParamIndex = - 1
7383 )
7484}
7585
7686/**
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.
87+ * Holds if `f` is a function such as `vprintf` that has a format parameter
88+ * and a variable argument list of type `va_arg`. `formatParamIndex` indicates
89+ * the format parameter and `type` indicates the type of `vprintf`:
90+ * - `""` is a `vprintf` variant, `outputParamIndex` is `-1`.
91+ * - `"f"` is a `vfprintf` variant, `outputParamIndex` indicates the output stream parameter.
92+ * - `"s"` is a `vsprintf` variant, `outputParamIndex` indicates the output buffer parameter.
93+ * - `"?"` if the type cannot be deteremined. `outputParamIndex` is `-1`.
8094 */
81- private predicate variadicFormatterOutput ( Function f , int outputParamIndex ) {
82- primitiveVariadicFormatterOutput ( f , outputParamIndex )
95+ predicate variadicFormatter ( Function f , string type , int formatParamIndex , int outputParamIndex ) {
96+ primitiveVariadicFormatter ( f , type , formatParamIndex , outputParamIndex )
8397 or
8498 not f .isVarargs ( ) and
85- callsVariadicFormatterOutput ( f , outputParamIndex )
99+ callsVariadicFormatter ( f , type , formatParamIndex , outputParamIndex )
86100}
87101
88- /**
89- * Holds if `f` is a function such as `vprintf` that has a format parameter
90- * (at `formatParamIndex`) and a variable argument list of type `va_arg`.
91- */
92- predicate variadicFormatter ( Function f , int formatParamIndex ) {
93- primitiveVariadicFormatter ( f , formatParamIndex )
94- or
95- not f .isVarargs ( ) and
96- callsVariadicFormatter ( f , formatParamIndex )
102+ deprecated predicate primitiveVariadicFormatter ( TopLevelFunction f , int formatParamIndex ) {
103+ primitiveVariadicFormatter ( f , _, formatParamIndex , _)
104+ }
105+
106+ deprecated predicate variadicFormatter ( Function f , int formatParamIndex ) {
107+ variadicFormatter ( f , _, formatParamIndex , _)
97108}
98109
99110/**
@@ -103,11 +114,17 @@ predicate variadicFormatter(Function f, int formatParamIndex) {
103114class UserDefinedFormattingFunction extends FormattingFunction {
104115 override string getAPrimaryQlClass ( ) { result = "UserDefinedFormattingFunction" }
105116
106- UserDefinedFormattingFunction ( ) { isVarargs ( ) and callsVariadicFormatter ( this , _) }
117+ UserDefinedFormattingFunction ( ) { isVarargs ( ) and callsVariadicFormatter ( this , _, _, _) }
118+
119+ override int getFormatParameterIndex ( ) { callsVariadicFormatter ( this , _, result , _) }
120+
121+ override int getOutputParameterIndex ( ) {
122+ callsVariadicFormatter ( this , _, _, result ) and not result = - 1
123+ }
107124
108- override int getFormatParameterIndex ( ) { callsVariadicFormatter ( this , result ) }
125+ override predicate isOutputGlobal ( ) { callsVariadicFormatter ( this , "" , _ , _ ) }
109126
110- override int getOutputParameterIndex ( ) { callsVariadicFormatterOutput ( this , result ) }
127+ override predicate isOutputStream ( ) { callsVariadicFormatter ( this , "f" , _ , _ ) }
111128}
112129
113130/**
0 commit comments