Skip to content

Commit 8e2af07

Browse files
authored
Merge pull request github#5237 from erik-krogh/moreInf
Approved by asgerf
2 parents 721ba5e + b9450c9 commit 8e2af07

File tree

4 files changed

+28
-11
lines changed

4 files changed

+28
-11
lines changed

javascript/ql/src/semmle/javascript/Arrays.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module ArrayTaintTracking {
2525
// `array.map(function (elt, i, ary) { ... })`: if `array` is tainted, then so are
2626
// `elt` and `ary`; similar for `forEach`
2727
exists(Function f |
28-
call.getArgument(0).analyze().getAValue().(AbstractFunction).getFunction() = f and
28+
call.getArgument(0).getAFunctionValue(0).getFunction() = f and
2929
call.(DataFlow::MethodCallNode).getMethodName() = ["map", "forEach"] and
3030
pred = call.getReceiver() and
3131
succ = DataFlow::parameterNode(f.getParameter([0, 2]))

javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ module DataFlow {
106106

107107
/** Holds if this node may evaluate to the Boolean value `b`. */
108108
predicate mayHaveBooleanValue(boolean b) {
109-
b = analyze().getAValue().(AbstractBoolean).getBooleanValue()
109+
getAPredecessor().mayHaveBooleanValue(b)
110+
or
111+
b = true and asExpr().(BooleanLiteral).getValue() = "true"
112+
or
113+
b = false and asExpr().(BooleanLiteral).getValue() = "false"
110114
}
111115

112116
/** Gets the integer value of this node, if it is an integer constant. */

javascript/ql/src/semmle/javascript/dataflow/Nodes.qll

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,13 @@ class InvokeNode extends DataFlow::SourceNode {
168168
private ObjectLiteralNode getOptionsArgument(int i) { result.flowsTo(getArgument(i)) }
169169

170170
/** Gets an abstract value representing possible callees of this call site. */
171-
final AbstractValue getACalleeValue() { result = getCalleeNode().analyze().getAValue() }
171+
final AbstractValue getACalleeValue() {
172+
exists(DataFlow::Node callee, DataFlow::AnalyzedNode analyzed |
173+
pragma[only_bind_into](callee) = getCalleeNode() and
174+
pragma[only_bind_into](analyzed) = callee.analyze() and
175+
pragma[only_bind_into](result) = analyzed.getAValue()
176+
)
177+
}
172178

173179
/**
174180
* Gets a potential callee of this call site.
@@ -1166,6 +1172,16 @@ module ClassNode {
11661172
result.getFile() = f
11671173
}
11681174

1175+
/**
1176+
* Gets a reference to the function `func`, where there exists a read/write of the "prototype" property on that reference.
1177+
*/
1178+
pragma[noinline]
1179+
private DataFlow::SourceNode getAFunctionValueWithPrototype(AbstractValue func) {
1180+
exists(result.getAPropertyReference("prototype")) and
1181+
result.analyze().getAValue() = pragma[only_bind_into](func) and
1182+
func instanceof AbstractFunction // the join-order goes bad if `func` has type `AbstractFunction`.
1183+
}
1184+
11691185
/**
11701186
* A function definition with prototype manipulation as a `ClassNode` instance.
11711187
*/
@@ -1176,10 +1192,7 @@ module ClassNode {
11761192
FunctionStyleClass() {
11771193
function.getFunction() = astNode and
11781194
(
1179-
exists(DataFlow::PropRef read |
1180-
read.getPropertyName() = "prototype" and
1181-
read.getBase().analyze().getAValue() = function
1182-
)
1195+
exists(getAFunctionValueWithPrototype(function))
11831196
or
11841197
exists(string name |
11851198
this = AccessPath::getAnAssignmentTo(name) and
@@ -1240,7 +1253,7 @@ module ClassNode {
12401253
* Gets a reference to the prototype of this class.
12411254
*/
12421255
DataFlow::SourceNode getAPrototypeReference() {
1243-
exists(DataFlow::SourceNode base | base.analyze().getAValue() = function |
1256+
exists(DataFlow::SourceNode base | base = getAFunctionValueWithPrototype(function) |
12441257
result = base.getAPropertyRead("prototype")
12451258
or
12461259
result = base.getAPropertySource("prototype")

javascript/ql/src/semmle/javascript/frameworks/Testing.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class BDDTest extends Test, @call_expr {
3333
exists(CallExpr call | call = this |
3434
call.getCallee().(VarAccess).getName() = "it" and
3535
exists(call.getArgument(0).getStringValue()) and
36-
call.getArgument(1).analyze().getAValue() instanceof AbstractFunction
36+
exists(call.getArgument(1).flow().getAFunctionValue(0))
3737
)
3838
}
3939
}
@@ -60,7 +60,7 @@ class JestTest extends Test, @call_expr {
6060
exists(CallExpr call | call = this |
6161
call.getCallee().(GlobalVarAccess).getName() = "test" and
6262
exists(call.getArgument(0).getStringValue()) and
63-
call.getArgument(1).analyze().getAValue() instanceof AbstractFunction
63+
exists(call.getArgument(1).flow().getAFunctionValue(0))
6464
) and
6565
getFile() = getTestFile(any(File f), "test")
6666
}
@@ -94,7 +94,7 @@ class CucumberTest extends Test, @call_expr {
9494
exists(DataFlow::ModuleImportNode m, CallExpr call |
9595
m.getPath() = "cucumber" and
9696
call = m.getAnInvocation().asExpr() and
97-
call.getArgument(0).analyze().getAValue() instanceof AbstractFunction and
97+
exists(call.getArgument(0).flow().getAFunctionValue()) and
9898
this = call
9999
)
100100
}

0 commit comments

Comments
 (0)