@@ -169,6 +169,46 @@ class CipherMode extends MemberConstant {
169169 }
170170}
171171
172+ class Stream extends Class {
173+ Stream ( ) { this .getABaseType ( ) .hasFullyQualifiedName ( "System.IO" , "Stream" ) }
174+ }
175+
176+ /**
177+ * A `Stream` object creation.
178+ */
179+ class StreamCreation extends ObjectCreation {
180+ StreamCreation ( ) { this .getObjectType ( ) instanceof Stream }
181+
182+ Expr getInputArg ( ) {
183+ result = this .getAnArgument ( ) and
184+ result .getType ( ) .hasFullyQualifiedName ( "System" , "Byte[]" )
185+ }
186+
187+ Expr getStreamArg ( ) {
188+ result = this .getAnArgument ( ) and
189+ result .getType ( ) instanceof Stream
190+ }
191+ }
192+
193+ class StreamUse extends MethodCall {
194+ StreamUse ( ) {
195+ this .getQualifier ( ) .getType ( ) instanceof Stream and
196+ this .getTarget ( ) .hasName ( [ "ToArray" , "Write" ] )
197+ }
198+
199+ predicate isIntermediate ( ) { this .getTarget ( ) .hasName ( "Write" ) }
200+
201+ Expr getInputArg ( ) {
202+ this .isIntermediate ( ) and
203+ result = this .getArgument ( 0 )
204+ }
205+
206+ Expr getOutput ( ) {
207+ not this .isIntermediate ( ) and
208+ result = this
209+ }
210+ }
211+
172212class CryptoStreamCreation extends ObjectCreation {
173213 CryptoStreamCreation ( ) { this .getObjectType ( ) instanceof CryptoStream }
174214
@@ -253,11 +293,16 @@ class CryptoStreamOperationInstance extends Crypto::KeyOperationInstance instanc
253293 )
254294 }
255295
256- // Inputs can be passed either through the `stream` argument when the
257- // `CryptoStream` is created, or through calls to `Write()` on the
258- // `CryptoStream` object.
296+ // Inputs can be passed to the `CryptoStream` instance in a number of ways.
297+ //
298+ // 1. Through the `stream` argument when the `CryptoStream` is created
299+ // 2. Through calls to `Write()` on (a stream wrapped by) the stream argument
300+ // 3. Through calls to write on this `CryptoStream` object
259301 override Crypto:: ConsumerInputDataFlowNode getInputConsumer ( ) {
260- result .asExpr ( ) = StreamFlow:: getWrappedStream ( this , _, _) .getInputArg ( ) or
302+ result .asExpr ( ) = this .getWrappedStreamCreation ( ) .getInputArg ( )
303+ or
304+ result .asExpr ( ) = this .getEarlierWrappedStreamUse ( ) .getInputArg ( )
305+ or
261306 result .asExpr ( ) = CryptoStreamFlow:: getUseFromCreation ( this , _, _) .getInputArg ( )
262307 }
263308
@@ -267,7 +312,19 @@ class CryptoStreamOperationInstance extends Crypto::KeyOperationInstance instanc
267312 // We perform backwards dataflow to identify stream objects that are wrapped
268313 // by the `CryptoStream` object, and then we look for calls to `ToArray()`
269314 // on those streams.
270- result .asExpr ( ) =
271- StreamFlow:: getStreamUse ( any ( StreamFlow:: getWrappedStream ( this , _, _) ) , _, _) .getOutput ( )
315+ result .asExpr ( ) = this .getLaterWrappedStreamUse ( ) .getOutput ( )
316+ }
317+
318+ // Gets either this stream, or a stream wrapped by this stream.
319+ StreamCreation getWrappedStreamCreation ( ) {
320+ result = StreamFlow:: getWrappedStreamCreation ( this , _, _)
321+ }
322+
323+ StreamUse getEarlierWrappedStreamUse ( ) {
324+ result = StreamFlow:: getEarlierUse ( this .getWrappedStreamCreation ( ) .getStreamArg ( ) , _, _)
325+ }
326+
327+ StreamUse getLaterWrappedStreamUse ( ) {
328+ result = StreamFlow:: getLaterUse ( this .getWrappedStreamCreation ( ) .getStreamArg ( ) , _, _)
272329 }
273330}
0 commit comments