@@ -159,6 +159,46 @@ class CipherMode extends MemberConstant {
159159 }
160160}
161161
162+ class Stream extends Class {
163+ Stream ( ) { this .getABaseType ( ) .hasFullyQualifiedName ( "System.IO" , "Stream" ) }
164+ }
165+
166+ /**
167+ * A `Stream` object creation.
168+ */
169+ class StreamCreation extends ObjectCreation {
170+ StreamCreation ( ) { this .getObjectType ( ) instanceof Stream }
171+
172+ Expr getInputArg ( ) {
173+ result = this .getAnArgument ( ) and
174+ result .getType ( ) .hasFullyQualifiedName ( "System" , "Byte[]" )
175+ }
176+
177+ Expr getStreamArg ( ) {
178+ result = this .getAnArgument ( ) and
179+ result .getType ( ) instanceof Stream
180+ }
181+ }
182+
183+ class StreamUse extends MethodCall {
184+ StreamUse ( ) {
185+ this .getQualifier ( ) .getType ( ) instanceof Stream and
186+ this .getTarget ( ) .hasName ( [ "ToArray" , "Write" ] )
187+ }
188+
189+ predicate isIntermediate ( ) { this .getTarget ( ) .hasName ( "Write" ) }
190+
191+ Expr getInputArg ( ) {
192+ this .isIntermediate ( ) and
193+ result = this .getArgument ( 0 )
194+ }
195+
196+ Expr getOutput ( ) {
197+ not this .isIntermediate ( ) and
198+ result = this
199+ }
200+ }
201+
162202class CryptoStreamCreation extends ObjectCreation {
163203 CryptoStreamCreation ( ) { this .getObjectType ( ) instanceof CryptoStream }
164204
@@ -243,11 +283,16 @@ class CryptoStreamOperationInstance extends Crypto::KeyOperationInstance instanc
243283 )
244284 }
245285
246- // Inputs can be passed either through the `stream` argument when the
247- // `CryptoStream` is created, or through calls to `Write()` on the
248- // `CryptoStream` object.
286+ // Inputs can be passed to the `CryptoStream` instance in a number of ways.
287+ //
288+ // 1. Through the `stream` argument when the `CryptoStream` is created
289+ // 2. Through calls to `Write()` on (a stream wrapped by) the stream argument
290+ // 3. Through calls to write on this `CryptoStream` object
249291 override Crypto:: ConsumerInputDataFlowNode getInputConsumer ( ) {
250- result .asExpr ( ) = StreamFlow:: getWrappedStream ( this , _, _) .getInputArg ( ) or
292+ result .asExpr ( ) = this .getWrappedStreamCreation ( ) .getInputArg ( )
293+ or
294+ result .asExpr ( ) = this .getEarlierWrappedStreamUse ( ) .getInputArg ( )
295+ or
251296 result .asExpr ( ) = CryptoStreamFlow:: getUseFromCreation ( this , _, _) .getInputArg ( )
252297 }
253298
@@ -257,7 +302,19 @@ class CryptoStreamOperationInstance extends Crypto::KeyOperationInstance instanc
257302 // We perform backwards dataflow to identify stream objects that are wrapped
258303 // by the `CryptoStream` object, and then we look for calls to `ToArray()`
259304 // on those streams.
260- result .asExpr ( ) =
261- StreamFlow:: getStreamUse ( any ( StreamFlow:: getWrappedStream ( this , _, _) ) , _, _) .getOutput ( )
305+ result .asExpr ( ) = this .getLaterWrappedStreamUse ( ) .getOutput ( )
306+ }
307+
308+ // Gets either this stream, or a stream wrapped by this stream.
309+ StreamCreation getWrappedStreamCreation ( ) {
310+ result = StreamFlow:: getWrappedStreamCreation ( this , _, _)
311+ }
312+
313+ StreamUse getEarlierWrappedStreamUse ( ) {
314+ result = StreamFlow:: getEarlierUse ( this .getWrappedStreamCreation ( ) .getStreamArg ( ) , _, _)
315+ }
316+
317+ StreamUse getLaterWrappedStreamUse ( ) {
318+ result = StreamFlow:: getLaterUse ( this .getWrappedStreamCreation ( ) .getStreamArg ( ) , _, _)
262319 }
263320}
0 commit comments