Skip to content

Commit 2006826

Browse files
committed
JS: Avoid breaking local object analysis
1 parent 9f2f10f commit 2006826

File tree

2 files changed

+29
-22
lines changed

2 files changed

+29
-22
lines changed

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

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,45 +31,49 @@ private class AnalyzedCapturedVariable extends @variable {
3131
}
3232

3333
/**
34-
* Flow analysis for accesses to SSA variables.
34+
* Flow analysis for SSA nodes.
3535
*/
3636
private class AnalyzedSsaDefinitionNode extends AnalyzedNode, DataFlow::SsaDefinitionNode {
3737
override AbstractValue getALocalValue() { result = ssa.(AnalyzedSsaDefinition).getAnRhsValue() }
3838
}
3939

4040
/**
41-
* Flow analysis for accesses to SSA variables.
42-
*
43-
* Unlike `AnalyzedSsaDefinitionNode`, this only contributes to `getAValue()`, not `getALocalValue()`.
41+
* An SSA definition whose right-hand side is a call with non-local data flow.
4442
*/
45-
private class AnalyzedSsaDefinitionNodeWithNonLocalAnalysis extends AnalyzedSsaDefinitionNode {
46-
DataFlow::AnalyzedValueNode src;
43+
private class SsaDefinitionWithNonLocalFlow extends SsaExplicitDefinition {
44+
CallWithNonLocalAnalyzedReturnFlow source;
4745

48-
AnalyzedSsaDefinitionNodeWithNonLocalAnalysis() {
49-
exists(VarDef varDef |
50-
varDef = ssa.(SsaExplicitDefinition).getDef() and
51-
varDef.getSource().flow() = src and
52-
src instanceof CallWithNonLocalAnalyzedReturnFlow
53-
)
46+
SsaDefinitionWithNonLocalFlow() {
47+
source = getDef().getSource().flow()
5448
}
5549

56-
override AbstractValue getAValue() { result = src.getAValue() }
50+
CallWithNonLocalAnalyzedReturnFlow getSource() { result = source }
5751
}
5852

5953
/**
60-
* Flow analysis for SSA variable uses.
61-
*
62-
* Ensures that `getAValue` propagates from the SSA definition to its use.
54+
* Flow analysis for SSA nodes corresponding to `SsaDefinitionWithNonLocalFlow`.
55+
*/
56+
private class AnalyzedSsaDefinitionNodeWithNonLocalAnalysis extends AnalyzedSsaDefinitionNode {
57+
override SsaDefinitionWithNonLocalFlow ssa;
58+
59+
override AbstractValue getAValue() {
60+
result = ssa.getSource().getAValue()
61+
}
62+
}
63+
64+
/**
65+
* Flow analysis for uses of an SSA variable corresponding to `SsaDefinitionWithNonLocalFlow`.
6366
*/
64-
private class AnalyzedSsaVariableUse extends AnalyzedValueNode {
65-
AnalyzedSsaVariableUse() {
66-
this = DataFlow::valueNode(any(SsaVariable v).getAUse())
67+
private class AnalyzedSsaVariableUseWithNonLocalFlow extends AnalyzedValueNode {
68+
SsaDefinitionWithNonLocalFlow ssaDef;
69+
70+
AnalyzedSsaVariableUseWithNonLocalFlow() {
71+
this = DataFlow::valueNode(ssaDef.getVariable().getAUse())
6772
}
6873

6974
override AbstractValue getAValue() {
70-
result = AnalyzedValueNode.super.getAValue()
71-
or
72-
result = localFlowPred().getAValue()
75+
// Block indefinite values coming from getALocalValue()
76+
result = ssaDef.getSource().getAValue()
7377
}
7478
}
7579

javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,11 @@ test_isUncertain
3636
| tst.js:69:1:69:10 | globalfn() |
3737
test_getAFunctionValue
3838
| a.js:1:8:1:10 | foo | b.js:1:16:1:27 | function(){} |
39+
| a.js:1:8:1:10 | foo | b.js:1:16:1:27 | function(){} |
40+
| a.js:1:15:1:17 | bar | b.js:2:8:2:24 | function bar() {} |
3941
| a.js:1:15:1:17 | bar | b.js:2:8:2:24 | function bar() {} |
4042
| a.js:1:20:1:22 | qux | c.js:2:8:2:24 | function bar() {} |
43+
| a.js:1:20:1:22 | qux | c.js:2:8:2:24 | function bar() {} |
4144
| a.js:2:1:2:3 | foo | b.js:1:16:1:27 | function(){} |
4245
| a.js:3:1:3:3 | bar | b.js:2:8:2:24 | function bar() {} |
4346
| a.js:4:1:4:3 | qux | c.js:2:8:2:24 | function bar() {} |

0 commit comments

Comments
 (0)