Skip to content

Commit 6c20d52

Browse files
committed
JS: Apply forceLocal overlay trick to API graphs
1 parent 8fcaa72 commit 6c20d52

File tree

1 file changed

+101
-5
lines changed

1 file changed

+101
-5
lines changed

javascript/ql/lib/semmle/javascript/ApiGraphs.qll

Lines changed: 101 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,13 @@ module API {
13501350
result = trackUseNode(nd, false, 0, "")
13511351
}
13521352

1353+
/**
1354+
* Gets a node whose forward tracking reaches `nd` in some state (e.g. possibly inside a content at this point).
1355+
*/
1356+
DataFlow::SourceNode trackUseNodeAnyState(DataFlow::SourceNode nd) {
1357+
result = trackUseNode(nd, _, _, _, _)
1358+
}
1359+
13531360
private DataFlow::SourceNode trackDefNode(DataFlow::Node nd, DataFlow::TypeBackTracker t) {
13541361
t.start() and
13551362
rhs(_, nd) and
@@ -1400,6 +1407,11 @@ module API {
14001407
result = trackDefNode(nd, DataFlow::TypeBackTracker::end())
14011408
}
14021409

1410+
/**
1411+
* Gets a node reached by the backwards tracking of `nd` in some state (e.g. possibly inside a content at this point).
1412+
*/
1413+
DataFlow::SourceNode trackDefNodeAnyState(DataFlow::Node nd) { result = trackDefNode(nd, _) }
1414+
14031415
private DataFlow::SourceNode awaited(DataFlow::InvokeNode call, DataFlow::TypeTracker t) {
14041416
t.startInPromise() and
14051417
trackUseNode(_, true, _, "").flowsTo(call.getCalleeNode()) and
@@ -1505,25 +1517,109 @@ module API {
15051517

15061518
private module Stage1 = Stage<Stage1Input>;
15071519

1520+
overlay[local]
1521+
private module Stage1Local {
1522+
predicate use(TApiNode node, DataFlow::Node ref) = forceLocal(Stage1::use/2)(node, ref)
1523+
1524+
predicate rhs(TApiNode node, DataFlow::Node def) = forceLocal(Stage1::rhs/2)(node, def)
1525+
1526+
DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) =
1527+
forceLocal(Stage1::trackUseNode/1)(nd, result)
1528+
1529+
DataFlow::SourceNode trackUseNodeAnyState(DataFlow::SourceNode nd) =
1530+
forceLocal(Stage1::trackUseNodeAnyState/1)(nd, result)
1531+
1532+
DataFlow::SourceNode trackDefNode(DataFlow::SourceNode nd) =
1533+
forceLocal(Stage1::trackDefNode/1)(nd, result)
1534+
1535+
DataFlow::SourceNode trackDefNodeAnyState(DataFlow::Node nd) =
1536+
forceLocal(Stage1::trackDefNodeAnyState/1)(nd, result)
1537+
1538+
predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) =
1539+
forceLocal(Stage1::edge/3)(pred, lbl, succ)
1540+
}
1541+
1542+
private module Stage2Input implements StageInputSig {
1543+
bindingset[node]
1544+
overlay[global]
1545+
pragma[inline_late]
1546+
private predicate isInOverlayChangedFile(DataFlow::Node node) {
1547+
overlayChangedFiles(node.getFile().getAbsolutePath())
1548+
}
1549+
1550+
pragma[nomagic]
1551+
private predicate shouldTrackIntoOverlay(DataFlow::SourceNode nd) {
1552+
exists(DataFlow::Node overlayNode |
1553+
StepSummary::step(Stage1Local::trackUseNodeAnyState(nd), overlayNode, _) and
1554+
isInOverlayChangedFile(overlayNode)
1555+
)
1556+
}
1557+
1558+
pragma[nomagic]
1559+
predicate isAdditionalUseRoot(Node node) {
1560+
exists(DataFlow::Node ref |
1561+
shouldTrackIntoOverlay(ref) and
1562+
Stage1Local::use(node, ref)
1563+
)
1564+
}
1565+
1566+
pragma[nomagic]
1567+
private predicate shouldBacktrackIntoOverlay(DataFlow::SourceNode nd) {
1568+
exists(DataFlow::Node overlayNode |
1569+
StepSummary::step(overlayNode, Stage1Local::trackDefNodeAnyState(nd), _) and
1570+
isInOverlayChangedFile(overlayNode)
1571+
)
1572+
}
1573+
1574+
pragma[nomagic]
1575+
predicate isAdditionalDefRoot(Node node) {
1576+
exists(DataFlow::Node def |
1577+
shouldBacktrackIntoOverlay(def) and
1578+
Stage1Local::rhs(node, def)
1579+
)
1580+
}
1581+
1582+
bindingset[node]
1583+
predicate inScope(DataFlow::Node node) { isInOverlayChangedFile(node) }
1584+
}
1585+
1586+
private module Stage2 = Stage<Stage2Input>;
1587+
15081588
cached
15091589
private module Cached {
15101590
cached
1511-
predicate rhs(TApiNode nd, DataFlow::Node rhs) { Stage1::rhs(nd, rhs) }
1591+
predicate rhs(TApiNode nd, DataFlow::Node rhs) {
1592+
Stage1Local::rhs(nd, rhs)
1593+
or
1594+
Stage2::rhs(nd, rhs)
1595+
}
15121596

15131597
cached
1514-
predicate use(TApiNode nd, DataFlow::Node ref) { Stage1::use(nd, ref) }
1598+
predicate use(TApiNode nd, DataFlow::Node ref) {
1599+
Stage1Local::use(nd, ref)
1600+
or
1601+
Stage2::use(nd, ref)
1602+
}
15151603

15161604
cached
15171605
DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) {
1518-
result = Stage1::trackUseNode(nd)
1606+
result = Stage1Local::trackUseNode(nd)
1607+
or
1608+
result = Stage2::trackUseNode(nd)
15191609
}
15201610

15211611
cached
1522-
DataFlow::SourceNode trackDefNode(DataFlow::Node nd) { result = Stage1::trackDefNode(nd) }
1612+
DataFlow::SourceNode trackDefNode(DataFlow::Node nd) {
1613+
result = Stage1Local::trackDefNode(nd)
1614+
or
1615+
result = Stage2::trackDefNode(nd)
1616+
}
15231617

15241618
cached
15251619
predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) {
1526-
Stage1::edge(pred, lbl, succ)
1620+
Stage1Local::edge(pred, lbl, succ)
1621+
or
1622+
Stage2::edge(pred, lbl, succ)
15271623
}
15281624

15291625
cached

0 commit comments

Comments
 (0)