88import javascript
99private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
1010private 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
1113private import internal.CachedStages
1214
1315/**
@@ -229,6 +231,40 @@ module API {
229231 result = this .getASuccessor ( Label:: unknownMember ( ) )
230232 }
231233
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+
232268 /**
233269 * Gets a node representing a member of this API component where the name of the member may
234270 * or may not be known statically.
@@ -790,6 +826,11 @@ module API {
790826 not DataFlow:: PseudoProperties:: isPseudoProperty ( prop )
791827 )
792828 or
829+ exists ( DataFlow:: ContentSet contents |
830+ SummaryTypeTracker:: basicStoreStep ( rhs , pred .getALocalUse ( ) , contents ) and
831+ lbl = Label:: content ( contents .getAStoreContent ( ) )
832+ )
833+ or
793834 exists ( DataFlow:: FunctionNode fn |
794835 fn = pred and
795836 lbl = Label:: return ( )
@@ -982,6 +1023,11 @@ module API {
9821023 // avoid generating member edges like "$arrayElement$"
9831024 not DataFlow:: PseudoProperties:: isPseudoProperty ( prop )
9841025 )
1026+ or
1027+ exists ( DataFlow:: ContentSet contents |
1028+ SummaryTypeTracker:: basicLoadStep ( pred .getALocalUse ( ) , ref , contents ) and
1029+ lbl = Label:: content ( contents .getAStoreContent ( ) )
1030+ )
9851031 )
9861032 or
9871033 exists ( DataFlow:: Node def , DataFlow:: FunctionNode fn |
@@ -1199,8 +1245,6 @@ module API {
11991245 t = useStep ( nd , promisified , boundArgs , prop , result )
12001246 }
12011247
1202- private import semmle.javascript.dataflow.internal.StepSummary
1203-
12041248 /**
12051249 * Holds if `nd`, which is a use of an API-graph node, flows in zero or more potentially
12061250 * inter-procedural steps to some intermediate node, and then from that intermediate node to
@@ -1458,8 +1502,11 @@ module API {
14581502 bindingset [ result ]
14591503 LabelMember member ( string m ) { result .getProperty ( ) = m }
14601504
1505+ /** Gets the `content` edge label for content `c`. */
1506+ LabelContent content ( ContentPrivate:: Content c ) { result .getContent ( ) = c }
1507+
14611508 /** Gets the `member` edge label for the unknown member. */
1462- LabelUnknownMember unknownMember ( ) { any ( ) }
1509+ LabelContent unknownMember ( ) { result . getContent ( ) . isUnknownArrayElement ( ) }
14631510
14641511 /**
14651512 * Gets a property name referred to by the given dynamic property access,
@@ -1516,10 +1563,10 @@ module API {
15161563 LabelForwardingFunction forwardingFunction ( ) { any ( ) }
15171564
15181565 /** Gets the `promised` edge label connecting a promise to its contained value. */
1519- LabelPromised promised ( ) { any ( ) }
1566+ LabelContent promised ( ) { result . getContent ( ) = ContentPrivate :: MkPromiseValue ( ) }
15201567
15211568 /** Gets the `promisedError` edge label connecting a promise to its rejected value. */
1522- LabelPromisedError promisedError ( ) { any ( ) }
1569+ LabelContent promisedError ( ) { result . getContent ( ) = ContentPrivate :: MkPromiseError ( ) }
15231570
15241571 /** Gets the label for an edge leading from a value `D` to any class that has `D` as a decorator. */
15251572 LabelDecoratedClass decoratedClass ( ) { any ( ) }
@@ -1533,6 +1580,7 @@ module API {
15331580 /** Gets an entry-point label for the entry-point `e`. */
15341581 LabelEntryPoint entryPoint ( API:: EntryPoint e ) { result .getEntryPoint ( ) = e }
15351582
1583+ private import semmle.javascript.dataflow.internal.Contents:: Private as ContentPrivate
15361584 private import LabelImpl
15371585
15381586 private module LabelImpl {
@@ -1542,18 +1590,12 @@ module API {
15421590 exists ( Impl:: MkModuleImport ( mod ) )
15431591 } or
15441592 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 ) )
15551598 } or
1556- MkLabelUnknownMember ( ) or
15571599 MkLabelParameter ( int i ) {
15581600 i =
15591601 [ 0 .. max ( int args |
@@ -1564,8 +1606,6 @@ module API {
15641606 } or
15651607 MkLabelReceiver ( ) or
15661608 MkLabelReturn ( ) or
1567- MkLabelPromised ( ) or
1568- MkLabelPromisedError ( ) or
15691609 MkLabelDecoratedClass ( ) or
15701610 MkLabelDecoratedMember ( ) or
15711611 MkLabelDecoratedParameter ( ) or
@@ -1585,13 +1625,13 @@ module API {
15851625 }
15861626
15871627 /** 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 ( ) ) }
15901630 }
15911631
15921632 /** 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 ( ) ) }
15951635 }
15961636
15971637 /** A label that gets the return value of a function. */
@@ -1617,9 +1657,39 @@ module API {
16171657 override string toString ( ) { result = "getInstance()" }
16181658 }
16191659
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+
16201690 /** A label for the member named `prop`. */
16211691 class LabelMember extends ApiLabel , MkLabelMember {
1622- string prop ;
1692+ private string prop ;
16231693
16241694 LabelMember ( ) { this = MkLabelMember ( prop ) }
16251695
@@ -1630,10 +1700,8 @@ module API {
16301700 }
16311701
16321702 /** 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 ( ) }
16371705 }
16381706
16391707 /** A label for parameter `i`. */
0 commit comments