JS: teach the dataflow library identity functions Object.freeze/seal

This commit is contained in:
Esben Sparre Andreasen
2020-06-25 15:06:58 +02:00
parent 33c52761d4
commit 75451e349a
5 changed files with 26 additions and 1 deletions

View File

@@ -4,6 +4,7 @@
import javascript
private import semmle.javascript.dataflow.InferredTypes
private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
deprecated module GlobalAccessPath {
/**
@@ -58,7 +59,8 @@ module AccessPath {
not this instanceof DataFlow::PropRead and
not this instanceof PropertyProjection and
not this instanceof Closure::ClosureNamespaceAccess and
not this = DataFlow::parameterNode(any(ImmediatelyInvokedFunctionExpr iife).getAParameter())
not this = DataFlow::parameterNode(any(ImmediatelyInvokedFunctionExpr iife).getAParameter()) and
not this = FlowSteps::IdentityCalls::syntactic(_)
}
/** Holds if this represents the root of the global access path. */

View File

@@ -198,6 +198,8 @@ module DataFlow {
result = unique(Expr ret | ret = fun.getAReturnedExpr()).flow() and
not fun.getExit().isJoin() // can only reach exit by the return statement
)
or
this = FlowSteps::IdentityCalls::syntactic(result)
}
/**

View File

@@ -529,3 +529,19 @@ module PathSummary {
*/
PathSummary return() { exists(FlowLabel lbl | result = MkPathSummary(true, false, lbl, lbl)) }
}
/**
* Provides predicates for reasoning about calls to identity functions.
*/
module IdentityCalls {
/**
* Gets an identity call for `input` that can be recognized syntactically.
*/
DataFlow::CallNode syntactic(DataFlow::Node input) {
exists(DataFlow::GlobalVarRefNode global |
global.getName() = "Object" and
result.(DataFlow::MethodCallNode).calls(global, ["freeze", "seal"]) and
input = result.getArgument(0)
)
}
}

View File

@@ -151,3 +151,4 @@
| tst.js:111:7:111:9 | v2a | tst.js:111:6:111:38 | v2a |
| tst.js:111:36:111:38 | o2d | tst.js:111:6:111:32 | [v2a, v ... = o2c] |
| tst.js:115:1:115:12 | reflective call | tst.js:115:1:115:12 | Array.call() |
| tst.js:117:22:117:23 | x1 | tst.js:117:10:117:24 | Object.seal(x1) |

View File

@@ -67,10 +67,14 @@ test_getAReferenceTo
| test.js:56:7:56:12 | random | random |
| test.js:67:11:67:16 | Object | Object |
| test.js:67:11:67:23 | Object.freeze | Object.freeze |
| test.js:67:11:67:32 | Object. ... oo.bar) | foo.bar |
| test.js:67:11:67:36 | Object. ... ar).baz | foo.bar.baz |
| test.js:67:25:67:27 | foo | foo |
| test.js:67:25:67:31 | foo.bar | foo.bar |
| test.js:68:11:68:16 | Object | Object |
| test.js:68:11:68:21 | Object.seal | Object.seal |
| test.js:68:11:68:30 | Object.seal(foo.bar) | foo.bar |
| test.js:68:11:68:34 | Object. ... ar).baz | foo.bar.baz |
| test.js:68:23:68:25 | foo | foo |
| test.js:68:23:68:29 | foo.bar | foo.bar |
| test.js:69:6:69:15 | O | Object |