Skip to content

Commit 3e70e8e

Browse files
committed
Updated Stream related data flow
1 parent 46c037c commit 3e70e8e

File tree

2 files changed

+81
-42
lines changed

2 files changed

+81
-42
lines changed

csharp/ql/lib/experimental/quantum/dotnet/FlowAnalysis.qll

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -189,43 +189,21 @@ module ModeLiteralFlow {
189189
* `ToArray()` on the stream, or a wrapped stream.
190190
*/
191191
module StreamFlow {
192-
private class Stream extends Class {
193-
Stream() { this.getABaseType().hasFullyQualifiedName("System.IO", "Stream") }
194-
}
195-
196-
/**
197-
* A `Stream` object creation.
198-
*/
199-
private class StreamCreation extends ObjectCreation {
200-
StreamCreation() { this.getObjectType() instanceof Stream }
201-
202-
Expr getInputArg() {
203-
result = this.getAnArgument() and
204-
result.getType().hasFullyQualifiedName("System", "Byte[]")
205-
}
206-
207-
Expr getStreamArg() {
208-
result = this.getAnArgument() and
209-
result.getType() instanceof Stream
210-
}
211-
}
212-
213-
private class StreamUse extends MethodCall {
214-
StreamUse() {
215-
this.getQualifier().getType() instanceof Stream and
216-
this.getTarget().hasName("ToArray")
217-
}
218-
219-
Expr getOutput() { result = this }
220-
}
221-
222192
private module StreamConfig implements DataFlow::ConfigSig {
223-
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof StreamCreation }
193+
predicate isSource(DataFlow::Node source) {
194+
source.asExpr() instanceof StreamCreation
195+
or
196+
exists(StreamUse use | source.asExpr() = use.getQualifier())
197+
or
198+
exists(Expr use | source.asExpr() = use and use.getType() instanceof Stream)
199+
}
224200

225201
predicate isSink(DataFlow::Node sink) {
226202
sink.asExpr() instanceof StreamCreation
227203
or
228204
exists(StreamUse use | sink.asExpr() = use.getQualifier())
205+
or
206+
exists(Expr use | sink.asExpr() = use and use.getType() instanceof Stream)
229207
}
230208

231209
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
@@ -245,21 +223,25 @@ module StreamFlow {
245223

246224
private module StreamFlow = DataFlow::Global<StreamConfig>;
247225

248-
StreamCreation getWrappedStream(
226+
StreamCreation getWrappedStreamCreation(
249227
StreamCreation stream, StreamFlow::PathNode source, StreamFlow::PathNode sink
250228
) {
251229
source.getNode().asExpr() = result and
252230
sink.getNode().asExpr() = stream and
253231
StreamFlow::flowPath(source, sink)
254232
}
255233

256-
StreamUse getStreamUse(
257-
StreamCreation stream, StreamFlow::PathNode source, StreamFlow::PathNode sink
258-
) {
259-
source.getNode().asExpr() = stream and
234+
StreamUse getLaterUse(Expr use, StreamFlow::PathNode source, StreamFlow::PathNode sink) {
235+
source.getNode().asExpr() = use and
260236
sink.getNode().asExpr() = result.getQualifier() and
261237
StreamFlow::flowPath(source, sink)
262238
}
239+
240+
StreamUse getEarlierUse(Expr use, StreamFlow::PathNode source, StreamFlow::PathNode sink) {
241+
source.getNode().asExpr() = result.getQualifier() and
242+
sink.getNode().asExpr() = use and
243+
StreamFlow::flowPath(source, sink)
244+
}
263245
}
264246

265247
/**

csharp/ql/lib/experimental/quantum/dotnet/OperationInstances.qll

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
162202
class 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

Comments
 (0)