Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e319159

Browse files
authored
Merge pull request #316 from xiemaisi/js/odasa-7355-workaround
Approved by esben-semmle
2 parents 1e76966 + df5a865 commit e319159

9 files changed

Lines changed: 58 additions & 14 deletions

File tree

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ class AbstractProtoProperty extends AbstractProperty {
9696
* which in turn introduces a materialization.
9797
*/
9898
private AbstractValue getAnAssignedValue(AbstractValue b, string p) {
99-
exists (AnalyzedPropertyWrite apw, DataFlow::AnalyzedNode afn |
100-
apw.writes(b, p, afn) and
101-
result = afn.getALocalValue()
99+
exists (AnalyzedPropertyWrite apw |
100+
apw.writesValue(b, p, result)
102101
)
103102
}

javascript/ql/src/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,12 @@ private class AnalyzedVariableExport extends AnalyzedPropertyWrite, DataFlow::Va
268268
propName = name and
269269
source = varDef.getSource().analyze()
270270
}
271+
272+
override predicate writesValue(AbstractValue baseVal, string propName, AbstractValue val) {
273+
baseVal = TAbstractExportsObject(export.getEnclosingModule()) and
274+
propName = name and
275+
val = varDef.getAnAssignedValue()
276+
}
271277
}
272278

273279
/**

javascript/ql/src/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,18 +160,26 @@ private class IIFEWithAnalyzedReturnFlow extends CallWithAnalyzedReturnFlow {
160160

161161
}
162162

163+
/**
164+
* Gets the only access to `v`, which is the variable declared by `fn`.
165+
*
166+
* This predicate is not defined for global functions `fn`, or for
167+
* local variables `v` that do not have exactly one access.
168+
*/
169+
private VarAccess getOnlyAccess(FunctionDeclStmt fn, LocalVariable v) {
170+
v = fn.getVariable() and
171+
result = v.getAnAccess() and
172+
strictcount(v.getAnAccess()) = 1
173+
}
174+
163175
/** A function that only is used locally, making it amenable to type inference. */
164176
class LocalFunction extends Function {
165177

166178
DataFlow::Impl::ExplicitInvokeNode invk;
167179

168180
LocalFunction() {
169-
this instanceof FunctionDeclStmt and
170-
exists (LocalVariable v, Expr callee |
171-
callee = invk.getCalleeNode().asExpr() and
172-
v = getVariable() and
173-
v.getAnAccess() = callee and
174-
forall(VarAccess o | o = v.getAnAccess() | o = callee) and
181+
exists (LocalVariable v |
182+
getOnlyAccess(this, v) = invk.getCalleeNode().asExpr() and
175183
not exists(v.getAnAssignedExpr()) and
176184
not exists(ExportDeclaration export | export.exportsAs(v, _))
177185
) and

javascript/ql/src/semmle/javascript/dataflow/internal/PropertyTypeInference.qll

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,24 @@ abstract class AnalyzedPropertyWrite extends DataFlow::Node {
9696
/**
9797
* Holds if this property write assigns `source` to property `propName` of one of the
9898
* concrete objects represented by `baseVal`.
99+
*
100+
* Note that not all property writes have an explicit `source` node; use predicate
101+
* `writesValue` below to cover these cases.
99102
*/
100-
abstract predicate writes(AbstractValue baseVal, string propName, DataFlow::AnalyzedNode source);
103+
predicate writes(AbstractValue baseVal, string propName, DataFlow::AnalyzedNode source) {
104+
none()
105+
}
106+
107+
/**
108+
* Holds if this property write assigns `val` to property `propName` of one of the
109+
* concrete objects represented by `baseVal`.
110+
*/
111+
predicate writesValue(AbstractValue baseVal, string propName, AbstractValue val) {
112+
exists (AnalyzedNode source |
113+
writes(baseVal, propName, source) and
114+
val = source.getALocalValue()
115+
)
116+
}
101117

102118
/**
103119
* Holds if the flow information for the base node of this property write is incomplete

javascript/ql/test/library-tests/Flow/AbstractValues.expected

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
| ChatListScreen.js:3:1:5:1 | instance of function foo |
55
| a2.js:1:1:2:0 | exports object of module a2 |
66
| a2.js:1:1:2:0 | module object of module a2 |
7-
| a.js:1:1:13:0 | exports object of module a |
8-
| a.js:1:1:13:0 | module object of module a |
7+
| a.js:1:1:18:0 | exports object of module a |
8+
| a.js:1:1:18:0 | module object of module a |
99
| a.js:3:8:5:1 | function setX |
1010
| a.js:3:8:5:1 | instance of function setX |
11+
| a.js:15:1:17:1 | function bump |
12+
| a.js:15:1:17:1 | instance of function bump |
1113
| amd2.js:1:1:4:0 | exports object of module amd2 |
1214
| amd2.js:1:1:4:0 | module object of module amd2 |
1315
| amd2.js:1:8:3:1 | anonymous function |
@@ -36,8 +38,8 @@
3638
| arguments.js:30:2:33:1 | anonymous function |
3739
| arguments.js:30:2:33:1 | arguments object of anonymous function |
3840
| arguments.js:30:2:33:1 | instance of anonymous function |
39-
| b.js:1:1:55:0 | exports object of module b |
40-
| b.js:1:1:55:0 | module object of module b |
41+
| b.js:1:1:58:0 | exports object of module b |
42+
| b.js:1:1:58:0 | module object of module b |
4143
| backend.js:1:1:3:0 | exports object of module backend |
4244
| backend.js:1:1:3:0 | module object of module backend |
4345
| backend.js:1:17:1:18 | object literal |

javascript/ql/test/library-tests/Flow/a.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,8 @@ let z = someGlobal;
1010

1111
export let w;
1212
w = "w";
13+
14+
export let notAlwaysZero = 0;
15+
function bump() {
16+
++notAlwaysZero;
17+
}

javascript/ql/test/library-tests/Flow/abseval.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
| a.js:9:5:9:5 | z | a.js:9:9:9:18 | someGlobal | file://:0:0:0:0 | indefinite value (global) |
77
| a.js:9:5:9:5 | z | a.js:9:9:9:18 | someGlobal | file://:0:0:0:0 | non-zero value |
88
| a.js:9:5:9:5 | z | a.js:9:9:9:18 | someGlobal | file://:0:0:0:0 | true |
9+
| a.js:14:12:14:24 | notAlwaysZero | a.js:14:28:14:28 | 0 | file://:0:0:0:0 | 0 |
910
| amd.js:2:7:2:7 | m | amd.js:2:11:2:13 | mod | amd.js:1:1:7:0 | module object of module amd |
1011
| amd.js:2:7:2:7 | m | amd.js:2:11:2:13 | mod | file://:0:0:0:0 | indefinite value (call) |
1112
| amd.js:3:7:3:7 | e | amd.js:3:11:3:13 | exp | amd.js:1:1:7:0 | exports object of module amd |
@@ -58,6 +59,8 @@
5859
| b.js:48:5:48:7 | z13 | b.js:48:11:48:11 | w | file://:0:0:0:0 | non-empty, non-numeric string |
5960
| b.js:51:5:51:7 | z14 | b.js:51:11:51:24 | foo_reexported | file://:0:0:0:0 | indefinite value (import) |
6061
| b.js:54:5:54:7 | z15 | b.js:54:11:54:19 | something | file://:0:0:0:0 | indefinite value (import) |
62+
| b.js:57:5:57:7 | z16 | b.js:57:11:57:23 | notAlwaysZero | file://:0:0:0:0 | 0 |
63+
| b.js:57:5:57:7 | z16 | b.js:57:11:57:23 | notAlwaysZero | file://:0:0:0:0 | non-zero value |
6164
| backend.js:1:7:1:13 | Backend | backend.js:1:17:1:18 | {} | backend.js:1:17:1:18 | object literal |
6265
| classAccessors.js:10:9:10:11 | myX | classAccessors.js:10:15:10:20 | this.x | file://:0:0:0:0 | indefinite value (call) |
6366
| classAccessors.js:10:9:10:11 | myX | classAccessors.js:10:15:10:20 | this.x | file://:0:0:0:0 | indefinite value (heap) |

javascript/ql/test/library-tests/Flow/b.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,6 @@ let z14 = foo_reexported;
5252

5353
import { something } from './reexport-unknown';
5454
let z15 = something;
55+
56+
import { notAlwaysZero } from './a';
57+
let z16 = notAlwaysZero;

javascript/ql/test/library-tests/Flow/types.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
| a.js:1:12:1:12 | x | a.js:1:16:1:16 | 0 | number |
33
| a.js:1:19:1:19 | y | a.js:1:23:1:23 | 0 | number |
44
| a.js:9:5:9:5 | z | a.js:9:9:9:18 | someGlobal | boolean, class, date, function, null, number, object, regular expression,string or undefined |
5+
| a.js:14:12:14:24 | notAlwaysZero | a.js:14:28:14:28 | 0 | number |
56
| amd.js:2:7:2:7 | m | amd.js:2:11:2:13 | mod | boolean, class, date, function, null, number, object, regular expression,string or undefined |
67
| amd.js:3:7:3:7 | e | amd.js:3:11:3:13 | exp | boolean, class, date, function, null, number, object, regular expression,string or undefined |
78
| arguments.js:2:7:2:7 | y | arguments.js:2:11:2:11 | x | number |
@@ -32,6 +33,7 @@
3233
| b.js:48:5:48:7 | z13 | b.js:48:11:48:11 | w | string |
3334
| b.js:51:5:51:7 | z14 | b.js:51:11:51:24 | foo_reexported | boolean, class, date, function, null, number, object, regular expression,string or undefined |
3435
| b.js:54:5:54:7 | z15 | b.js:54:11:54:19 | something | boolean, class, date, function, null, number, object, regular expression,string or undefined |
36+
| b.js:57:5:57:7 | z16 | b.js:57:11:57:23 | notAlwaysZero | number |
3537
| backend.js:1:7:1:13 | Backend | backend.js:1:17:1:18 | {} | object |
3638
| classAccessors.js:10:9:10:11 | myX | classAccessors.js:10:15:10:20 | this.x | boolean, class, date, function, null, number, object, regular expression,string or undefined |
3739
| classAccessors.js:11:9:11:11 | myY | classAccessors.js:11:15:11:20 | this.y | boolean, class, date, function, null, number, object, regular expression,string or undefined |

0 commit comments

Comments
 (0)