Skip to content

Commit c63283f

Browse files
committed
Data flow: Add new lambda flow interface
1 parent 570260b commit c63283f

File tree

2 files changed

+87
-1
lines changed

2 files changed

+87
-1
lines changed

shared/dataflow/codeql/dataflow/DataFlow.qll

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,9 @@ signature module InputSig<LocationSig Location> {
290290
class LambdaCallKind;
291291

292292
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
293-
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c);
293+
predicate lambdaCreation(
294+
Node creation, LambdaCallKind kind, DataFlowCallable c, DataFlowCall synthCall
295+
);
294296

295297
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
296298
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver);
@@ -344,6 +346,12 @@ signature module InputSig<LocationSig Location> {
344346

345347
/** Holds if `fieldFlowBranchLimit` should be ignored for flow going into/out of `c`. */
346348
default predicate ignoreFieldFlowBranchLimit(DataFlowCallable c) { none() }
349+
350+
Content getLambdaReturnContent(LambdaCallKind kind);
351+
352+
Content getLambdaArgumentContent(LambdaCallKind kind, ArgumentPosition pos);
353+
354+
predicate isLambdaInstanceParameter(ParameterNode p);
347355
}
348356

349357
module Configs<LocationSig Location, InputSig<Location> Lang> {

shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,83 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
10451045
cached
10461046
DataFlowCallable viableCallableCached(DataFlowCall call) { result = viableCallable(call) }
10471047

1048+
/*
1049+
* foo(x => sink(x), notaint)
1050+
* foo(x => safe(x), taint)
1051+
*
1052+
* foo(lambda, x) {
1053+
* lambda(x);
1054+
* }
1055+
*
1056+
* x.Field = taint;
1057+
* taint --store(Field) --> x [Field]
1058+
*
1059+
* y = x; // x [Field] --> y [Field]
1060+
*
1061+
* sink(y.Field) // y [Field] --read(Field)--> y.Field
1062+
*
1063+
*
1064+
*
1065+
*
1066+
* lambda = () => "taint";
1067+
*
1068+
* "taint" --store(ReturnValue)--> this (post-update) [ReturnValue]
1069+
*
1070+
* lambda.synth_call();
1071+
*
1072+
* this (post-update) [ReturnValue] --> lambda (post-update) [ReturnValue]
1073+
*
1074+
* sink(lambda_1());
1075+
*
1076+
* "taint" --store(ReturnValue)--> () => "taint" [ReturnValue]
1077+
* () => "taint" [ReturnValue] --> lambda [ReturnValue]
1078+
* lambda [ReturnValue] --> lambda_1 [ReturnValue]
1079+
* lambda_1 [ReturnValue] --read(ReturnValue)--> lambda_1()
1080+
*
1081+
*
1082+
* setField(p, value) {
1083+
* sink(p.Field);
1084+
* p.Field = value; // value --store(Field)--> p (post-update) [Field]
1085+
* }
1086+
*
1087+
* // p (post-update) [Field] --> x (post-update) [Field]
1088+
*
1089+
* setField(x, "taint");
1090+
* sink(x.Field);
1091+
*
1092+
*
1093+
* lambda = (x) => sink(x);
1094+
* lambda.synth_call_lambda(lambda_arg0, lambda_arg1)
1095+
*
1096+
*
1097+
*
1098+
* foo(lambda);
1099+
*
1100+
* foo(l1) {
1101+
* bar(l1)
1102+
* }
1103+
*
1104+
* bar(l2) {
1105+
* l2("taint"); // taint --store(Argument0)--> l2 (post-update) [Argument0]
1106+
* }
1107+
*
1108+
* l2 (post-update) [Argument0] --> l1 (post-update) [Argument0]
1109+
*
1110+
* l1 (post-update) [Argument0] --> lambda (post-update) [Argument0]
1111+
*
1112+
*
1113+
* id = (x) => x;
1114+
* id.synth_call(arg0)
1115+
* foo(id);
1116+
*
1117+
* foo(l) {
1118+
* x = l("taint");
1119+
* y = l("safe");
1120+
* sink(x);
1121+
* sink(y);
1122+
* }
1123+
*/
1124+
10481125
/**
10491126
* Gets a viable target for the lambda call `call`.
10501127
*
@@ -1053,6 +1130,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
10531130
*/
10541131
cached
10551132
DataFlowCallable viableCallableLambda(DataFlowCall call, DataFlowCallOption lastCall) {
1133+
none() and
10561134
exists(Node creation, LambdaCallKind kind |
10571135
LambdaFlow::revLambdaFlow(call, kind, creation, _, _, _, lastCall) and
10581136
lambdaCreation(creation, kind, result)

0 commit comments

Comments
 (0)