Merge pull request #10126 from erik-krogh/myApply

JS: precise flow through calls to `.apply()`
This commit is contained in:
Erik Krogh Kristensen
2022-08-24 12:55:36 +02:00
committed by GitHub
26 changed files with 408 additions and 83 deletions

View File

@@ -261,14 +261,12 @@ private module ArrayDataFlow {
/**
* A step for creating an array and storing the elements in the array.
*/
private class ArrayCreationStep extends DataFlow::SharedFlowStep {
private class ArrayCreationStep extends PreCallGraphStep {
override predicate storeStep(DataFlow::Node element, DataFlow::SourceNode obj, string prop) {
exists(DataFlow::ArrayCreationNode array, int i |
element = array.getElement(i) and
obj = array and
if array = any(PromiseAllCreation c).getArrayNode()
then prop = arrayElement(i)
else prop = arrayElement()
prop = arrayElement(i)
)
}
}
@@ -346,6 +344,14 @@ private module ArrayLibraries {
result = DataFlow::globalVarRef("Array").getAMemberCall("from")
or
result = DataFlow::moduleImport("array-from").getACall()
or
// Array.prototype.slice.call acts the same as Array.from, and is sometimes used with e.g. the arguments object.
result =
DataFlow::globalVarRef("Array")
.getAPropertyRead("prototype")
.getAPropertyRead("slice")
.getAMethodCall("call") and
result.getNumArgument() = 1
}
/**

View File

@@ -11,36 +11,14 @@ private import semmle.javascript.internal.CachedStages
* Gets a parameter that is a library input to a top-level package.
*/
cached
DataFlow::SourceNode getALibraryInputParameter() {
DataFlow::Node getALibraryInputParameter() {
Stages::Taint::ref() and
exists(int bound, DataFlow::FunctionNode func |
func = getAValueExportedByPackage().getABoundFunctionValue(bound)
|
result = func.getParameter(any(int arg | arg >= bound))
or
result = getAnArgumentsRead(func.getFunction())
)
}
private DataFlow::SourceNode getAnArgumentsRead(Function func) {
exists(DataFlow::PropRead read |
not read.getPropertyName() = "length" and
result = read
|
read.getBase() = func.getArgumentsVariable().getAnAccess().flow()
or
exists(DataFlow::MethodCallNode call |
call =
DataFlow::globalVarRef("Array")
.getAPropertyRead("prototype")
.getAPropertyRead("slice")
.getAMethodCall("call")
or
call = DataFlow::globalVarRef("Array").getAMethodCall("from")
|
call.getArgument(0) = func.getArgumentsVariable().getAnAccess().flow() and
call.flowsTo(read.getBase())
)
result = func.getFunction().getArgumentsVariable().getAnAccess().flow()
)
}

View File

@@ -1267,56 +1267,47 @@ private predicate loadStep(
* If `onlyRelevantInCall` is true, the `base` object will not be propagated out of return edges, because
* the flow that originally reached `base.startProp` used a call edge.
*/
pragma[nomagic]
pragma[noopt]
private predicate reachableFromStoreBase(
string startProp, string endProp, DataFlow::Node base, DataFlow::Node nd,
DataFlow::Configuration cfg, PathSummary summary, boolean onlyRelevantInCall
DataFlow::Configuration cfg, TPathSummary summary, boolean onlyRelevantInCall
) {
exists(PathSummary s1, PathSummary s2, DataFlow::Node rhs |
reachableFromSource(rhs, cfg, s1) and
onlyRelevantInCall = s1.hasCall()
or
reachableFromStoreBase(_, _, _, rhs, cfg, s1, onlyRelevantInCall)
|
exists(TPathSummary s1, TPathSummary s2, DataFlow::Node rhs |
storeStep(rhs, nd, startProp, cfg, s2) and
endProp = startProp and
base = nd and
summary =
MkPathSummary(false, s2.hasCall(), DataFlow::FlowLabel::data(), DataFlow::FlowLabel::data())
exists(boolean hasCall, DataFlow::FlowLabel data |
hasCall = hasCall(s2) and
data = DataFlow::FlowLabel::data() and
summary = MkPathSummary(false, hasCall, data, data)
)
|
reachableFromSource(rhs, cfg, s1) and
onlyRelevantInCall = hasCall(s1)
or
reachableFromStoreBase(_, _, _, rhs, cfg, s1, onlyRelevantInCall)
)
or
exists(PathSummary newSummary, PathSummary oldSummary |
reachableFromStoreBaseStep(startProp, endProp, base, nd, cfg, oldSummary, newSummary,
onlyRelevantInCall) and
summary = oldSummary.appendValuePreserving(newSummary)
)
}
/**
* Holds if `base` is the base of a write to property `endProp`, and `nd` is reachable
* from `base` under configuration `cfg` (possibly through callees) along a path whose
* last step is summarized by `newSummary`, and the previous steps are summarized
* by `oldSummary`.
*/
pragma[noinline]
private predicate reachableFromStoreBaseStep(
string startProp, string endProp, DataFlow::Node base, DataFlow::Node nd,
DataFlow::Configuration cfg, PathSummary oldSummary, PathSummary newSummary,
boolean onlyRelevantInCall
) {
exists(DataFlow::Node mid |
exists(DataFlow::Node mid, PathSummary oldSummary, PathSummary newSummary |
reachableFromStoreBase(startProp, endProp, base, mid, cfg, oldSummary, onlyRelevantInCall) and
flowStep(mid, cfg, nd, newSummary) and
onlyRelevantInCall.booleanAnd(newSummary.hasReturn()) = false
exists(boolean hasReturn |
hasReturn = newSummary.hasReturn() and
onlyRelevantInCall.booleanAnd(hasReturn) = false
)
or
exists(string midProp |
reachableFromStoreBase(startProp, midProp, base, mid, cfg, oldSummary, onlyRelevantInCall) and
isAdditionalLoadStoreStep(mid, nd, midProp, endProp, cfg) and
newSummary = PathSummary::level()
)
|
summary = oldSummary.appendValuePreserving(newSummary)
)
}
private boolean hasCall(PathSummary summary) { result = summary.hasCall() }
/**
* Holds if the value of `pred` is written to a property of some base object, and that base
* object may flow into the base of property read `succ` under configuration `cfg` along

View File

@@ -1029,6 +1029,32 @@ module DataFlow {
override File getFile() { result = function.getFile() }
}
/**
* A data flow node representing the arguments object given to a function.
*/
class ReflectiveParametersNode extends DataFlow::Node, TReflectiveParametersNode {
Function function;
ReflectiveParametersNode() { this = TReflectiveParametersNode(function) }
override string toString() { result = "'arguments' object of " + function.describe() }
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
function.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
override BasicBlock getBasicBlock() { result = function.getEntry().getBasicBlock() }
/**
* Gets the function whose `arguments` object is represented by this node.
*/
Function getFunction() { result = function }
override File getFile() { result = function.getFile() }
}
/**
* A data flow node representing the exceptions thrown by the callee of an invocation.
*/
@@ -1627,6 +1653,35 @@ module DataFlow {
exists(Function f | not f.isAsyncOrGenerator() |
DataFlow::functionReturnNode(succ, f) and pred = valueNode(f.getAReturnedExpr())
)
or
// from a reflective params node to a reference to the arguments object.
exists(DataFlow::ReflectiveParametersNode params, Function f | f = params.getFunction() |
succ = f.getArgumentsVariable().getAnAccess().flow() and
pred = params
)
}
/** A load step from a reflective parameter node to each parameter. */
private class ReflectiveParamsStep extends PreCallGraphStep {
override predicate loadStep(DataFlow::Node obj, DataFlow::Node element, string prop) {
exists(DataFlow::ReflectiveParametersNode params, DataFlow::FunctionNode f, int i |
f.getFunction() = params.getFunction() and
obj = params and
prop = i + "" and
element = f.getParameter(i)
)
}
}
/** A taint step from the reflective parameters node to any parameter. */
private class ReflectiveParamsTaintStep extends TaintTracking::SharedTaintStep {
override predicate step(DataFlow::Node obj, DataFlow::Node element) {
exists(DataFlow::ReflectiveParametersNode params, DataFlow::FunctionNode f |
f.getFunction() = params.getFunction() and
obj = params and
element = f.getAParameter()
)
}
}
/**

View File

@@ -332,6 +332,8 @@ module SourceNode {
or
// Include return nodes because they model the implicit Promise creation in async functions.
DataFlow::functionReturnNode(this, _)
or
this instanceof DataFlow::ReflectiveParametersNode
}
}
}

View File

@@ -31,4 +31,5 @@ newtype TNode =
TExceptionalFunctionReturnNode(Function f) or
TExceptionalInvocationReturnNode(InvokeExpr e) or
TGlobalAccessPathRoot() or
TTemplatePlaceholderTag(Templating::TemplatePlaceholderTag tag)
TTemplatePlaceholderTag(Templating::TemplatePlaceholderTag tag) or
TReflectiveParametersNode(Function f)

View File

@@ -224,6 +224,14 @@ private module CachedSteps {
or
arg = invk.(DataFlow::PropWrite).getRhs() and
parm = DataFlow::parameterNode(f.getParameter(0))
or
calls(invk, f) and
exists(MethodCallExpr apply |
invk = DataFlow::reflectiveCallNode(apply) and
apply.getMethodName() = "apply" and
arg = apply.getArgument(1).flow()
) and
parm.(DataFlow::ReflectiveParametersNode).getFunction() = f
)
or
exists(DataFlow::Node callback, int i, Parameter p, Function target |

View File

@@ -68,7 +68,7 @@ module PrototypePollutingAssignment {
/**
* A parameter of an exported function, seen as a source prototype-polluting assignment.
*/
class ExternalInputSource extends Source, DataFlow::SourceNode {
class ExternalInputSource extends Source {
ExternalInputSource() { this = Exports::getALibraryInputParameter() }
override string describe() { result = "library input" }

View File

@@ -21,11 +21,11 @@ module UnsafeCodeConstruction {
/**
* A parameter of an exported function, seen as a source.
*/
class ExternalInputSource extends Source, DataFlow::ParameterNode {
class ExternalInputSource extends Source {
ExternalInputSource() {
this = Exports::getALibraryInputParameter() and
// permit parameters that clearly are intended to contain executable code.
not this.getName() = "code"
not this.(DataFlow::ParameterNode).getName() = "code"
}
}

View File

@@ -22,7 +22,7 @@ module UnsafeHtmlConstruction {
/**
* A parameter of an exported function, seen as a source for usnafe HTML constructed from input.
*/
class ExternalInputSource extends Source, DataFlow::ParameterNode {
class ExternalInputSource extends Source {
ExternalInputSource() {
this = Exports::getALibraryInputParameter() and
// An AMD-style module sometimes loads the jQuery library in a way which looks like library input.

View File

@@ -49,7 +49,7 @@ module UnsafeShellCommandConstruction {
/**
* A parameter of an exported function, seen as a source for shell command constructed from library input.
*/
class ExternalInputSource extends Source, DataFlow::SourceNode {
class ExternalInputSource extends Source {
ExternalInputSource() {
this = Exports::getALibraryInputParameter() and
not (

View File

@@ -138,7 +138,7 @@ module PolynomialReDoS {
/**
* A parameter of an exported function, seen as a source for polynomial-redos.
*/
class ExternalInputSource extends Source, DataFlow::SourceNode {
class ExternalInputSource extends Source {
ExternalInputSource() { this = Exports::getALibraryInputParameter() }
override string getKind() { result = "library" }

View File

@@ -15,11 +15,13 @@ basicBlock
| arguments.js:1:1:12:4 | (functi ... );\\n})() | arguments.js:1:1:1:0 | entry node of <toplevel> |
| arguments.js:1:1:12:4 | exceptional return of (functi ... );\\n})() | arguments.js:1:1:1:0 | entry node of <toplevel> |
| arguments.js:1:2:1:1 | this | arguments.js:1:2:1:1 | entry node of functio ... , 3);\\n} |
| arguments.js:1:2:12:1 | 'arguments' object of anonymous function | arguments.js:1:2:1:1 | entry node of functio ... , 3);\\n} |
| arguments.js:1:2:12:1 | exceptional return of anonymous function | arguments.js:1:2:1:1 | entry node of functio ... , 3);\\n} |
| arguments.js:1:2:12:1 | functio ... , 3);\\n} | arguments.js:1:1:1:0 | entry node of <toplevel> |
| arguments.js:1:2:12:1 | return of anonymous function | arguments.js:1:2:1:1 | entry node of functio ... , 3);\\n} |
| arguments.js:2:5:2:4 | this | arguments.js:2:5:2:4 | entry node of functio ... ;\\n } |
| arguments.js:2:5:2:5 | arguments | arguments.js:2:5:2:4 | entry node of functio ... ;\\n } |
| arguments.js:2:5:10:5 | 'arguments' object of function f | arguments.js:2:5:2:4 | entry node of functio ... ;\\n } |
| arguments.js:2:5:10:5 | exceptional return of function f | arguments.js:2:5:2:4 | entry node of functio ... ;\\n } |
| arguments.js:2:5:10:5 | functio ... ;\\n } | arguments.js:1:2:1:1 | entry node of functio ... , 3);\\n} |
| arguments.js:2:5:10:5 | return of function f | arguments.js:2:5:2:4 | entry node of functio ... ;\\n } |
@@ -66,6 +68,7 @@ basicBlock
| arguments.js:11:13:11:13 | 3 | arguments.js:1:2:1:1 | entry node of functio ... , 3);\\n} |
| eval.js:1:1:1:0 | this | eval.js:1:1:1:0 | entry node of <toplevel> |
| eval.js:1:1:1:0 | this | eval.js:1:1:1:0 | entry node of functio ... eval`\\n} |
| eval.js:1:1:5:1 | 'arguments' object of function k | eval.js:1:1:1:0 | entry node of functio ... eval`\\n} |
| eval.js:1:1:5:1 | exceptional return of function k | eval.js:1:1:1:0 | entry node of functio ... eval`\\n} |
| eval.js:1:1:5:1 | functio ... eval`\\n} | eval.js:1:1:1:0 | entry node of <toplevel> |
| eval.js:1:1:5:1 | return of function k | eval.js:1:1:1:0 | entry node of functio ... eval`\\n} |
@@ -85,6 +88,7 @@ basicBlock
| sources.js:1:5:1:12 | (x => x) | sources.js:1:1:1:0 | entry node of <toplevel> |
| sources.js:1:6:1:6 | x | sources.js:1:6:1:5 | entry node of x => x |
| sources.js:1:6:1:6 | x | sources.js:1:6:1:5 | entry node of x => x |
| sources.js:1:6:1:11 | 'arguments' object of anonymous function | sources.js:1:6:1:5 | entry node of x => x |
| sources.js:1:6:1:11 | exceptional return of anonymous function | sources.js:1:6:1:5 | entry node of x => x |
| sources.js:1:6:1:11 | return of anonymous function | sources.js:1:6:1:5 | entry node of x => x |
| sources.js:1:6:1:11 | x => x | sources.js:1:1:1:0 | entry node of <toplevel> |
@@ -93,6 +97,7 @@ basicBlock
| sources.js:3:1:5:6 | (functi ... \\n})(23) | sources.js:1:1:1:0 | entry node of <toplevel> |
| sources.js:3:1:5:6 | exceptional return of (functi ... \\n})(23) | sources.js:1:1:1:0 | entry node of <toplevel> |
| sources.js:3:2:3:1 | this | sources.js:3:2:3:1 | entry node of functio ... x+19;\\n} |
| sources.js:3:2:5:1 | 'arguments' object of anonymous function | sources.js:3:2:3:1 | entry node of functio ... x+19;\\n} |
| sources.js:3:2:5:1 | exceptional return of anonymous function | sources.js:3:2:3:1 | entry node of functio ... x+19;\\n} |
| sources.js:3:2:5:1 | functio ... x+19;\\n} | sources.js:1:1:1:0 | entry node of <toplevel> |
| sources.js:3:2:5:1 | return of anonymous function | sources.js:3:2:3:1 | entry node of functio ... x+19;\\n} |
@@ -104,6 +109,7 @@ basicBlock
| sources.js:5:4:5:5 | 23 | sources.js:1:1:1:0 | entry node of <toplevel> |
| sources.js:7:1:7:3 | /x/ | sources.js:1:1:1:0 | entry node of <toplevel> |
| sources.js:9:1:9:0 | this | sources.js:9:1:9:0 | entry node of functio ... ey; }\\n} |
| sources.js:9:1:12:1 | 'arguments' object of function foo | sources.js:9:1:9:0 | entry node of functio ... ey; }\\n} |
| sources.js:9:1:12:1 | exceptional return of function foo | sources.js:12:2:12:1 | exit node of functio ... ey; }\\n} |
| sources.js:9:1:12:1 | functio ... ey; }\\n} | sources.js:1:1:1:0 | entry node of <toplevel> |
| sources.js:9:1:12:1 | return of function foo | sources.js:12:2:12:1 | exit node of functio ... ey; }\\n} |
@@ -140,6 +146,7 @@ basicBlock
| tst2.ts:4:3:4:3 | x | tst2.ts:1:1:1:0 | entry node of <toplevel> |
| tst2.ts:7:1:7:0 | A | tst2.ts:7:1:7:0 | entry node of functio ... = 23;\\n} |
| tst2.ts:7:1:7:0 | this | tst2.ts:7:1:7:0 | entry node of functio ... = 23;\\n} |
| tst2.ts:7:1:9:1 | 'arguments' object of function setX | tst2.ts:7:1:7:0 | entry node of functio ... = 23;\\n} |
| tst2.ts:7:1:9:1 | exceptional return of function setX | tst2.ts:7:1:7:0 | entry node of functio ... = 23;\\n} |
| tst2.ts:7:1:9:1 | functio ... = 23;\\n} | tst2.ts:1:1:1:0 | entry node of <toplevel> |
| tst2.ts:7:1:9:1 | return of function setX | tst2.ts:7:1:7:0 | entry node of functio ... = 23;\\n} |
@@ -160,6 +167,7 @@ basicBlock
| tst2.ts:13:7:13:16 | StringList | tst2.ts:1:1:1:0 | entry node of <toplevel> |
| tst2.ts:13:26:13:29 | List | tst2.ts:1:1:1:0 | entry node of <toplevel> |
| tst2.ts:13:26:13:37 | List<string> | tst2.ts:1:1:1:0 | entry node of <toplevel> |
| tst2.ts:13:39:13:38 | 'arguments' object of default constructor of class StringList | tst2.ts:13:39:13:38 | entry node of (...arg ... rgs); } |
| tst2.ts:13:39:13:38 | (...arg ... rgs); } | tst2.ts:1:1:1:0 | entry node of <toplevel> |
| tst2.ts:13:39:13:38 | ...args | tst2.ts:13:39:13:38 | entry node of (...arg ... rgs); } |
| tst2.ts:13:39:13:38 | args | tst2.ts:13:39:13:38 | entry node of (...arg ... rgs); } |
@@ -221,6 +229,7 @@ basicBlock
| tst.js:16:1:20:9 | (functi ... ("arg") | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:16:1:20:9 | exceptional return of (functi ... ("arg") | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:16:2:16:1 | this | tst.js:16:2:16:1 | entry node of functio ... n "";\\n} |
| tst.js:16:2:20:1 | 'arguments' object of function f | tst.js:16:2:16:1 | entry node of functio ... n "";\\n} |
| tst.js:16:2:20:1 | exceptional return of function f | tst.js:20:2:20:1 | exit node of functio ... n "";\\n} |
| tst.js:16:2:20:1 | functio ... n "";\\n} | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:16:2:20:1 | return of function f | tst.js:20:2:20:1 | exit node of functio ... n "";\\n} |
@@ -254,12 +263,14 @@ basicBlock
| tst.js:28:1:30:3 | (() =>\\n ... les\\n)() | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:28:1:30:3 | exceptional return of (() =>\\n ... les\\n)() | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:28:2:28:1 | x | tst.js:28:2:28:1 | entry node of () =>\\n x |
| tst.js:28:2:29:3 | 'arguments' object of anonymous function | tst.js:28:2:28:1 | entry node of () =>\\n x |
| tst.js:28:2:29:3 | () =>\\n x | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:28:2:29:3 | exceptional return of anonymous function | tst.js:28:2:28:1 | entry node of () =>\\n x |
| tst.js:28:2:29:3 | return of anonymous function | tst.js:28:2:28:1 | entry node of () =>\\n x |
| tst.js:29:3:29:3 | x | tst.js:28:2:28:1 | entry node of () =>\\n x |
| tst.js:32:1:32:0 | this | tst.js:32:1:32:0 | entry node of functio ... ables\\n} |
| tst.js:32:1:32:0 | x | tst.js:32:1:32:0 | entry node of functio ... ables\\n} |
| tst.js:32:1:34:1 | 'arguments' object of function g | tst.js:32:1:32:0 | entry node of functio ... ables\\n} |
| tst.js:32:1:34:1 | exceptional return of function g | tst.js:32:1:32:0 | entry node of functio ... ables\\n} |
| tst.js:32:1:34:1 | functio ... ables\\n} | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:32:1:34:1 | return of function g | tst.js:32:1:32:0 | entry node of functio ... ables\\n} |
@@ -283,6 +294,7 @@ basicBlock
| tst.js:39:3:41:3 | m() {\\n this;\\n } | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:39:3:41:3 | m() {\\n this;\\n } | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:39:4:39:3 | this | tst.js:39:4:39:3 | entry node of () {\\n this;\\n } |
| tst.js:39:4:41:3 | 'arguments' object of method m | tst.js:39:4:39:3 | entry node of () {\\n this;\\n } |
| tst.js:39:4:41:3 | () {\\n this;\\n } | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:39:4:41:3 | exceptional return of method m | tst.js:39:4:39:3 | entry node of () {\\n this;\\n } |
| tst.js:39:4:41:3 | return of method m | tst.js:39:4:39:3 | entry node of () {\\n this;\\n } |
@@ -307,6 +319,7 @@ basicBlock
| tst.js:50:3:53:3 | constru ... et`\\n } | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:50:3:53:3 | constru ... et`\\n } | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:50:14:50:13 | this | tst.js:50:14:50:13 | entry node of () {\\n ... et`\\n } |
| tst.js:50:14:53:3 | 'arguments' object of constructor of class A | tst.js:50:14:50:13 | entry node of () {\\n ... et`\\n } |
| tst.js:50:14:53:3 | () {\\n ... et`\\n } | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:50:14:53:3 | exceptional return of constructor of class A | tst.js:50:14:50:13 | entry node of () {\\n ... et`\\n } |
| tst.js:50:14:53:3 | return of constructor of class A | tst.js:50:14:50:13 | entry node of () {\\n ... et`\\n } |
@@ -333,6 +346,7 @@ basicBlock
| tst.js:62:1:62:4 | o::g | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:62:4:62:4 | g | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:64:1:64:0 | this | tst.js:64:1:64:0 | entry node of functio ... lysed\\n} |
| tst.js:64:1:67:1 | 'arguments' object of function h | tst.js:64:1:64:0 | entry node of functio ... lysed\\n} |
| tst.js:64:1:67:1 | exceptional return of function h | tst.js:64:1:64:0 | entry node of functio ... lysed\\n} |
| tst.js:64:1:67:1 | functio ... lysed\\n} | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:64:1:67:1 | return of function h | tst.js:64:1:64:0 | entry node of functio ... lysed\\n} |
@@ -356,6 +370,7 @@ basicBlock
| tst.js:69:6:69:9 | next | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:69:11:69:12 | 23 | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:71:1:71:0 | this | tst.js:71:1:71:0 | entry node of async f ... lysed\\n} |
| tst.js:71:1:73:1 | 'arguments' object of function k | tst.js:71:1:71:0 | entry node of async f ... lysed\\n} |
| tst.js:71:1:73:1 | async f ... lysed\\n} | tst.js:16:1:20:10 | (functi ... "arg"); |
| tst.js:71:1:73:1 | exceptional return of function k | tst.js:71:1:71:0 | entry node of async f ... lysed\\n} |
| tst.js:71:1:73:1 | return of function k | tst.js:71:1:71:0 | entry node of async f ... lysed\\n} |
@@ -398,6 +413,7 @@ basicBlock
| tst.js:87:1:96:2 | (functi ... r: 0\\n}) | tst.js:85:5:85:28 | vs2 = ( ... o) v ) |
| tst.js:87:1:96:2 | exceptional return of (functi ... r: 0\\n}) | tst.js:85:5:85:28 | vs2 = ( ... o) v ) |
| tst.js:87:2:87:1 | this | tst.js:87:2:87:1 | entry node of functio ... + z;\\n} |
| tst.js:87:2:92:1 | 'arguments' object of anonymous function | tst.js:87:2:87:1 | entry node of functio ... + z;\\n} |
| tst.js:87:2:92:1 | exceptional return of anonymous function | tst.js:87:2:87:1 | entry node of functio ... + z;\\n} |
| tst.js:87:2:92:1 | functio ... + z;\\n} | tst.js:85:5:85:28 | vs2 = ( ... o) v ) |
| tst.js:87:2:92:1 | return of anonymous function | tst.js:87:2:87:1 | entry node of functio ... + z;\\n} |
@@ -451,6 +467,7 @@ basicBlock
| tst.js:98:1:103:17 | (functi ... 3, 0 ]) | tst.js:85:5:85:28 | vs2 = ( ... o) v ) |
| tst.js:98:1:103:17 | exceptional return of (functi ... 3, 0 ]) | tst.js:85:5:85:28 | vs2 = ( ... o) v ) |
| tst.js:98:2:98:1 | this | tst.js:98:2:98:1 | entry node of functio ... + z;\\n} |
| tst.js:98:2:103:1 | 'arguments' object of anonymous function | tst.js:98:2:98:1 | entry node of functio ... + z;\\n} |
| tst.js:98:2:103:1 | exceptional return of anonymous function | tst.js:98:2:98:1 | entry node of functio ... + z;\\n} |
| tst.js:98:2:103:1 | functio ... + z;\\n} | tst.js:85:5:85:28 | vs2 = ( ... o) v ) |
| tst.js:98:2:103:1 | return of anonymous function | tst.js:98:2:98:1 | entry node of functio ... + z;\\n} |
@@ -492,6 +509,7 @@ basicBlock
| tst.js:105:6:105:6 | y | tst.js:105:6:105:6 | y |
| tst.js:107:1:113:2 | (functi ... v2c;\\n}) | tst.js:107:1:113:3 | (functi ... 2c;\\n}); |
| tst.js:107:2:107:1 | this | tst.js:107:2:107:1 | entry node of functio ... v2c;\\n} |
| tst.js:107:2:113:1 | 'arguments' object of anonymous function | tst.js:107:2:107:1 | entry node of functio ... v2c;\\n} |
| tst.js:107:2:113:1 | exceptional return of anonymous function | tst.js:107:2:107:1 | entry node of functio ... v2c;\\n} |
| tst.js:107:2:113:1 | functio ... v2c;\\n} | tst.js:107:1:113:3 | (functi ... 2c;\\n}); |
| tst.js:107:2:113:1 | return of anonymous function | tst.js:107:2:107:1 | entry node of functio ... v2c;\\n} |
@@ -918,6 +936,11 @@ flowStep
| arguments.js:2:5:2:5 | arguments | arguments.js:4:28:4:36 | arguments |
| arguments.js:2:5:2:5 | arguments | arguments.js:5:25:5:33 | arguments |
| arguments.js:2:5:2:5 | arguments | arguments.js:6:20:6:28 | arguments |
| arguments.js:2:5:10:5 | 'arguments' object of function f | arguments.js:4:28:4:36 | arguments |
| arguments.js:2:5:10:5 | 'arguments' object of function f | arguments.js:5:25:5:33 | arguments |
| arguments.js:2:5:10:5 | 'arguments' object of function f | arguments.js:6:20:6:28 | arguments |
| arguments.js:2:5:10:5 | 'arguments' object of function f | arguments.js:8:9:8:17 | arguments |
| arguments.js:2:5:10:5 | 'arguments' object of function f | arguments.js:9:27:9:35 | arguments |
| arguments.js:2:5:10:5 | functio ... ;\\n } | arguments.js:2:14:2:14 | f |
| arguments.js:2:14:2:14 | f | arguments.js:11:5:11:5 | f |
| arguments.js:2:16:2:16 | x | arguments.js:2:16:2:16 | x |
@@ -1421,9 +1444,11 @@ sources
| arguments.js:1:1:1:0 | this |
| arguments.js:1:1:12:4 | (functi ... );\\n})() |
| arguments.js:1:2:1:1 | this |
| arguments.js:1:2:12:1 | 'arguments' object of anonymous function |
| arguments.js:1:2:12:1 | functio ... , 3);\\n} |
| arguments.js:1:2:12:1 | return of anonymous function |
| arguments.js:2:5:2:4 | this |
| arguments.js:2:5:10:5 | 'arguments' object of function f |
| arguments.js:2:5:10:5 | functio ... ;\\n } |
| arguments.js:2:5:10:5 | return of function f |
| arguments.js:2:16:2:16 | x |
@@ -1435,6 +1460,7 @@ sources
| arguments.js:11:5:11:14 | f(1, 2, 3) |
| eval.js:1:1:1:0 | this |
| eval.js:1:1:1:0 | this |
| eval.js:1:1:5:1 | 'arguments' object of function k |
| eval.js:1:1:5:1 | functio ... eval`\\n} |
| eval.js:1:1:5:1 | return of function k |
| eval.js:3:3:3:6 | eval |
@@ -1444,15 +1470,18 @@ sources
| sources.js:1:1:1:0 | this |
| sources.js:1:1:1:12 | new (x => x) |
| sources.js:1:6:1:6 | x |
| sources.js:1:6:1:11 | 'arguments' object of anonymous function |
| sources.js:1:6:1:11 | return of anonymous function |
| sources.js:1:6:1:11 | x => x |
| sources.js:3:1:5:6 | (functi ... \\n})(23) |
| sources.js:3:2:3:1 | this |
| sources.js:3:2:5:1 | 'arguments' object of anonymous function |
| sources.js:3:2:5:1 | functio ... x+19;\\n} |
| sources.js:3:2:5:1 | return of anonymous function |
| sources.js:3:11:3:11 | x |
| sources.js:7:1:7:3 | /x/ |
| sources.js:9:1:9:0 | this |
| sources.js:9:1:12:1 | 'arguments' object of function foo |
| sources.js:9:1:12:1 | functio ... ey; }\\n} |
| sources.js:9:1:12:1 | return of function foo |
| sources.js:9:14:9:18 | array |
@@ -1462,12 +1491,14 @@ sources
| tst2.ts:1:1:1:0 | this |
| tst2.ts:3:3:3:8 | setX() |
| tst2.ts:7:1:7:0 | this |
| tst2.ts:7:1:9:1 | 'arguments' object of function setX |
| tst2.ts:7:1:9:1 | functio ... = 23;\\n} |
| tst2.ts:7:1:9:1 | return of function setX |
| tst2.ts:8:3:8:5 | A.x |
| tst2.ts:11:11:11:13 | A.x |
| tst2.ts:13:1:13:40 | class S ... ing> {} |
| tst2.ts:13:26:13:29 | List |
| tst2.ts:13:39:13:38 | 'arguments' object of default constructor of class StringList |
| tst2.ts:13:39:13:38 | (...arg ... rgs); } |
| tst2.ts:13:39:13:38 | args |
| tst2.ts:13:39:13:38 | return of default constructor of class StringList |
@@ -1480,6 +1511,7 @@ sources
| tst.js:4:9:4:12 | "hi" |
| tst.js:16:1:20:9 | (functi ... ("arg") |
| tst.js:16:2:16:1 | this |
| tst.js:16:2:20:1 | 'arguments' object of function f |
| tst.js:16:2:20:1 | functio ... n "";\\n} |
| tst.js:16:2:20:1 | return of function f |
| tst.js:16:13:16:13 | a |
@@ -1490,15 +1522,18 @@ sources
| tst.js:20:4:20:8 | "arg" |
| tst.js:22:7:22:18 | readFileSync |
| tst.js:28:1:30:3 | (() =>\\n ... les\\n)() |
| tst.js:28:2:29:3 | 'arguments' object of anonymous function |
| tst.js:28:2:29:3 | () =>\\n x |
| tst.js:28:2:29:3 | return of anonymous function |
| tst.js:32:1:32:0 | this |
| tst.js:32:1:34:1 | 'arguments' object of function g |
| tst.js:32:1:34:1 | functio ... ables\\n} |
| tst.js:32:1:34:1 | return of function g |
| tst.js:32:12:32:12 | b |
| tst.js:35:1:35:7 | g(true) |
| tst.js:37:9:42:1 | {\\n x: ... ;\\n }\\n} |
| tst.js:39:4:39:3 | this |
| tst.js:39:4:41:3 | 'arguments' object of method m |
| tst.js:39:4:41:3 | () {\\n this;\\n } |
| tst.js:39:4:41:3 | return of method m |
| tst.js:43:1:43:3 | o.x |
@@ -1510,6 +1545,7 @@ sources
| tst.js:49:1:54:1 | class A ... `\\n }\\n} |
| tst.js:49:17:49:17 | B |
| tst.js:50:14:50:13 | this |
| tst.js:50:14:53:3 | 'arguments' object of constructor of class A |
| tst.js:50:14:53:3 | () {\\n ... et`\\n } |
| tst.js:50:14:53:3 | return of constructor of class A |
| tst.js:51:5:51:13 | super(42) |
@@ -1519,6 +1555,7 @@ sources
| tst.js:61:3:61:5 | o.m |
| tst.js:62:1:62:4 | o::g |
| tst.js:64:1:64:0 | this |
| tst.js:64:1:67:1 | 'arguments' object of function h |
| tst.js:64:1:67:1 | functio ... lysed\\n} |
| tst.js:64:1:67:1 | return of function h |
| tst.js:65:3:65:10 | yield 42 |
@@ -1527,6 +1564,7 @@ sources
| tst.js:69:1:69:9 | iter.next |
| tst.js:69:1:69:13 | iter.next(23) |
| tst.js:71:1:71:0 | this |
| tst.js:71:1:73:1 | 'arguments' object of function k |
| tst.js:71:1:73:1 | async f ... lysed\\n} |
| tst.js:71:1:73:1 | return of function k |
| tst.js:72:3:72:11 | await p() |
@@ -1539,6 +1577,7 @@ sources
| tst.js:85:11:85:28 | ( for (v of o) v ) |
| tst.js:87:1:96:2 | (functi ... r: 0\\n}) |
| tst.js:87:2:87:1 | this |
| tst.js:87:2:92:1 | 'arguments' object of anonymous function |
| tst.js:87:2:92:1 | functio ... + z;\\n} |
| tst.js:87:2:92:1 | return of anonymous function |
| tst.js:87:11:87:24 | { p: x, ...o } |
@@ -1549,6 +1588,7 @@ sources
| tst.js:92:4:96:1 | {\\n p: ... r: 0\\n} |
| tst.js:98:1:103:17 | (functi ... 3, 0 ]) |
| tst.js:98:2:98:1 | this |
| tst.js:98:2:103:1 | 'arguments' object of anonymous function |
| tst.js:98:2:103:1 | functio ... + z;\\n} |
| tst.js:98:2:103:1 | return of anonymous function |
| tst.js:98:11:98:24 | [ x, ...rest ] |
@@ -1558,6 +1598,7 @@ sources
| tst.js:101:7:101:7 | z |
| tst.js:103:4:103:16 | [ 19, 23, 0 ] |
| tst.js:107:2:107:1 | this |
| tst.js:107:2:113:1 | 'arguments' object of anonymous function |
| tst.js:107:2:113:1 | functio ... v2c;\\n} |
| tst.js:107:2:113:1 | return of anonymous function |
| tst.js:108:7:108:9 | v1a |

View File

@@ -14,6 +14,7 @@ dataFlow
| callback.js:16:14:16:21 | "source" | callback.js:13:14:13:14 | x |
| callback.js:17:15:17:23 | "source2" | callback.js:13:14:13:14 | x |
| callback.js:27:15:27:23 | "source3" | callback.js:13:14:13:14 | x |
| destructuring.js:2:16:2:24 | "tainted" | destructuring.js:5:14:5:20 | tainted |
| destructuring.js:2:16:2:24 | "tainted" | destructuring.js:9:15:9:22 | tainted2 |
| destructuring.js:19:15:19:23 | "tainted" | destructuring.js:14:15:14:15 | p |
| destructuring.js:20:15:20:28 | "also tainted" | destructuring.js:15:15:15:15 | r |
@@ -201,6 +202,7 @@ germanFlow
| callback.js:17:15:17:23 | "source2" | callback.js:13:14:13:14 | x |
| callback.js:27:15:27:23 | "source3" | callback.js:13:14:13:14 | x |
| custom.js:1:14:1:26 | "verschmutzt" | custom.js:2:15:2:20 | quelle |
| destructuring.js:2:16:2:24 | "tainted" | destructuring.js:5:14:5:20 | tainted |
| destructuring.js:2:16:2:24 | "tainted" | destructuring.js:9:15:9:22 | tainted2 |
| destructuring.js:19:15:19:23 | "tainted" | destructuring.js:14:15:14:15 | p |
| destructuring.js:20:15:20:28 | "also tainted" | destructuring.js:15:15:15:15 | r |

View File

@@ -1,4 +1,15 @@
typeInferenceMismatch
| call-apply.js:27:14:27:21 | source() | call-apply.js:3:1:5:1 | 'arguments' object of function foo1 |
| call-apply.js:27:14:27:21 | source() | call-apply.js:7:1:9:1 | 'arguments' object of function foo2 |
| call-apply.js:27:14:27:21 | source() | call-apply.js:12:10:12:30 | reflective call |
| call-apply.js:27:14:27:21 | source() | call-apply.js:16:10:16:40 | reflective call |
| call-apply.js:27:14:27:21 | source() | call-apply.js:23:1:25:1 | 'arguments' object of function foo1_sink |
| call-apply.js:27:14:27:21 | source() | call-apply.js:29:6:29:32 | reflective call |
| call-apply.js:27:14:27:21 | source() | call-apply.js:32:6:32:35 | reflective call |
| call-apply.js:27:14:27:21 | source() | call-apply.js:33:6:33:35 | reflective call |
| call-apply.js:27:14:27:21 | source() | call-apply.js:64:3:66:3 | 'arguments' object of function sinkArguments1 |
| call-apply.js:27:14:27:21 | source() | call-apply.js:67:3:69:3 | 'arguments' object of function sinkArguments0 |
| call-apply.js:27:14:27:21 | source() | call-apply.js:71:3:74:3 | 'arguments' object of function fowardArguments |
| destruct.js:20:7:20:14 | source() | destruct.js:13:14:13:19 | [a, b] |
#select
| access-path-sanitizer.js:2:18:2:25 | source() | access-path-sanitizer.js:4:8:4:12 | obj.x |
@@ -12,6 +23,19 @@ typeInferenceMismatch
| array-mutation.js:31:33:31:40 | source() | array-mutation.js:32:8:32:8 | h |
| array-mutation.js:35:36:35:43 | source() | array-mutation.js:36:8:36:8 | i |
| array-mutation.js:39:17:39:24 | source() | array-mutation.js:40:8:40:8 | j |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:17:8:17:13 | arr[1] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:22:8:22:13 | arr[6] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:27:8:27:13 | arr[0] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:28:8:28:13 | arr[1] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:33:8:33:13 | arr[0] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:34:8:34:13 | arr[1] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:35:8:35:13 | arr[2] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:36:8:36:13 | arr[3] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:37:8:37:13 | arr[4] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:38:8:38:13 | arr[5] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:43:10:43:15 | arr[i] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:55:10:55:15 | arr[i] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:61:10:61:13 | item |
| arrays.js:2:15:2:22 | source() | arrays.js:5:10:5:20 | arrify(foo) |
| arrays.js:2:15:2:22 | source() | arrays.js:8:10:8:22 | arrayIfy(foo) |
| arrays.js:2:15:2:22 | source() | arrays.js:11:10:11:28 | union(["bla"], foo) |
@@ -28,6 +52,16 @@ typeInferenceMismatch
| bound-function.js:45:10:45:17 | source() | bound-function.js:45:6:45:18 | id3(source()) |
| bound-function.js:49:12:49:19 | source() | bound-function.js:54:6:54:14 | source0() |
| bound-function.js:49:12:49:19 | source() | bound-function.js:55:6:55:14 | source1() |
| call-apply.js:27:14:27:21 | source() | call-apply.js:24:8:24:11 | arg1 |
| call-apply.js:27:14:27:21 | source() | call-apply.js:29:6:29:32 | foo1.ca ... ce, "") |
| call-apply.js:27:14:27:21 | source() | call-apply.js:32:6:32:35 | foo1.ap ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:33:6:33:35 | foo2.ap ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:40:6:40:29 | foo1_ap ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:46:6:46:28 | foo1_ca ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:47:6:47:28 | foo1_ca ... ource]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:65:10:65:21 | arguments[1] |
| call-apply.js:27:14:27:21 | source() | call-apply.js:68:10:68:21 | arguments[0] |
| call-apply.js:87:17:87:24 | source() | call-apply.js:84:8:84:11 | this |
| callbacks.js:4:6:4:13 | source() | callbacks.js:34:27:34:27 | x |
| callbacks.js:4:6:4:13 | source() | callbacks.js:35:27:35:27 | x |
| callbacks.js:5:6:5:13 | source() | callbacks.js:34:27:34:27 | x |

View File

@@ -1,5 +1,12 @@
| access-path-sanitizer.js:2:18:2:25 | source() | access-path-sanitizer.js:4:8:4:12 | obj.x |
| advanced-callgraph.js:2:13:2:20 | source() | advanced-callgraph.js:6:22:6:22 | v |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:17:8:17:13 | arr[1] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:22:8:22:13 | arr[6] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:28:8:28:13 | arr[1] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:34:8:34:13 | arr[1] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:43:10:43:15 | arr[i] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:55:10:55:15 | arr[i] |
| arrays-init.js:2:16:2:23 | source() | arrays-init.js:61:10:61:13 | item |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:4:8:4:8 | x |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:7:10:7:10 | x |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:10:10:10:10 | x |
@@ -12,6 +19,12 @@
| bound-function.js:45:10:45:17 | source() | bound-function.js:45:6:45:18 | id3(source()) |
| bound-function.js:49:12:49:19 | source() | bound-function.js:54:6:54:14 | source0() |
| bound-function.js:49:12:49:19 | source() | bound-function.js:55:6:55:14 | source1() |
| call-apply.js:27:14:27:21 | source() | call-apply.js:24:8:24:11 | arg1 |
| call-apply.js:27:14:27:21 | source() | call-apply.js:29:6:29:32 | foo1.ca ... ce, "") |
| call-apply.js:27:14:27:21 | source() | call-apply.js:32:6:32:35 | foo1.ap ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:46:6:46:28 | foo1_ca ... e, ""]) |
| call-apply.js:27:14:27:21 | source() | call-apply.js:68:10:68:21 | arguments[0] |
| call-apply.js:87:17:87:24 | source() | call-apply.js:84:8:84:11 | this |
| callbacks.js:4:6:4:13 | source() | callbacks.js:34:27:34:27 | x |
| callbacks.js:4:6:4:13 | source() | callbacks.js:35:27:35:27 | x |
| callbacks.js:5:6:5:13 | source() | callbacks.js:34:27:34:27 | x |

View File

@@ -0,0 +1,63 @@
(function () {
let source = source();
var str = "FALSE";
console.log("=== access by index (init by ctor) ===");
var arr = new Array(2);
arr[0] = str;
arr[1] = source;
arr[2] = 'b';
arr[3] = 'c';
arr[4] = 'd';
arr[5] = 'e';
arr[6] = source;
sink(arr[0]); // OK
sink(arr[1]); // NOT OK
sink(arr[2]); // OK
sink(arr[3]); // OK
sink(arr[4]); // OK
sink(arr[5]); // OK
sink(arr[6]); // NOT OK
sink(str); // OK
console.log("=== access by index (init by [...]) ===");
var arr = [str, source];
sink(arr[0]); // OK
sink(arr[1]); // NOT OK
sink(str); // OK
console.log("=== access by index (init by [...], array.lenght > 5) ===");
var arr = [str, source, 'b', 'c', 'd', source];
sink(arr[0]); // OK
sink(arr[1]); // NOT OK
sink(arr[2]); // OK
sink(arr[3]); // OK
sink(arr[4]); // OK
sink(arr[5]); // NOT OK - but not flagged [INCONSISTENCY]
console.log("=== access in for (init by [...]) ===");
var arr = [str, source];
for (let i = 0; i < arr.length; i++) {
sink(arr[i]); // NOT OK
}
console.log("=== access in for (init by [...]) w/o source ===");
var arr = [str, 'a'];
for (let i = 0; i < arr.length; i++) {
sink(arr[i]); // OK
}
console.log("=== access in for (init by [...], array.lenght > 5) ===");
var arr = [str, 'a', 'b', 'c', 'd', source];
for (let i = 0; i < arr.length; i++) {
sink(arr[i]); // NOT OK
}
console.log("=== access in forof (init by [...]) ===");
var arr = [str, source];
for (const item of arr) {
sink(item); // NOT OK
}
}());

View File

@@ -0,0 +1,87 @@
import * as foolib from 'foolib';
function foo1(arg1, arg2) {
return arg1;
}
function foo2(arg1, arg2) {
return arg2;
}
function foo1_apply(arr) {
return foo1.apply(this, arr);
}
function foo1_call(arr) {
return foo1.call(this, arr[0], arr[1]);
}
function foo1_apply_sink(arr) {
foo1_sink.apply(this, arr);
}
function foo1_sink(arg1, arg2) {
sink(arg1); // NOT OK
}
var source = source();
sink(foo1.call(null, source, "")); // NOT OK
sink(foo2.call(null, source, "")); // OK
sink(foo1.apply(null, [source, ""])); // NOT OK
sink(foo2.apply(null, [source, ""])); // OK
// doesn't work due to fundamental limitations of our dataflow analysis.
// exactly (and I mean exactly) the same thing happens in the below `obj.foo` example.
// in general we don't track flow that first goes through a call, and then a return, unless we can summarize it.
// in the other examples we can summarize the flow, because it's quite simple, but here we can't.
// (try to read the QLDoc in the top of `Configuration.qll`, that might help).
sink(foo1_apply([source, ""])); // NOT OK - but not flagged [INCONSISTENCY]
foo1_apply_sink([source, ""]); // This works, because we don't need a return after a call (the sink is inside the called function).
sink(foo1_apply.apply(["", source])); // OK
sink(foo1_call([source, ""])); // NOT OK
sink(foo1_call(["", source])); // OK
var obj = {
foo: source(),
bar: "safe"
};
function foo(x) {
return bar(x);
}
function bar(x) {
return x.foo;
}
sink(foo(obj)); // NOT OK - but not flagged [INCONSISTENCY]
function argumentsObject() {
function sinkArguments1() {
sink(arguments[1]); // OK
}
function sinkArguments0() {
sink(arguments[0]); // NOT OK
}
function fowardArguments() {
sinkArguments1.apply(this, arguments);
sinkArguments0.apply(this, arguments);
}
fowardArguments.apply(this, [source, ""]);
}
function sinksThis() {
sinksThis2.apply(this, arguments);
}
function sinksThis2() {
sink(this); // NOT OK
}
sinksThis.apply(source(), []);

View File

@@ -24,6 +24,7 @@ typeTracking
| tst.js:2:16:2:23 | source() | tst.js:29:14:29:14 | e |
| tst.js:2:16:2:23 | source() | tst.js:33:14:33:14 | e |
| tst.js:2:16:2:23 | source() | tst.js:37:14:37:14 | e |
| tst.js:2:16:2:23 | source() | tst.js:41:14:41:14 | e |
| tst.js:2:16:2:23 | source() | tst.js:45:14:45:14 | e |
| tst.js:2:16:2:23 | source() | tst.js:53:8:53:21 | map.get("key") |
| tst.js:2:16:2:23 | source() | tst.js:59:8:59:22 | map2.get("foo") |

View File

@@ -39,7 +39,7 @@
}
for (const e of new Set([source])) {
sink(e); // NOT OK (not caught by type-tracking, as it doesn't include array steps).
sink(e); // NOT OK
}
for (const e of new Set(set)) {

View File

@@ -1,5 +1,4 @@
| src/hapi.js:1:1:1:30 | functio ... t, h){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
| src/iterated-handlers.js:4:2:4:22 | functio ... res){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
| src/route-objects.js:7:19:7:38 | function(req, res){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
| src/route-objects.js:8:12:10:5 | (req, res) {\\n\\n } | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
| src/route-objects.js:20:16:22:9 | (req, r ... } | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |

View File

@@ -16,6 +16,7 @@ routeHandler
| src/exported-middleware-attacher.js:2:13:2:32 | function(req, res){} |
| src/handler-in-property.js:5:14:5:33 | function(req, res){} |
| src/handler-in-property.js:12:18:12:37 | function(req, res){} |
| src/iterated-handlers.js:4:2:4:22 | functio ... res){} |
| src/middleware-attacher-getter.js:4:17:4:36 | function(req, res){} |
| src/middleware-attacher-getter.js:19:19:19:38 | function(req, res){} |
| src/middleware-attacher-getter.js:29:32:29:51 | function(req, res){} |

View File

@@ -32,6 +32,7 @@
| lib/lib.js:1:15:1:16 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding a*b |
| lib/lib.js:8:3:8:4 | f* | Strings with many repetitions of 'f' can start matching anywhere after the start of the preceeding f*g |
| lib/lib.js:28:3:28:4 | f* | Strings with many repetitions of 'f' can start matching anywhere after the start of the preceeding f*g |
| lib/lib.js:36:3:36:4 | f* | Strings with many repetitions of 'f' can start matching anywhere after the start of the preceeding f*g |
| lib/moduleLib/moduleLib.js:2:3:2:4 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding a*b |
| lib/otherLib/js/src/index.js:2:3:2:4 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding a*b |
| lib/snapdragon.js:7:28:7:29 | a* | Strings starting with 'a' and with many repetitions of 'a' can start matching anywhere after the start of the preceeding aa*$ |

View File

@@ -22,6 +22,12 @@ nodes
| lib/lib.js:27:10:27:19 | id("safe") |
| lib/lib.js:28:13:28:13 | y |
| lib/lib.js:28:13:28:13 | y |
| lib/lib.js:32:32:32:40 | arguments |
| lib/lib.js:32:32:32:40 | arguments |
| lib/lib.js:35:1:37:1 | 'arguments' object of function usedWithArguments |
| lib/lib.js:35:28:35:31 | name |
| lib/lib.js:36:13:36:16 | name |
| lib/lib.js:36:13:36:16 | name |
| lib/moduleLib/moduleLib.js:1:28:1:31 | name |
| lib/moduleLib/moduleLib.js:1:28:1:31 | name |
| lib/moduleLib/moduleLib.js:2:13:2:16 | name |
@@ -238,6 +244,11 @@ edges
| lib/lib.js:27:6:27:19 | y | lib/lib.js:28:13:28:13 | y |
| lib/lib.js:27:6:27:19 | y | lib/lib.js:28:13:28:13 | y |
| lib/lib.js:27:10:27:19 | id("safe") | lib/lib.js:27:6:27:19 | y |
| lib/lib.js:32:32:32:40 | arguments | lib/lib.js:35:1:37:1 | 'arguments' object of function usedWithArguments |
| lib/lib.js:32:32:32:40 | arguments | lib/lib.js:35:1:37:1 | 'arguments' object of function usedWithArguments |
| lib/lib.js:35:1:37:1 | 'arguments' object of function usedWithArguments | lib/lib.js:35:28:35:31 | name |
| lib/lib.js:35:28:35:31 | name | lib/lib.js:36:13:36:16 | name |
| lib/lib.js:35:28:35:31 | name | lib/lib.js:36:13:36:16 | name |
| lib/moduleLib/moduleLib.js:1:28:1:31 | name | lib/moduleLib/moduleLib.js:2:13:2:16 | name |
| lib/moduleLib/moduleLib.js:1:28:1:31 | name | lib/moduleLib/moduleLib.js:2:13:2:16 | name |
| lib/moduleLib/moduleLib.js:1:28:1:31 | name | lib/moduleLib/moduleLib.js:2:13:2:16 | name |
@@ -428,6 +439,7 @@ edges
| lib/indirect.js:2:5:2:17 | /k*h/.test(x) | lib/indirect.js:1:32:1:32 | x | lib/indirect.js:2:16:2:16 | x | This $@ that depends on $@ may run slow on strings with many repetitions of 'k'. | lib/indirect.js:2:6:2:7 | k* | regular expression | lib/indirect.js:1:32:1:32 | x | library input |
| lib/lib.js:4:2:4:18 | regexp.test(name) | lib/lib.js:3:28:3:31 | name | lib/lib.js:4:14:4:17 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | lib/lib.js:1:15:1:16 | a* | regular expression | lib/lib.js:3:28:3:31 | name | library input |
| lib/lib.js:8:2:8:17 | /f*g/.test(name) | lib/lib.js:7:19:7:22 | name | lib/lib.js:8:13:8:16 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'f'. | lib/lib.js:8:3:8:4 | f* | regular expression | lib/lib.js:7:19:7:22 | name | library input |
| lib/lib.js:36:2:36:17 | /f*g/.test(name) | lib/lib.js:32:32:32:40 | arguments | lib/lib.js:36:13:36:16 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'f'. | lib/lib.js:36:3:36:4 | f* | regular expression | lib/lib.js:32:32:32:40 | arguments | library input |
| lib/moduleLib/moduleLib.js:2:2:2:17 | /a*b/.test(name) | lib/moduleLib/moduleLib.js:1:28:1:31 | name | lib/moduleLib/moduleLib.js:2:13:2:16 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | lib/moduleLib/moduleLib.js:2:3:2:4 | a* | regular expression | lib/moduleLib/moduleLib.js:1:28:1:31 | name | library input |
| lib/otherLib/js/src/index.js:2:2:2:17 | /a*b/.test(name) | lib/otherLib/js/src/index.js:1:28:1:31 | name | lib/otherLib/js/src/index.js:2:13:2:16 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | lib/otherLib/js/src/index.js:2:3:2:4 | a* | regular expression | lib/otherLib/js/src/index.js:1:28:1:31 | name | library input |
| lib/snapdragon.js:7:15:7:32 | this.match(/aa*$/) | lib/snapdragon.js:3:34:3:38 | input | lib/snapdragon.js:7:15:7:18 | this | This $@ that depends on $@ may run slow on strings starting with 'a' and with many repetitions of 'a'. | lib/snapdragon.js:7:28:7:29 | a* | regular expression | lib/snapdragon.js:3:34:3:38 | input | library input |

View File

@@ -28,4 +28,12 @@ module.exports.safe = function (x) {
/f*g/.test(y); // OK
}
module.exports.useArguments = function () {
usedWithArguments.apply(this, arguments);
}
function usedWithArguments(name) {
/f*g/.test(name); // NOT OK
}
module.exports.snapdragon = require("./snapdragon")

View File

@@ -26,7 +26,8 @@ nodes
| lib.js:15:7:15:10 | path |
| lib.js:15:7:15:13 | path[0] |
| lib.js:20:7:20:25 | path |
| lib.js:20:14:20:25 | arguments[1] |
| lib.js:20:14:20:22 | arguments |
| lib.js:20:14:20:22 | arguments |
| lib.js:20:14:20:25 | arguments[1] |
| lib.js:22:3:22:14 | obj[path[0]] |
| lib.js:22:3:22:14 | obj[path[0]] |
@@ -38,15 +39,23 @@ nodes
| lib.js:26:10:26:21 | obj[path[0]] |
| lib.js:26:14:26:17 | path |
| lib.js:26:14:26:20 | path[0] |
| lib.js:30:9:30:52 | args |
| lib.js:30:16:30:52 | Array.p ... uments) |
| lib.js:30:43:30:51 | arguments |
| lib.js:30:43:30:51 | arguments |
| lib.js:32:7:32:20 | path |
| lib.js:32:14:32:20 | args[1] |
| lib.js:32:14:32:17 | args |
| lib.js:32:14:32:20 | args[1] |
| lib.js:34:3:34:14 | obj[path[0]] |
| lib.js:34:3:34:14 | obj[path[0]] |
| lib.js:34:7:34:10 | path |
| lib.js:34:7:34:13 | path[0] |
| lib.js:38:9:38:36 | args |
| lib.js:38:16:38:36 | Array.f ... uments) |
| lib.js:38:27:38:35 | arguments |
| lib.js:38:27:38:35 | arguments |
| lib.js:40:7:40:20 | path |
| lib.js:40:14:40:20 | args[1] |
| lib.js:40:14:40:17 | args |
| lib.js:40:14:40:20 | args[1] |
| lib.js:42:3:42:14 | obj[path[0]] |
| lib.js:42:3:42:14 | obj[path[0]] |
@@ -71,7 +80,8 @@ nodes
| lib.js:70:17:70:20 | path |
| lib.js:70:17:70:23 | path[0] |
| lib.js:83:7:83:25 | path |
| lib.js:83:14:83:25 | arguments[1] |
| lib.js:83:14:83:22 | arguments |
| lib.js:83:14:83:22 | arguments |
| lib.js:83:14:83:25 | arguments[1] |
| lib.js:86:7:86:26 | proto |
| lib.js:86:15:86:26 | obj[path[0]] |
@@ -89,7 +99,8 @@ nodes
| lib.js:95:3:95:12 | maybeProto |
| lib.js:95:3:95:12 | maybeProto |
| lib.js:104:7:104:24 | one |
| lib.js:104:13:104:24 | arguments[1] |
| lib.js:104:13:104:21 | arguments |
| lib.js:104:13:104:21 | arguments |
| lib.js:104:13:104:24 | arguments[1] |
| lib.js:108:3:108:10 | obj[one] |
| lib.js:108:3:108:10 | obj[one] |
@@ -183,7 +194,8 @@ edges
| lib.js:15:7:15:13 | path[0] | lib.js:15:3:15:14 | obj[path[0]] |
| lib.js:15:7:15:13 | path[0] | lib.js:15:3:15:14 | obj[path[0]] |
| lib.js:20:7:20:25 | path | lib.js:22:7:22:10 | path |
| lib.js:20:14:20:25 | arguments[1] | lib.js:20:7:20:25 | path |
| lib.js:20:14:20:22 | arguments | lib.js:20:14:20:25 | arguments[1] |
| lib.js:20:14:20:22 | arguments | lib.js:20:14:20:25 | arguments[1] |
| lib.js:20:14:20:25 | arguments[1] | lib.js:20:7:20:25 | path |
| lib.js:22:7:22:10 | path | lib.js:22:7:22:13 | path[0] |
| lib.js:22:7:22:13 | path[0] | lib.js:22:3:22:14 | obj[path[0]] |
@@ -193,14 +205,22 @@ edges
| lib.js:26:14:26:17 | path | lib.js:26:14:26:20 | path[0] |
| lib.js:26:14:26:20 | path[0] | lib.js:26:10:26:21 | obj[path[0]] |
| lib.js:26:14:26:20 | path[0] | lib.js:26:10:26:21 | obj[path[0]] |
| lib.js:30:9:30:52 | args | lib.js:32:14:32:17 | args |
| lib.js:30:16:30:52 | Array.p ... uments) | lib.js:30:9:30:52 | args |
| lib.js:30:43:30:51 | arguments | lib.js:30:16:30:52 | Array.p ... uments) |
| lib.js:30:43:30:51 | arguments | lib.js:30:16:30:52 | Array.p ... uments) |
| lib.js:32:7:32:20 | path | lib.js:34:7:34:10 | path |
| lib.js:32:14:32:20 | args[1] | lib.js:32:7:32:20 | path |
| lib.js:32:14:32:17 | args | lib.js:32:14:32:20 | args[1] |
| lib.js:32:14:32:20 | args[1] | lib.js:32:7:32:20 | path |
| lib.js:34:7:34:10 | path | lib.js:34:7:34:13 | path[0] |
| lib.js:34:7:34:13 | path[0] | lib.js:34:3:34:14 | obj[path[0]] |
| lib.js:34:7:34:13 | path[0] | lib.js:34:3:34:14 | obj[path[0]] |
| lib.js:38:9:38:36 | args | lib.js:40:14:40:17 | args |
| lib.js:38:16:38:36 | Array.f ... uments) | lib.js:38:9:38:36 | args |
| lib.js:38:27:38:35 | arguments | lib.js:38:16:38:36 | Array.f ... uments) |
| lib.js:38:27:38:35 | arguments | lib.js:38:16:38:36 | Array.f ... uments) |
| lib.js:40:7:40:20 | path | lib.js:42:7:42:10 | path |
| lib.js:40:14:40:20 | args[1] | lib.js:40:7:40:20 | path |
| lib.js:40:14:40:17 | args | lib.js:40:14:40:20 | args[1] |
| lib.js:40:14:40:20 | args[1] | lib.js:40:7:40:20 | path |
| lib.js:42:7:42:10 | path | lib.js:42:7:42:13 | path[0] |
| lib.js:42:7:42:13 | path[0] | lib.js:42:3:42:14 | obj[path[0]] |
@@ -222,7 +242,8 @@ edges
| lib.js:70:17:70:23 | path[0] | lib.js:70:13:70:24 | obj[path[0]] |
| lib.js:70:17:70:23 | path[0] | lib.js:70:13:70:24 | obj[path[0]] |
| lib.js:83:7:83:25 | path | lib.js:86:19:86:22 | path |
| lib.js:83:14:83:25 | arguments[1] | lib.js:83:7:83:25 | path |
| lib.js:83:14:83:22 | arguments | lib.js:83:14:83:25 | arguments[1] |
| lib.js:83:14:83:22 | arguments | lib.js:83:14:83:25 | arguments[1] |
| lib.js:83:14:83:25 | arguments[1] | lib.js:83:7:83:25 | path |
| lib.js:86:7:86:26 | proto | lib.js:87:10:87:14 | proto |
| lib.js:86:7:86:26 | proto | lib.js:87:10:87:14 | proto |
@@ -238,7 +259,8 @@ edges
| lib.js:91:20:91:28 | obj[path] | lib.js:91:7:91:28 | maybeProto |
| lib.js:91:24:91:27 | path | lib.js:91:20:91:28 | obj[path] |
| lib.js:104:7:104:24 | one | lib.js:108:7:108:9 | one |
| lib.js:104:13:104:24 | arguments[1] | lib.js:104:7:104:24 | one |
| lib.js:104:13:104:21 | arguments | lib.js:104:13:104:24 | arguments[1] |
| lib.js:104:13:104:21 | arguments | lib.js:104:13:104:24 | arguments[1] |
| lib.js:104:13:104:24 | arguments[1] | lib.js:104:7:104:24 | one |
| lib.js:108:7:108:9 | one | lib.js:108:3:108:10 | obj[one] |
| lib.js:108:7:108:9 | one | lib.js:108:3:108:10 | obj[one] |
@@ -299,13 +321,13 @@ edges
#select
| lib.js:6:7:6:9 | obj | lib.js:1:43:1:46 | path | lib.js:6:7:6:9 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:1:43:1:46 | path | library input |
| lib.js:15:3:15:14 | obj[path[0]] | lib.js:14:38:14:41 | path | lib.js:15:3:15:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:14:38:14:41 | path | library input |
| lib.js:22:3:22:14 | obj[path[0]] | lib.js:20:14:20:25 | arguments[1] | lib.js:22:3:22:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:20:14:20:25 | arguments[1] | library input |
| lib.js:22:3:22:14 | obj[path[0]] | lib.js:20:14:20:22 | arguments | lib.js:22:3:22:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:20:14:20:22 | arguments | library input |
| lib.js:26:10:26:21 | obj[path[0]] | lib.js:25:44:25:47 | path | lib.js:26:10:26:21 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:25:44:25:47 | path | library input |
| lib.js:34:3:34:14 | obj[path[0]] | lib.js:32:14:32:20 | args[1] | lib.js:34:3:34:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:32:14:32:20 | args[1] | library input |
| lib.js:42:3:42:14 | obj[path[0]] | lib.js:40:14:40:20 | args[1] | lib.js:42:3:42:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:40:14:40:20 | args[1] | library input |
| lib.js:34:3:34:14 | obj[path[0]] | lib.js:30:43:30:51 | arguments | lib.js:34:3:34:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:30:43:30:51 | arguments | library input |
| lib.js:42:3:42:14 | obj[path[0]] | lib.js:38:27:38:35 | arguments | lib.js:42:3:42:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:38:27:38:35 | arguments | library input |
| lib.js:70:13:70:24 | obj[path[0]] | lib.js:59:18:59:18 | s | lib.js:70:13:70:24 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:59:18:59:18 | s | library input |
| lib.js:87:10:87:14 | proto | lib.js:83:14:83:25 | arguments[1] | lib.js:87:10:87:14 | proto | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:83:14:83:25 | arguments[1] | library input |
| lib.js:108:3:108:10 | obj[one] | lib.js:104:13:104:24 | arguments[1] | lib.js:108:3:108:10 | obj[one] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:104:13:104:24 | arguments[1] | library input |
| lib.js:87:10:87:14 | proto | lib.js:83:14:83:22 | arguments | lib.js:87:10:87:14 | proto | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:83:14:83:22 | arguments | library input |
| lib.js:108:3:108:10 | obj[one] | lib.js:104:13:104:21 | arguments | lib.js:108:3:108:10 | obj[one] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:104:13:104:21 | arguments | library input |
| lib.js:119:13:119:24 | obj[path[0]] | lib.js:118:29:118:32 | path | lib.js:119:13:119:24 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:118:29:118:32 | path | library input |
| sublib/sub.js:2:3:2:14 | obj[path[0]] | sublib/sub.js:1:37:1:40 | path | sublib/sub.js:2:3:2:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | sublib/sub.js:1:37:1:40 | path | library input |
| tst.js:8:5:8:17 | object[taint] | tst.js:5:24:5:37 | req.query.data | tst.js:8:5:8:17 | object[taint] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:5:24:5:37 | req.query.data | user controlled input |