11import javascript
22import DataFlow
33import advanced_security.javascript.frameworks.ui5.JsonParser
4+ import advanced_security.javascript.frameworks.ui5.dataflow.TypeTrackers
45import semmle.javascript.security.dataflow.DomBasedXssCustomizations
56import advanced_security.javascript.frameworks.ui5.UI5View
67import advanced_security.javascript.frameworks.ui5.UI5HTML
@@ -138,6 +139,15 @@ class WebApp extends HTML::HtmlFile {
138139 * by a call to `sap.ui.getCore()`.
139140 */
140141class SapUiCore extends MethodCallNode {
142+ /*
143+ * NOTE: Ideally, we'd like to use `ModelOutput::getATypeNode("SapUICore").asSource()` to
144+ * take advantage of the inter-procedural flexibility of MaD, but doing so causes
145+ * non-monotomic recursion.
146+ *
147+ * So, we opt to use `SourceNode.getAPropertyRead/1` and `SourceNode.getAMethodCall/1`
148+ * instead and get away with local flow tracking they provide.
149+ */
150+
141151 SapUiCore ( ) { this = globalVarRef ( "sap" ) .getAPropertyRead ( "ui" ) .getAMethodCall ( "getCore" ) }
142152}
143153
@@ -247,9 +257,8 @@ class Renderer extends SapExtendCall {
247257
248258class CustomControl extends SapExtendCall {
249259 CustomControl ( ) {
250- this =
251- TypeTrackers:: hasDependency ( [ "sap/ui/core/Control" , "sap.ui.core.Control" ] )
252- .getAMemberCall ( "extend" ) or
260+ this = ModelOutput:: getATypeNode ( "CustomControl" ) .getACall ( )
261+ or
253262 exists ( SapDefineModule sapModule | this .getDefine ( ) = sapModule .getExtendingModule ( ) )
254263 }
255264
@@ -449,17 +458,18 @@ class ControllerReference extends Reference {
449458}
450459
451460class CustomController extends SapExtendCall {
461+ API:: Node customController ;
452462 string name ;
453463
454464 CustomController ( ) {
455- this =
456- TypeTrackers:: hasDependency ( [ "sap/ui/core/mvc/Controller" , "sap.ui.core.mvc.Controller" ] )
457- .getAMemberCall ( "extend" ) and
458- name = this .getFile ( ) .getBaseName ( ) .regexpCapture ( "([a-zA-Z0-9]+).[cC]ontroller.js" , 1 )
465+ customController = ModelOutput:: getATypeNode ( "CustomController" ) and
466+ this = customController .getACall ( ) and
467+ name = this .getFile ( ) .getBaseName ( ) .regexpCapture ( "(.+).[cC]ontroller.js" , 1 )
459468 }
460469
461470 Component getOwnerComponent ( ) {
462- exists ( ManifestJson manifestJson , JsonObject rootObj | manifestJson = result .getManifestJson ( ) |
471+ exists ( ManifestJson manifestJson , JsonObject rootObj |
472+ manifestJson = result .getManifestJson ( ) and
463473 rootObj
464474 .getPropValue ( "targets" )
465475 .( JsonObject )
@@ -474,7 +484,12 @@ class CustomController extends SapExtendCall {
474484 }
475485
476486 MethodCallNode getOwnerComponentRef ( ) {
477- result = this .getAThisNode ( ) .getAMemberCall ( "getOwnerComponent" )
487+ exists ( API:: Node getOwnerComponent |
488+ getOwnerComponent = ModelOutput:: getATypeNode ( "CustomControllerGetOwnerComponent" )
489+ |
490+ customController .getASuccessor + ( ) = getOwnerComponent and
491+ result = getOwnerComponent .asSource ( )
492+ )
478493 }
479494
480495 /**
@@ -757,14 +772,10 @@ class Component extends SapExtendCall {
757772 * It is the value flowing to a `setModel` call in a handler of a `CustomController` (which is represented by `ControllerHandler`), since it is the closest we can get to the actual model itself.
758773 */
759774
760- this =
761- TypeTrackers:: hasDependency ( [
762- "sap/ui/core/mvc/Component" , "sap.ui.core.mvc.Component" , "sap/ui/core/UIComponent" ,
763- "sap.ui.core.UIComponent"
764- ] ) .getAMemberCall ( "extend" )
775+ this = ModelOutput:: getATypeNode ( "CustomComponent" ) .getACall ( )
765776 }
766777
767- string getId ( ) { result = this .getName ( ) .regexpCapture ( "([a-zA-Z0-9.] +).Component" , 1 ) }
778+ string getId ( ) { result = this .getName ( ) .regexpCapture ( "(. +).Component" , 1 ) }
768779
769780 ManifestJson getManifestJson ( ) {
770781 this .getMetadata ( ) .getAPropertySource ( "manifest" ) .asExpr ( ) .( StringLiteral ) .getValue ( ) = "json" and
@@ -1428,18 +1439,162 @@ class PropertyMetadata extends ObjectLiteralNode {
14281439 }
14291440}
14301441
1431- module TypeTrackers {
1432- private SourceNode hasDependency ( TypeTracker t , string dependencyPath ) {
1433- t .start ( ) and
1434- exists ( UserModule d |
1435- d .getADependency ( ) = dependencyPath and
1436- result = d .getRequiredObject ( dependencyPath ) .asSourceNode ( )
1437- )
1438- or
1439- exists ( TypeTracker t2 | result = hasDependency ( t2 , dependencyPath ) .track ( t2 , t ) )
1442+ module EventBus {
1443+ abstract class EventBusPublishCall extends CallNode {
1444+ abstract EventBusSubscribeCall getAMatchingSubscribeCall ( ) ;
1445+
1446+ abstract DataFlow:: Node getPublishedData ( ) ;
1447+
1448+ string getChannelName ( ) { result = this .getArgument ( 0 ) .getALocalSource ( ) .getStringValue ( ) }
1449+
1450+ string getMessageType ( ) { result = this .getArgument ( 1 ) .getALocalSource ( ) .getStringValue ( ) }
1451+ }
1452+
1453+ abstract class EventBusSubscribeCall extends CallNode {
1454+ abstract EventBusPublishCall getMatchingPublishCall ( ) ;
1455+
1456+ abstract DataFlow:: Node getSubscriptionData ( ) ;
1457+
1458+ string getChannelName ( ) { result = this .getArgument ( 0 ) .getALocalSource ( ) .getStringValue ( ) }
1459+
1460+ string getMessageType ( ) { result = this .getArgument ( 1 ) .getALocalSource ( ) .getStringValue ( ) }
1461+ }
1462+
1463+ class GlobalEventBusPublishCall extends EventBusPublishCall {
1464+ API:: Node publishMethod ;
1465+
1466+ GlobalEventBusPublishCall ( ) {
1467+ publishMethod = ModelOutput:: getATypeNode ( "UI5EventBusPublish" ) and
1468+ this = publishMethod .getACall ( )
1469+ }
1470+
1471+ override GlobalEventBusSubscribeCall getAMatchingSubscribeCall ( ) {
1472+ result .getChannelName ( ) = this .getChannelName ( ) and
1473+ result .getMessageType ( ) = this .getMessageType ( )
1474+ }
1475+
1476+ override DataFlow:: Node getPublishedData ( ) {
1477+ exists ( API:: Node publishedData |
1478+ publishedData = ModelOutput:: getATypeNode ( "UI5EventBusPublishedEventData" )
1479+ |
1480+ publishMethod .getASuccessor * ( ) = publishedData and
1481+ result = publishedData .getInducingNode ( )
1482+ )
1483+ }
1484+ }
1485+
1486+ class SapUICoreEventBusPublishCall extends EventBusPublishCall {
1487+ API:: Node publishMethod ;
1488+
1489+ SapUICoreEventBusPublishCall ( ) {
1490+ publishMethod = ModelOutput:: getATypeNode ( "SapUICoreEventBusPublish" ) and
1491+ this = publishMethod .getACall ( )
1492+ }
1493+
1494+ override SapUICoreEventBusSubscribeCall getAMatchingSubscribeCall ( ) {
1495+ result .getChannelName ( ) = this .getChannelName ( ) and
1496+ result .getMessageType ( ) = this .getMessageType ( )
1497+ }
1498+
1499+ override DataFlow:: Node getPublishedData ( ) {
1500+ exists ( API:: Node publishedData |
1501+ publishedData = ModelOutput:: getATypeNode ( "SapUICoreEventBusPublishedEventData" )
1502+ |
1503+ publishMethod .getASuccessor * ( ) = publishedData and
1504+ result = publishedData .getInducingNode ( )
1505+ )
1506+ }
1507+ }
1508+
1509+ class ComponentEventBusPublishCall extends EventBusPublishCall {
1510+ API:: Node customController ;
1511+
1512+ ComponentEventBusPublishCall ( ) {
1513+ exists ( API:: Node customControllerGetOwnerComponentEventBusPublish |
1514+ customControllerGetOwnerComponentEventBusPublish =
1515+ ModelOutput:: getATypeNode ( "CustomControllerGetOwnerComponentEventBusPublish" )
1516+ |
1517+ customController = ModelOutput:: getATypeNode ( "CustomController" ) and
1518+ customControllerGetOwnerComponentEventBusPublish = customController .getASuccessor + ( ) and
1519+ this = customControllerGetOwnerComponentEventBusPublish .getACall ( )
1520+ )
1521+ }
1522+
1523+ override ComponentEventBusSubscribeCall getAMatchingSubscribeCall ( ) {
1524+ result .getChannelName ( ) = this .getChannelName ( ) and
1525+ result .getMessageType ( ) = this .getMessageType ( )
1526+ }
1527+
1528+ override DataFlow:: Node getPublishedData ( ) { result = this .getArgument ( 2 ) }
14401529 }
14411530
1442- SourceNode hasDependency ( string dependencyPath ) {
1443- result = hasDependency ( TypeTracker:: end ( ) , dependencyPath )
1531+ class GlobalEventBusSubscribeCall extends EventBusSubscribeCall {
1532+ API:: Node subscribeMethod ;
1533+
1534+ GlobalEventBusSubscribeCall ( ) {
1535+ subscribeMethod = ModelOutput:: getATypeNode ( "UI5EventBusSubscribe" ) and
1536+ this = subscribeMethod .getACall ( )
1537+ }
1538+
1539+ override GlobalEventBusPublishCall getMatchingPublishCall ( ) {
1540+ result .getChannelName ( ) = this .getChannelName ( ) and
1541+ result .getMessageType ( ) = this .getMessageType ( )
1542+ }
1543+
1544+ override DataFlow:: Node getSubscriptionData ( ) {
1545+ exists ( API:: Node subscribeMethodCallbackDataParameter |
1546+ subscribeMethodCallbackDataParameter =
1547+ ModelOutput:: getATypeNode ( "UI5EventSubscriptionHandlerDataParameter" )
1548+ |
1549+ subscribeMethod .getASuccessor * ( ) = subscribeMethodCallbackDataParameter and
1550+ result = subscribeMethodCallbackDataParameter .getInducingNode ( )
1551+ )
1552+ }
1553+ }
1554+
1555+ class SapUICoreEventBusSubscribeCall extends EventBusSubscribeCall {
1556+ API:: Node subscribeMethod ;
1557+
1558+ SapUICoreEventBusSubscribeCall ( ) {
1559+ subscribeMethod = ModelOutput:: getATypeNode ( "SapUICoreEventBusSubscribe" ) and
1560+ this = subscribeMethod .getACall ( )
1561+ }
1562+
1563+ override SapUICoreEventBusPublishCall getMatchingPublishCall ( ) {
1564+ result .getChannelName ( ) = this .getChannelName ( ) and
1565+ result .getMessageType ( ) = this .getMessageType ( )
1566+ }
1567+
1568+ override DataFlow:: Node getSubscriptionData ( ) {
1569+ exists ( API:: Node subscribeMethodCallbackDataParameter |
1570+ subscribeMethodCallbackDataParameter =
1571+ ModelOutput:: getATypeNode ( "SapUICoreEventSubscriptionHandlerDataParameter" )
1572+ |
1573+ subscribeMethod .getASuccessor + ( ) = subscribeMethodCallbackDataParameter and
1574+ result = subscribeMethodCallbackDataParameter .getInducingNode ( )
1575+ )
1576+ }
1577+ }
1578+
1579+ class ComponentEventBusSubscribeCall extends EventBusSubscribeCall {
1580+ API:: Node customController ;
1581+
1582+ ComponentEventBusSubscribeCall ( ) {
1583+ exists ( API:: Node customControllerGetOwnerComponentEventBusSubscribe |
1584+ customControllerGetOwnerComponentEventBusSubscribe =
1585+ ModelOutput:: getATypeNode ( "CustomControllerGetOwnerComponentEventBusSubscribe" )
1586+ |
1587+ customController = ModelOutput:: getATypeNode ( "CustomController" ) and
1588+ customControllerGetOwnerComponentEventBusSubscribe = customController .getASuccessor + ( ) and
1589+ this = customControllerGetOwnerComponentEventBusSubscribe .getACall ( )
1590+ )
1591+ }
1592+
1593+ override ComponentEventBusPublishCall getMatchingPublishCall ( ) {
1594+ result .getChannelName ( ) = this .getChannelName ( ) and
1595+ result .getMessageType ( ) = this .getMessageType ( )
1596+ }
1597+
1598+ override DataFlow:: Node getSubscriptionData ( ) { result = this .getABoundCallbackParameter ( 2 , 2 ) }
14441599 }
14451600}
0 commit comments