8
8
import javascript
9
9
private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
10
10
private import semmle.javascript.dataflow.internal.PreCallGraphStep
11
+ private import semmle.javascript.dataflow.internal.StepSummary
12
+ private import semmle.javascript.dataflow.internal.sharedlib.SummaryTypeTracker as SummaryTypeTracker
11
13
private import internal.CachedStages
12
14
13
15
/**
@@ -229,6 +231,40 @@ module API {
229
231
result = this .getASuccessor ( Label:: unknownMember ( ) )
230
232
}
231
233
234
+ cached
235
+ private Node getContentRaw ( DataFlow:: Content content ) {
236
+ Stages:: ApiStage:: ref ( ) and
237
+ result = this .getASuccessor ( Label:: content ( content ) )
238
+ }
239
+
240
+ /**
241
+ * Gets a representative for the `content` of this value.
242
+ *
243
+ * When possible, it is preferrable to use one of the specialized variants of this predicate, such as `getMember`.
244
+ */
245
+ pragma [ inline]
246
+ Node getContent ( DataFlow:: Content content ) {
247
+ result = this .getContentRaw ( content )
248
+ or
249
+ result = this .getMember ( content .asPropertyName ( ) )
250
+ }
251
+
252
+ /**
253
+ * Gets a representative for the `contents` of this value.
254
+ */
255
+ bindingset [ this , contents]
256
+ pragma [ inline_late]
257
+ Node getContents ( DataFlow:: ContentSet contents ) {
258
+ // We always use getAStoreContent when generating content edges, and we always use getAReadContent when querying the graph.
259
+ result = this .getContent ( contents .getAReadContent ( ) )
260
+ }
261
+
262
+ /**
263
+ * Gets a node representing an arbitrary array element in the array represented by this node.
264
+ */
265
+ cached
266
+ Node getArrayElement ( ) { result = this .getContents ( DataFlow:: ContentSet:: arrayElement ( ) ) }
267
+
232
268
/**
233
269
* Gets a node representing a member of this API component where the name of the member may
234
270
* or may not be known statically.
@@ -790,6 +826,11 @@ module API {
790
826
not DataFlow:: PseudoProperties:: isPseudoProperty ( prop )
791
827
)
792
828
or
829
+ exists ( DataFlow:: ContentSet contents |
830
+ SummaryTypeTracker:: basicStoreStep ( rhs , pred .getALocalUse ( ) , contents ) and
831
+ lbl = Label:: content ( contents .getAStoreContent ( ) )
832
+ )
833
+ or
793
834
exists ( DataFlow:: FunctionNode fn |
794
835
fn = pred and
795
836
lbl = Label:: return ( )
@@ -982,6 +1023,11 @@ module API {
982
1023
// avoid generating member edges like "$arrayElement$"
983
1024
not DataFlow:: PseudoProperties:: isPseudoProperty ( prop )
984
1025
)
1026
+ or
1027
+ exists ( DataFlow:: ContentSet contents |
1028
+ SummaryTypeTracker:: basicLoadStep ( pred .getALocalUse ( ) , ref , contents ) and
1029
+ lbl = Label:: content ( contents .getAStoreContent ( ) )
1030
+ )
985
1031
)
986
1032
or
987
1033
exists ( DataFlow:: Node def , DataFlow:: FunctionNode fn |
@@ -1199,8 +1245,6 @@ module API {
1199
1245
t = useStep ( nd , promisified , boundArgs , prop , result )
1200
1246
}
1201
1247
1202
- private import semmle.javascript.dataflow.internal.StepSummary
1203
-
1204
1248
/**
1205
1249
* Holds if `nd`, which is a use of an API-graph node, flows in zero or more potentially
1206
1250
* inter-procedural steps to some intermediate node, and then from that intermediate node to
@@ -1458,8 +1502,11 @@ module API {
1458
1502
bindingset [ result ]
1459
1503
LabelMember member ( string m ) { result .getProperty ( ) = m }
1460
1504
1505
+ /** Gets the `content` edge label for content `c`. */
1506
+ LabelContent content ( ContentPrivate:: Content c ) { result .getContent ( ) = c }
1507
+
1461
1508
/** Gets the `member` edge label for the unknown member. */
1462
- LabelUnknownMember unknownMember ( ) { any ( ) }
1509
+ LabelContent unknownMember ( ) { result . getContent ( ) . isUnknownArrayElement ( ) }
1463
1510
1464
1511
/**
1465
1512
* Gets a property name referred to by the given dynamic property access,
@@ -1516,10 +1563,10 @@ module API {
1516
1563
LabelForwardingFunction forwardingFunction ( ) { any ( ) }
1517
1564
1518
1565
/** Gets the `promised` edge label connecting a promise to its contained value. */
1519
- LabelPromised promised ( ) { any ( ) }
1566
+ LabelContent promised ( ) { result . getContent ( ) = ContentPrivate :: MkPromiseValue ( ) }
1520
1567
1521
1568
/** Gets the `promisedError` edge label connecting a promise to its rejected value. */
1522
- LabelPromisedError promisedError ( ) { any ( ) }
1569
+ LabelContent promisedError ( ) { result . getContent ( ) = ContentPrivate :: MkPromiseError ( ) }
1523
1570
1524
1571
/** Gets the label for an edge leading from a value `D` to any class that has `D` as a decorator. */
1525
1572
LabelDecoratedClass decoratedClass ( ) { any ( ) }
@@ -1533,6 +1580,7 @@ module API {
1533
1580
/** Gets an entry-point label for the entry-point `e`. */
1534
1581
LabelEntryPoint entryPoint ( API:: EntryPoint e ) { result .getEntryPoint ( ) = e }
1535
1582
1583
+ private import semmle.javascript.dataflow.internal.Contents:: Private as ContentPrivate
1536
1584
private import LabelImpl
1537
1585
1538
1586
private module LabelImpl {
@@ -1542,18 +1590,12 @@ module API {
1542
1590
exists ( Impl:: MkModuleImport ( mod ) )
1543
1591
} or
1544
1592
MkLabelInstance ( ) or
1545
- MkLabelMember ( string prop ) {
1546
- exports ( _, prop , _) or
1547
- exists ( any ( DataFlow:: ClassNode c ) .getInstanceMethod ( prop ) ) or
1548
- prop = "exports" or
1549
- prop = any ( CanonicalName c ) .getName ( ) or
1550
- prop = any ( DataFlow:: PropRef p ) .getPropertyName ( ) or
1551
- exists ( Impl:: MkTypeUse ( _, prop ) ) or
1552
- exists ( any ( Module m ) .getAnExportedValue ( prop ) ) or
1553
- PreCallGraphStep:: loadStep ( _, _, prop ) or
1554
- PreCallGraphStep:: storeStep ( _, _, prop )
1593
+ MkLabelContent ( DataFlow:: Content content ) or
1594
+ MkLabelMember ( string name ) {
1595
+ name instanceof PropertyName
1596
+ or
1597
+ exists ( Impl:: MkTypeUse ( _, name ) )
1555
1598
} or
1556
- MkLabelUnknownMember ( ) or
1557
1599
MkLabelParameter ( int i ) {
1558
1600
i =
1559
1601
[ 0 .. max ( int args |
@@ -1564,8 +1606,6 @@ module API {
1564
1606
} or
1565
1607
MkLabelReceiver ( ) or
1566
1608
MkLabelReturn ( ) or
1567
- MkLabelPromised ( ) or
1568
- MkLabelPromisedError ( ) or
1569
1609
MkLabelDecoratedClass ( ) or
1570
1610
MkLabelDecoratedMember ( ) or
1571
1611
MkLabelDecoratedParameter ( ) or
@@ -1585,13 +1625,13 @@ module API {
1585
1625
}
1586
1626
1587
1627
/** A label that gets a promised value. */
1588
- class LabelPromised extends ApiLabel , MkLabelPromised {
1589
- override string toString ( ) { result = "getPromised()" }
1628
+ deprecated class LabelPromised extends ApiLabel {
1629
+ LabelPromised ( ) { this = MkLabelContent ( ContentPrivate :: MkPromiseValue ( ) ) }
1590
1630
}
1591
1631
1592
1632
/** A label that gets a rejected promise. */
1593
- class LabelPromisedError extends ApiLabel , MkLabelPromisedError {
1594
- override string toString ( ) { result = "getPromisedError()" }
1633
+ deprecated class LabelPromisedError extends ApiLabel {
1634
+ LabelPromisedError ( ) { this = MkLabelContent ( ContentPrivate :: MkPromiseError ( ) ) }
1595
1635
}
1596
1636
1597
1637
/** A label that gets the return value of a function. */
@@ -1617,9 +1657,39 @@ module API {
1617
1657
override string toString ( ) { result = "getInstance()" }
1618
1658
}
1619
1659
1660
+ /** A label for a content. */
1661
+ class LabelContent extends ApiLabel , MkLabelContent {
1662
+ private DataFlow:: Content content ;
1663
+
1664
+ LabelContent ( ) {
1665
+ this = MkLabelContent ( content ) and
1666
+ // Property names are represented by LabelMember to ensure additional property
1667
+ // names from PreCallGraph step are included, as well as those from MkTypeUse.
1668
+ not content instanceof ContentPrivate:: MkPropertyContent
1669
+ }
1670
+
1671
+ /** Gets the content associated with this label. */
1672
+ DataFlow:: Content getContent ( ) { result = content }
1673
+
1674
+ private string specialisedToString ( ) {
1675
+ content instanceof ContentPrivate:: MkPromiseValue and result = "getPromised()"
1676
+ or
1677
+ content instanceof ContentPrivate:: MkPromiseError and result = "getPromisedError()"
1678
+ or
1679
+ content instanceof ContentPrivate:: MkArrayElementUnknown and result = "getUnknownMember()"
1680
+ }
1681
+
1682
+ override string toString ( ) {
1683
+ result = this .specialisedToString ( )
1684
+ or
1685
+ not exists ( this .specialisedToString ( ) ) and
1686
+ result = "getContent(" + content + ")"
1687
+ }
1688
+ }
1689
+
1620
1690
/** A label for the member named `prop`. */
1621
1691
class LabelMember extends ApiLabel , MkLabelMember {
1622
- string prop ;
1692
+ private string prop ;
1623
1693
1624
1694
LabelMember ( ) { this = MkLabelMember ( prop ) }
1625
1695
@@ -1630,10 +1700,8 @@ module API {
1630
1700
}
1631
1701
1632
1702
/** A label for a member with an unknown name. */
1633
- class LabelUnknownMember extends ApiLabel , MkLabelUnknownMember {
1634
- LabelUnknownMember ( ) { this = MkLabelUnknownMember ( ) }
1635
-
1636
- override string toString ( ) { result = "getUnknownMember()" }
1703
+ deprecated class LabelUnknownMember extends LabelContent {
1704
+ LabelUnknownMember ( ) { this .getContent ( ) .isUnknownArrayElement ( ) }
1637
1705
}
1638
1706
1639
1707
/** A label for parameter `i`. */
0 commit comments