@@ -8,67 +8,120 @@ private import semmle.code.csharp.frameworks.System
8
8
private import semmle.code.csharp.frameworks.system.Text
9
9
10
10
/** A method that formats a string, for example `string.Format()`. */
11
- class FormatMethod extends Method {
12
- FormatMethod ( ) {
13
- exists ( Class declType | declType = this .getDeclaringType ( ) |
11
+ abstract private class FormatMethodImpl extends Method {
12
+ /**
13
+ * Gets the argument containing the format string. For example, the argument of
14
+ * `string.Format(IFormatProvider, String, Object)` is `1`.
15
+ */
16
+ abstract int getFormatArgument ( ) ;
17
+
18
+ /**
19
+ * Gets the argument number of the first supplied insert.
20
+ */
21
+ int getFirstArgument ( ) { result = this .getFormatArgument ( ) + 1 }
22
+ }
23
+
24
+ final class FormatMethod = FormatMethodImpl ;
25
+
26
+ /** A class of types used for formatting. */
27
+ private class FormatType extends Type {
28
+ FormatType ( ) {
29
+ this instanceof StringType or
30
+ this instanceof SystemTextCompositeFormatClass
31
+ }
32
+ }
33
+
34
+ private class StringAndStringBuilderFormatMethods extends FormatMethodImpl {
35
+ StringAndStringBuilderFormatMethods ( ) {
36
+ (
14
37
this .getParameter ( 0 ) .getType ( ) instanceof SystemIFormatProviderInterface and
15
- this .getParameter ( 1 ) .getType ( ) instanceof StringType and
38
+ this .getParameter ( 1 ) .getType ( ) instanceof FormatType
39
+ or
40
+ this .getParameter ( 0 ) .getType ( ) instanceof StringType
41
+ ) and
42
+ (
43
+ this = any ( SystemStringClass c ) .getFormatMethod ( )
44
+ or
45
+ this = any ( SystemTextStringBuilderClass c ) .getAppendFormatMethod ( )
46
+ )
47
+ }
48
+
49
+ override int getFormatArgument ( ) {
50
+ if this .getParameter ( 0 ) .getType ( ) instanceof SystemIFormatProviderInterface
51
+ then result = 1
52
+ else result = 0
53
+ }
54
+ }
55
+
56
+ private class SystemMemoryExtensionsFormatMethods extends FormatMethodImpl {
57
+ SystemMemoryExtensionsFormatMethods ( ) {
58
+ this = any ( SystemMemoryExtensionsClass c ) .getTryWriteMethod ( ) and
59
+ this .getParameter ( 1 ) .getType ( ) instanceof SystemIFormatProviderInterface and
60
+ this .getParameter ( 2 ) .getType ( ) instanceof SystemTextCompositeFormatClass
61
+ }
62
+
63
+ override int getFormatArgument ( ) { result = 2 }
64
+
65
+ override int getFirstArgument ( ) { result = this .getFormatArgument ( ) + 2 }
66
+ }
67
+
68
+ private class SystemConsoleAndSystemIoTextWriterFormatMethods extends FormatMethodImpl {
69
+ SystemConsoleAndSystemIoTextWriterFormatMethods ( ) {
70
+ this .getParameter ( 0 ) .getType ( ) instanceof StringType and
71
+ this .getNumberOfParameters ( ) > 1 and
72
+ exists ( Class declType | declType = this .getDeclaringType ( ) |
73
+ this .hasName ( [ "Write" , "WriteLine" ] ) and
16
74
(
17
- this = any ( SystemStringClass c ) . getFormatMethod ( )
75
+ declType . hasFullyQualifiedName ( "System" , "Console" )
18
76
or
19
- this = any ( SystemTextStringBuilderClass c ) . getAppendFormatMethod ( )
77
+ declType . hasFullyQualifiedName ( "System.IO" , "TextWriter" )
20
78
)
21
- or
22
- this .getParameter ( 0 ) .getType ( ) instanceof StringType and
79
+ )
80
+ }
81
+
82
+ override int getFormatArgument ( ) { result = 0 }
83
+ }
84
+
85
+ private class SystemDiagnosticsDebugAssert extends FormatMethodImpl {
86
+ SystemDiagnosticsDebugAssert ( ) {
87
+ this .hasName ( "Assert" ) and
88
+ this .getDeclaringType ( ) .hasFullyQualifiedName ( "System.Diagnostics" , "Debug" ) and
89
+ this .getNumberOfParameters ( ) = 4
90
+ }
91
+
92
+ override int getFormatArgument ( ) { result = 2 }
93
+ }
94
+
95
+ private class SystemDiagnosticsFormatMethods extends FormatMethodImpl {
96
+ SystemDiagnosticsFormatMethods ( ) {
97
+ this .getParameter ( 0 ) .getType ( ) instanceof StringType and
98
+ this .getNumberOfParameters ( ) > 1 and
99
+ exists ( Class declType |
100
+ declType = this .getDeclaringType ( ) and
101
+ declType .getNamespace ( ) .getFullName ( ) = "System.Diagnostics"
102
+ |
103
+ declType .hasName ( "Trace" ) and
23
104
(
24
- this = any ( SystemStringClass c ) .getFormatMethod ( )
25
- or
26
- this = any ( SystemTextStringBuilderClass c ) .getAppendFormatMethod ( )
27
- or
28
- ( this .hasName ( "Write" ) or this .hasName ( "WriteLine" ) ) and
29
- (
30
- declType .hasFullyQualifiedName ( "System" , "Console" )
31
- or
32
- declType .hasFullyQualifiedName ( "System.IO" , "TextWriter" )
33
- or
34
- declType .hasFullyQualifiedName ( "System.Diagnostics" , "Debug" ) and
35
- this .getParameter ( 1 ) .getType ( ) instanceof ArrayType
36
- )
105
+ this .hasName ( "TraceError" )
37
106
or
38
- declType .hasFullyQualifiedName ( "System.Diagnostics" , "Trace" ) and
39
- (
40
- this .hasName ( "TraceError" ) or
41
- this .hasName ( "TraceInformation" ) or
42
- this .hasName ( "TraceWarning" )
43
- )
107
+ this .hasName ( "TraceInformation" )
44
108
or
45
- this .hasName ( "TraceInformation" ) and
46
- declType .hasFullyQualifiedName ( "System.Diagnostics" , "TraceSource" )
47
- or
48
- this .hasName ( "Print" ) and
49
- declType .hasFullyQualifiedName ( "System.Diagnostics" , "Debug" )
109
+ this .hasName ( "TraceWarning" )
50
110
)
51
111
or
52
- this .hasName ( "Assert" ) and
53
- declType .hasFullyQualifiedName ( "System.Diagnostics" , "Debug" ) and
54
- this .getNumberOfParameters ( ) = 4
112
+ declType .hasName ( "TraceSource" ) and this .hasName ( "TraceInformation" )
113
+ or
114
+ declType .hasName ( "Debug" ) and
115
+ (
116
+ this .hasName ( "Print" )
117
+ or
118
+ this .hasName ( [ "Write" , "WriteLine" ] ) and
119
+ this .getParameter ( 1 ) .getType ( ) instanceof ArrayType
120
+ )
55
121
)
56
122
}
57
123
58
- /**
59
- * Gets the argument containing the format string. For example, the argument of
60
- * `string.Format(IFormatProvider, String, Object)` is `1`.
61
- */
62
- int getFormatArgument ( ) {
63
- if this .getParameter ( 0 ) .getType ( ) instanceof SystemIFormatProviderInterface
64
- then result = 1
65
- else
66
- if
67
- this .hasName ( "Assert" ) and
68
- this .getDeclaringType ( ) .hasFullyQualifiedName ( "System.Diagnostics" , "Debug" )
69
- then result = 2
70
- else result = 0
71
- }
124
+ override int getFormatArgument ( ) { result = 0 }
72
125
}
73
126
74
127
pragma [ nomagic]
@@ -194,24 +247,36 @@ class FormatCall extends MethodCall {
194
247
int getFormatArgument ( ) { result = this .getTarget ( ) .( FormatMethod ) .getFormatArgument ( ) }
195
248
196
249
/** Gets the argument number of the first supplied insert. */
197
- int getFirstArgument ( ) { result = this .getFormatArgument ( ) + 1 }
250
+ int getFirstArgument ( ) { result = this .getTarget ( ) . ( FormatMethod ) . getFirstArgument ( ) }
198
251
199
252
/** Holds if this call has one or more insertions. */
200
253
predicate hasInsertions ( ) { exists ( this .getArgument ( this .getFirstArgument ( ) ) ) }
201
254
202
- /** Holds if the arguments are supplied in an array, not individually. */
203
- predicate hasArrayExpr ( ) {
255
+ /**
256
+ * DEPRECATED: use `hasCollectionExpr` instead.
257
+ *
258
+ * Holds if the arguments are supplied in an array, not individually.
259
+ */
260
+ deprecated predicate hasArrayExpr ( ) {
204
261
this .getNumberOfArguments ( ) = this .getFirstArgument ( ) + 1 and
205
262
this .getArgument ( this .getFirstArgument ( ) ) .getType ( ) instanceof ArrayType
206
263
}
207
264
265
+ /**
266
+ * Holds if the arguments are supplied in a collection, not individually.
267
+ */
268
+ predicate hasCollectionExpr ( ) {
269
+ this .getNumberOfArguments ( ) = this .getFirstArgument ( ) + 1 and
270
+ this .getArgument ( this .getFirstArgument ( ) ) .getType ( ) instanceof ParamsCollectionType
271
+ }
272
+
208
273
/**
209
274
* Gets the number of supplied arguments (excluding the format string and format
210
275
* provider). Does not return a value if the arguments are supplied in an array,
211
276
* in which case we generally can't assess the size of the array.
212
277
*/
213
278
int getSuppliedArguments ( ) {
214
- not this .hasArrayExpr ( ) and
279
+ not this .hasCollectionExpr ( ) and
215
280
result = this .getNumberOfArguments ( ) - this .getFirstArgument ( )
216
281
}
217
282
0 commit comments