@@ -241,6 +241,23 @@ module Angular2 {
241241 }
242242 }
243243
244+ /**
245+ * A call derived from a pipe expression.
246+ *
247+ * For example, the expression `x | f: y` is desugared to `f(x, y)` where
248+ * `f` is a `PipeRefExpr` and the call itself is a `PipeCallExpr`.
249+ */
250+ class PipeCallExpr extends CallExpr {
251+ PipeCallExpr ( ) {
252+ getCallee ( ) instanceof PipeRefExpr
253+ }
254+
255+ /** Gets the name of the pipe being invoked, such as `f` in `x | f`. */
256+ string getPipeName ( ) {
257+ result = getCallee ( ) .( PipeRefExpr ) .getName ( )
258+ }
259+ }
260+
244261 /**
245262 * A reference to a variable in a template expression, corresponding
246263 * to a property on the component class.
@@ -263,6 +280,7 @@ module Angular2 {
263280 result = DataFlow:: ssaDefinitionNode ( SSA:: implicitInit ( getScope ( ) .getVariable ( name ) ) )
264281 }
265282
283+ /** Gets a data flow node corresponding to a use of the given template variable within this top-level. */
266284 DataFlow:: SourceNode getAVariableUse ( string name ) {
267285 result = getScope ( ) .getVariable ( name ) .getAnAccess ( ) .flow ( )
268286 }
@@ -375,9 +393,9 @@ module Angular2 {
375393 }
376394
377395 /**
378- * Gets an access to the variable `name` in the template body.
396+ * Gets an access to the given template variable within the template body of this component .
379397 */
380- DataFlow:: Node getATemplateVarAccess ( string name ) {
398+ DataFlow:: SourceNode getATemplateVarAccess ( string name ) {
381399 result = getATemplateElement ( ) .getAnAttribute ( ) .getCodeInAttribute ( ) .( TemplateTopLevel ) .getAVariableUse ( name )
382400 }
383401 }
@@ -453,7 +471,7 @@ module Angular2 {
453471
454472 /** Gets the name of the variable holding the element of the current iteration. */
455473 string getIteratorName ( ) {
456- result = getValue ( ) .regexpCapture ( "^ *let (\\w+) .*" , 1 )
474+ result = getValue ( ) .regexpCapture ( " *let + (\\w+).*" , 1 )
457475 }
458476
459477 /** Gets an HTML element in which the iterator variable is in scope. */
@@ -484,11 +502,119 @@ module Angular2 {
484502 }
485503 }
486504
487- private class AnyCastStep extends TaintTracking:: AdditionalTaintStep , DataFlow:: CallNode {
488- AnyCastStep ( ) { this = any ( TemplateTopLevel tl ) .getAVariableUse ( "$any" ) .getACall ( ) }
505+ private class AnyCastStep extends PreCallGraphStep {
506+ override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) {
507+ exists ( DataFlow:: CallNode call |
508+ call = any ( TemplateTopLevel tl ) .getAVariableUse ( "$any" ) .getACall ( ) and
509+ pred = call .getArgument ( 0 ) and
510+ succ = call
511+ )
512+ }
513+ }
514+
515+ /**
516+ * Gets an invocation of the pipe of the given name.
517+ *
518+ * For example, the call generated from `items | async` would be found by `getAPipeCall("async")`.
519+ */
520+ DataFlow:: CallNode getAPipeCall ( string name ) {
521+ result .getCalleeNode ( ) .asExpr ( ) .( PipeRefExpr ) .getName ( ) = name
522+ }
523+
524+ private class BuiltinPipeStep extends TaintTracking:: AdditionalTaintStep , DataFlow:: CallNode {
525+ string name ;
526+
527+ BuiltinPipeStep ( ) {
528+ this = getAPipeCall ( name )
529+ }
530+
531+ override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) {
532+ succ = this and
533+ exists ( int i | pred = getArgument ( i ) |
534+ i = 0 and name = [ "async" , "i18nPlural" , "json" , "keyvalue" , "lowercase" , "uppercase" , "titlecase" , "slice" ]
535+ or
536+ i = 1 and name = "date" // date format string
537+ )
538+ or
539+ // Arguments to translate are assumed to be included in the result somewhere
540+ name = "translate" and
541+ succ = this and
542+ pred = [ getArgument ( 1 ) , getOptionArgument ( 1 , _) ]
543+ }
544+ }
545+
546+ /**
547+ * A `<mat-table>` element.
548+ */
549+ class MatTableElement extends HTML:: Element {
550+ MatTableElement ( ) {
551+ getName ( ) = "mat-table"
552+ }
553+
554+ /** Gets the data flow node corresponding to the `[dataSource]` attribute. */
555+ DataFlow:: Node getDataSourceNode ( ) {
556+ result = getAttributeValueAsNode ( getAttributeByName ( "[dataSource]" ) )
557+ }
558+
559+ /**
560+ * Gets an element of form `<mat-cell *matCellDef="let rowBinding">` in this table.
561+ */
562+ HTML:: Element getATableCell ( string rowBinding ) {
563+ result .getName ( ) = "mat-cell" and
564+ result .getParent + ( ) = this and
565+ rowBinding = result .getAttributeByName ( "*matCellDef" ) .getValue ( ) .regexpCapture ( " *let +(\\w+).*" , 1 )
566+ }
567+
568+ /** Gets a data flow node that refers to one of the rows from the data source. */
569+ DataFlow:: Node getARowRef ( ) {
570+ exists ( string rowBinding |
571+ result = getATableCell ( rowBinding ) .getChild * ( ) .getAnAttribute ( ) .getCodeInAttribute ( ) .( TemplateTopLevel ) .getAVariableUse ( rowBinding )
572+ )
573+ }
574+ }
575+
576+ /**
577+ * A taint step from `x -> y` in code of form:
578+ * ```
579+ * <mat-table [dataSource]="x">
580+ * <mat-cell *matCellDef="let y">
581+ * <foo [prop]="y"/>
582+ * </mat-cell>
583+ * </mat-table>
584+ * ```
585+ */
586+ private class MatTableTaintStep extends TaintTracking:: AdditionalTaintStep {
587+ MatTableElement table ;
588+
589+ MatTableTaintStep ( ) {
590+ this = table .getDataSourceNode ( )
591+ }
592+
593+ override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) {
594+ pred = this and
595+ succ = table .getARowRef ( )
596+ }
597+ }
598+
599+ /** Like `MatTableTaintStep` but as a value-preserving load step. */
600+ private class MatTableLoadStep extends PreCallGraphStep {
601+ override predicate loadStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
602+ exists ( MatTableElement table |
603+ pred = table .getDataSourceNode ( ) and
604+ succ = table .getARowRef ( ) and
605+ prop = DataFlow:: PseudoProperties:: arrayElement ( )
606+ )
607+ }
608+ }
609+
610+ /** A taint step into the data array of a `MatTableDataSource` instance. */
611+ private class MatTableDataSourceStep extends TaintTracking:: AdditionalTaintStep , DataFlow:: NewNode {
612+ MatTableDataSourceStep ( ) {
613+ this = DataFlow:: moduleMember ( "@angular/material/table" , "MatTableDataSource" ) .getAnInstantiation ( )
614+ }
489615
490616 override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) {
491- pred = getArgument ( 0 ) and
617+ pred = [ getArgument ( 0 ) , getAPropertyWrite ( "data" ) . getRhs ( ) ] and
492618 succ = this
493619 }
494620 }
0 commit comments