Skip to content

Commit 78ec643

Browse files
committed
Replace all E.getReceiver().getALocalSource() with .getAMemberCall()
The latter is a bad idea as it misses some local data flow steps.
1 parent b84195a commit 78ec643

File tree

1 file changed

+81
-87
lines changed
  • javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5

1 file changed

+81
-87
lines changed

javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/UI5.qll

Lines changed: 81 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,13 @@ class JQuerySap extends DataFlow::SourceNode {
214214
* A user-defined module through `jQuery.sap.declare`.
215215
*/
216216
class JQueryDefineModule extends UserModule, MethodCallExpr {
217-
JQueryDefineModule() { exists(JQuerySap jquerySap | jquerySap.asExpr() = this.getReceiver()) }
217+
JQueryDefineModule() {
218+
exists(JQuerySap jQuerySap | this = jQuerySap.getAMemberCall(["declare", "define"]).asExpr())
219+
}
218220

219-
override string getADependency() { result = this.getArgument(0).getStringValue() }
221+
override string getADependency() {
222+
result = this.getArgument(0).getALocalSource().getStringValue()
223+
}
220224

221225
override string getModuleFileRelativePath() { result = this.getFile().getRelativePath() }
222226

@@ -229,8 +233,9 @@ class JQueryDefineModule extends UserModule, MethodCallExpr {
229233

230234
class Renderer extends SapExtendCall {
231235
Renderer() {
232-
this.getReceiver().getALocalSource() =
236+
this =
233237
TypeTrackers::hasDependency(["sap/ui/core/Renderer", "sap.ui.core.Renderer"])
238+
.getAMemberCall("extend")
234239
}
235240

236241
FunctionNode getRenderer() {
@@ -244,8 +249,9 @@ class Renderer extends SapExtendCall {
244249

245250
class CustomControl extends SapExtendCall {
246251
CustomControl() {
247-
this.getReceiver().getALocalSource() =
248-
TypeTrackers::hasDependency(["sap/ui/core/Control", "sap.ui.core.Control"]) or
252+
this =
253+
TypeTrackers::hasDependency(["sap/ui/core/Control", "sap.ui.core.Control"])
254+
.getAMemberCall("extend") or
249255
exists(SapDefineModule sapModule | this.getDefine() = sapModule.getExtendingModule())
250256
}
251257

@@ -293,28 +299,43 @@ class CustomControl extends SapExtendCall {
293299
result = renderer.getRenderer()
294300
)
295301
}
302+
}
296303

297-
ValueNode getAThisNode() {
298-
exists(ThisNode thisNode | thisNode.getBinder() = this.getAMethod() |
299-
result.getALocalSource() = thisNode
304+
class ControlPlaceAtCall extends MethodCallNode {
305+
ControlPlaceAtCall() {
306+
exists(SapElement ui5Control |
307+
// /* 1. `this.placeAt(...)` in a custom control definition */
308+
// this = ui5Control.asDefinition().getAThisNode()
309+
// or
310+
// /*
311+
// * 2. `new SomeControl(...).placeAt(...)` where `SomeControl`
312+
// * may be UI5 library control or a custom control
313+
// */
314+
// ui5Control.asInstantiation().
315+
// or
316+
// /* 3. `.byId(...).placeAt(...)` */
317+
// ui5Control.asReference().
318+
none() // TODO
300319
)
301320
}
302321
}
303322

304323
abstract class Reference extends MethodCallNode { }
305324

325+
private predicate byId(MethodCallNode byId) { byId.getMethodName() = "byId" }
326+
306327
/**
307328
* A JS reference to a `UI5Control`, commonly obtained via its ID.
308329
*/
309330
class ControlReference extends Reference {
310331
string controlId;
311332

312333
ControlReference() {
313-
this.getArgument(0).getStringValue() = controlId and
334+
this.getArgument(0).getALocalSource().getStringValue() = controlId and
314335
(
315336
exists(CustomController controller |
316337
this = controller.getAViewReference().getAMemberCall("byId") or
317-
this.getReceiver() = controller.getAThisNode()
338+
this = controller.getAThisNode().getAMemberCall("byId")
318339
)
319340
or
320341
exists(SapUiCore sapUiCore | this = sapUiCore.getAMemberCall("byId"))
@@ -398,17 +419,11 @@ class ControlReference extends Reference {
398419
class ViewReference extends Reference {
399420
CustomController controller;
400421

401-
ViewReference() {
402-
this.getMethodName() = "getView" and
403-
controller.getAThisNode() = this.getReceiver()
404-
}
422+
ViewReference() { this = controller.getAThisNode().getAMemberCall("getView") }
405423

406424
UI5View getDefinition() { result = controller.getView() }
407425

408-
MethodCallNode getABindElementCall() {
409-
result.getMethodName() = "bindElement" and
410-
this.flowsTo(result.getReceiver())
411-
}
426+
MethodCallNode getABindElementCall() { result = this.getAMemberCall("bindElement") }
412427
}
413428

414429
/**
@@ -417,7 +432,7 @@ class ViewReference extends Reference {
417432
class ControllerReference extends Reference {
418433
ViewReference viewReference;
419434

420-
ControllerReference() { viewReference.flowsTo(this.getReceiver()) }
435+
ControllerReference() { this = viewReference.getAMemberCall("getController") }
421436

422437
CustomController getDefinition() { result = viewReference.getDefinition().getController() }
423438
}
@@ -426,8 +441,9 @@ class CustomController extends SapExtendCall {
426441
string name;
427442

428443
CustomController() {
429-
this.getReceiver().getALocalSource() =
430-
TypeTrackers::hasDependency(["sap/ui/core/mvc/Controller", "sap.ui.core.mvc.Controller"]) and
444+
this =
445+
TypeTrackers::hasDependency(["sap/ui/core/mvc/Controller", "sap.ui.core.mvc.Controller"])
446+
.getAMemberCall("extend") and
431447
name = this.getFile().getBaseName().regexpCapture("([a-zA-Z0-9]+).[cC]ontroller.js", 1)
432448
}
433449

@@ -447,39 +463,33 @@ class CustomController extends SapExtendCall {
447463
}
448464

449465
MethodCallNode getOwnerComponentRef() {
450-
this.getAThisNode() = result.getReceiver() and
451-
result.getMethodName() = "getOwnerComponent"
466+
result = this.getAThisNode().getAMemberCall("getOwnerComponent")
452467
}
453468

454469
/**
455470
* Gets a reference to a view object that can be accessed from one of the methods of this controller.
456471
*/
457-
ViewReference getAViewReference() {
458-
result.getMethodName() = "getView" and
459-
result.(MethodCallNode).getReceiver() = this.getAThisNode()
460-
}
472+
ViewReference getAViewReference() { result = this.getAThisNode().getAMemberCall("getView") }
461473

462474
UI5View getView() { this = result.getController() }
463475

464476
ControlReference getAControlReference() {
465477
result = this.getAViewReference().getAMemberCall("byId")
466478
}
467479

468-
ValueNode getAThisNode() {
469-
exists(ThisNode thisNode | thisNode.getBinder() = this.getAMethod() |
470-
/* ========== 1. `this` referring to the binder ========== */
471-
thisNode.flowsTo(result)
472-
or
473-
/* 2. ========== `this` bound to an outside `this` ========== */
474-
/*
475-
* 2-1. The DisplayEventHandler's `this` bound to an outside `this` via
476-
* `.attachDisplay` or `.detachDisplay`
477-
*/
480+
override ThisNode getAThisNode() {
481+
/* 1. `this` referring to the binder */
482+
result = super.getAThisNode()
483+
or
484+
/* 2. `this` bound to a callback's `this` */
485+
/*
486+
* 2-1. The this node of `.attachDisplay` or `.detachDisplay` also represents this
487+
* controller.
488+
*/
478489

479-
exists(DisplayEventHandler handler, ThisNode handlerThis | handlerThis.getBinder() = handler |
480-
thisNode.flowsTo(handler.getAssociatedContextObject()) and
481-
handlerThis.flowsTo(result)
482-
)
490+
exists(DisplayEventHandler handler |
491+
handler.getAssociatedContextObject().getALocalSource() = this.getAThisNode() and
492+
result.getBinder() = handler
483493
)
484494
}
485495

@@ -516,7 +526,7 @@ class RouteReference extends MethodCallNode {
516526
RouteReference() {
517527
exists(RouterReference routerReference |
518528
this = routerReference.getAMemberCall("getRoute") and
519-
this.getArgument(0).getStringValue() = name
529+
this.getArgument(0).getALocalSource().getStringValue() = name
520530
)
521531
}
522532

@@ -545,10 +555,9 @@ class ControllerHandler extends EventHandler {
545555

546556
class RouterReference extends MethodCallNode {
547557
RouterReference() {
548-
this.getMethodName() = "getRouter" and
549558
exists(CustomController controller |
550-
controller.getAThisNode() = this.getReceiver() or
551-
controller.getOwnerComponentRef().flowsTo(this.getReceiver())
559+
this = controller.getAThisNode().getAMemberCall("getRouter") or
560+
this = controller.getOwnerComponentRef().getAMemberCall("getRouter")
552561
)
553562
}
554563

@@ -565,9 +574,8 @@ class RoutingTarget extends MethodCallNode {
565574
RouterReference routerReference;
566575

567576
RoutingTarget() {
568-
this.getArgument(0).getALocalSource().asExpr().(StringLiteral).getValue() = name and
569-
routerReference = this.getReceiver().getALocalSource() and
570-
this.getMethodName() = "getTarget"
577+
this.getArgument(0).getALocalSource().getStringValue() = name and
578+
this = routerReference.getAMemberCall("getTarget")
571579
}
572580

573581
RouterReference getRouterReference() { result = routerReference }
@@ -615,27 +623,22 @@ class DisplayEventHandler extends EventHandler {
615623
*/
616624
class ModelReference extends MethodCallNode {
617625
ModelReference() {
618-
this.getMethodName() = "getModel" and
619-
(
620-
exists(ViewReference view | view.flowsTo(this.getReceiver()))
621-
or
622-
exists(CustomController controller |
623-
controller.getAViewReference().flowsTo(this.getReceiver()) or
624-
controller.getOwnerComponentRef().flowsTo(this.getReceiver())
625-
)
626-
or
627-
exists(Component component | component.getAThisNode().flowsTo(this.getReceiver()))
626+
exists(ViewReference view | this = view.getAMemberCall("getModel"))
627+
or
628+
exists(CustomController controller |
629+
this = controller.getAViewReference().getAMemberCall("getModel") or
630+
this = controller.getOwnerComponentRef().getAMemberCall("getModel")
628631
)
632+
or
633+
exists(Component component | this = component.getAThisNode().getAMemberCall("getModel"))
629634
}
630635

631636
predicate isDefaultModelReference() { this.getNumArgument() = 0 }
632637

633638
/**
634639
* Gets the models' name being referred to, given that it can be statically determined.
635640
*/
636-
string getModelName() {
637-
result = this.getArgument(0).getALocalSource().asExpr().(StringLiteral).getValue()
638-
}
641+
string getModelName() { result = this.getArgument(0).getALocalSource().getStringValue() }
639642

640643
predicate isLocalModelReference() {
641644
exists(InternalModelManifest internalModelManifest |
@@ -704,10 +707,7 @@ class ModelReference extends MethodCallNode {
704707
/**
705708
* Gets a `getProperty` or `getObject` method call on this `ModelReference`. These methods read from a single property of the model this refers to.
706709
*/
707-
MethodCallNode getARead() {
708-
result.getMethodName() = ["getProperty", "getObject"] and
709-
result.getReceiver().getALocalSource() = this
710-
}
710+
MethodCallNode getARead() { result = this.getAMemberCall(["getProperty", "getObject"]) }
711711

712712
/**
713713
* Gets the resolved model of this `ModelReference` by looking for a matching `setModel` call.
@@ -724,10 +724,7 @@ abstract class UI5Model extends InvokeNode {
724724
/**
725725
* A `getProperty` or `getObject` method call on this `UI5Model`. These methods read from a single property of this model.
726726
*/
727-
MethodCallNode getARead() {
728-
result.getMethodName() = ["getProperty", "getObject"] and
729-
result.getReceiver().getALocalSource() = this
730-
}
727+
MethodCallNode getARead() { result = this.getAMemberCall(["getProperty", "getObject"]) }
731728
}
732729

733730
/**
@@ -748,16 +745,16 @@ import ManifestJson
748745
*/
749746
class Component extends SapExtendCall {
750747
Component() {
751-
this.getReceiver().getALocalSource() =
752-
/*
753-
* Represents models that are loaded from an external source, e.g. OData service.
754-
* 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.
755-
*/
748+
/*
749+
* Represents models that are loaded from an external source, e.g. OData service.
750+
* 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.
751+
*/
756752

753+
this =
757754
TypeTrackers::hasDependency([
758755
"sap/ui/core/mvc/Component", "sap.ui.core.mvc.Component", "sap/ui/core/UIComponent",
759756
"sap.ui.core.UIComponent"
760-
])
757+
]).getAMemberCall("extend")
761758
}
762759

763760
string getId() { result = this.getName().regexpCapture("([a-zA-Z0-9.]+).Component", 1) }
@@ -788,8 +785,6 @@ class Component extends SapExtendCall {
788785
}
789786

790787
ExternalModelManifest getAnExternalModelDef() { result = this.getExternalModelDef(_) }
791-
792-
ThisNode getAThisNode() { result.getBinder() = this.getAMethod() }
793788
}
794789

795790
module ManifestJson {
@@ -1185,20 +1180,17 @@ class ResourceModel extends UI5Model, ModelReference {
11851180
/* A model reference obtained from this.getOwnerComponent().getModel("i18n") */
11861181
exists(CustomController controller, ResourceModelManifest manifest |
11871182
(
1188-
controller.getAThisNode() = this.getReceiver() or
1189-
controller.getOwnerComponentRef().flowsTo(this.(ModelReference).getReceiver())
1183+
this = controller.getAThisNode().getAMemberCall("getModel") or
1184+
this = controller.getOwnerComponentRef().getAMemberCall("getModel")
11901185
) and
11911186
modelName = this.getModelName() and
11921187
manifest.getName() = modelName
11931188
)
11941189
}
11951190

1196-
override MethodCallNode getARead() { result = this.(ModelReference).getARead() }
1191+
override MethodCallNode getARead() { result = ModelReference.super.getARead() }
11971192

1198-
MethodCallNode getResourceBundle() {
1199-
result.getMethodName() = "getResourceBundle" and
1200-
this = result.getReceiver().getALocalSource()
1201-
}
1193+
MethodCallNode getResourceBundle() { result = this.getAMemberCall("getResourceBundle") }
12021194
}
12031195

12041196
class BindingMode extends RequiredObject {
@@ -1250,7 +1242,7 @@ class SapExtendCall extends InvokeNode, MethodCallNode {
12501242

12511243
FunctionNode getAMethod() { result = this.getMethod(_) }
12521244

1253-
string getName() { result = this.getArgument(0).getStringValue() }
1245+
string getName() { result = this.getArgument(0).getALocalSource().getStringValue() }
12541246

12551247
ObjectLiteralNode getContent() { result = this.getArgument(1) }
12561248

@@ -1265,6 +1257,8 @@ class SapExtendCall extends InvokeNode, MethodCallNode {
12651257

12661258
/** Gets the `sap.ui.define` call that wraps this extension. */
12671259
SapDefineModule getDefine() { this.getEnclosingFunction() = result.getArgument(1) }
1260+
1261+
ThisNode getAThisNode() { result.getBinder() = this.getAMethod() }
12681262
}
12691263

12701264
class ElementInstantiation extends NewNode {
@@ -1402,10 +1396,10 @@ class PropertyMetadata extends ObjectLiteralNode {
14021396
*/
14031397
predicate isUnrestrictedStringType() {
14041398
/* text : "string" */
1405-
this.asExpr().(StringLiteral).getValue() = "string"
1399+
this.getStringValue() = "string"
14061400
or
14071401
/* text: { type: "string" } */
1408-
this.getAPropertySource("type").asExpr().(StringLiteral).getValue() = "string"
1402+
this.getAPropertySource("type").getStringValue() = "string"
14091403
or
14101404
/* text: { someOther: "someOtherVal", ... } */
14111405
not exists(this.getAPropertySource("type"))

0 commit comments

Comments
 (0)