Skip to content

Commit dfa8c08

Browse files
committed
Sort out EntityReference
1 parent 440712f commit dfa8c08

File tree

2 files changed

+70
-62
lines changed
  • javascript/frameworks/cap/lib/advanced_security/javascript/frameworks/cap

2 files changed

+70
-62
lines changed

javascript/frameworks/cap/lib/advanced_security/javascript/frameworks/cap/CDS.qll

Lines changed: 65 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -49,46 +49,6 @@ class CdsDb extends SourceNode {
4949
MethodCallNode getInsertCall() { result = this.getAMemberCall("insert") }
5050
}
5151

52-
/**
53-
* An entity object that belongs to a service.
54-
*
55-
* ```javascript
56-
* // Obtained through `cds.entities`
57-
* const { Service1 } = cds.entities("sample.application.namespace");
58-
* // Obtained through `Service.entities`, in this case the `Service`
59-
* // being a `this` variable of the service.
60-
* const { Service1 } = this.entities;
61-
* ```
62-
*/
63-
abstract class EntityEntry instanceof PropRead {
64-
Location getLocation() { result = PropRead.super.getLocation() }
65-
66-
string toString() { result = PropRead.super.toString() }
67-
68-
/**
69-
* Gets the definition of the service to which this entity belongs to.
70-
*/
71-
abstract UserDefinedApplicationService getServiceDefinition();
72-
}
73-
74-
private class EntityEntryFromCdsEntities extends EntityEntry {
75-
CdsEntitiesCall cdsEntities;
76-
77-
EntityEntryFromCdsEntities() { this = cdsEntities.getAPropertyRead() }
78-
79-
override UserDefinedApplicationService getServiceDefinition() {
80-
result.getServiceName() = cdsEntities.getNamespace()
81-
}
82-
}
83-
84-
private class EntityEntryFromServiceInstance extends EntityEntry {
85-
ServiceInstance srv;
86-
87-
EntityEntryFromServiceInstance() { this = srv.getAPropertyRead("entities").getAPropertyRead() }
88-
89-
override UserDefinedApplicationService getServiceDefinition() { result = srv.getDefinition() }
90-
}
91-
9252
/**
9353
* A call to `serve` on a CDS facade.
9454
*/
@@ -645,38 +605,87 @@ class CdsTransaction extends MethodCallNode {
645605

646606
abstract class CdsReference extends DataFlow::Node { }
647607

608+
/**
609+
* A reference object to an entity that belongs to a service. e.g.
610+
*
611+
* ```javascript
612+
* // 1. Obtained through `cds.entities`
613+
* const { Entity1 } = cds.entities("sample.application.namespace");
614+
* // 2. Obtained through `Service.entities`, in this case the `Service`
615+
* // being a `this` variable of the service.
616+
* const { Entity2 } = this.entities;
617+
* // 3. A direct mention of a name in a literal pass to the fluent API builder.
618+
* SELECT.from`Books`.where(`ID=${id}`)
619+
* ```
620+
*/
648621
abstract class EntityReference extends CdsReference {
649622
abstract CdlEntity getCqlDefinition();
650623
}
651624

625+
/**
626+
* A reference object to an entity that belongs to a service, either
627+
* obtained through a method call to `entities`, or a read from property
628+
* `entities`. e.g.
629+
*
630+
* ```javascript
631+
* // 1. Obtained through `cds.entities`
632+
* const { Entity1 } = cds.entities("sample.application.namespace");
633+
* // 2. Obtained through `Service.entities`, in this case the `Service`
634+
* // being a `this` variable of the service.
635+
* const { Entity2 } = this.entities;
636+
* // 3. A direct mention of a name in a literal pass to the fluent API builder.
637+
* SELECT.from`Books`.where(`ID=${id}`)
638+
* ```
639+
*/
652640
class EntityReferenceFromEntities extends EntityReference instanceof PropRead {
653-
DataFlow::SourceNode entities;
641+
/**
642+
* Property or call to entities
643+
*/
644+
DataFlow::SourceNode entitiesAccess;
645+
/**
646+
* Receiver of the entities call or the base of propread
647+
*/
654648
DataFlow::Node receiver;
649+
/**
650+
* Name of the (unqualified) entity being accessed
651+
*/
655652
string entityName;
656653

657654
EntityReferenceFromEntities() {
655+
/*
656+
* 1. Reference obtained through a call to `entities` on the
657+
* service instance.
658+
*/
659+
658660
exists(MethodCallNode entitiesCall |
659-
entities = entitiesCall and
661+
entitiesAccess = entitiesCall and
660662
receiver = entitiesCall.getReceiver() and
661663
entitiesCall.getMethodName() = "entities" and
662664
this = entitiesCall.getAPropertyRead(entityName)
663665
)
664666
or
667+
/*
668+
* 2. Reference obtained through a read from property `entities` of the
669+
* service instance.
670+
*/
671+
665672
exists(PropRead entitiesRead |
666-
entities = entitiesRead and
673+
entitiesAccess = entitiesRead and
667674
receiver = entitiesRead.getBase() and
668675
entitiesRead.getPropertyName() = "entities" and
669676
this = entitiesRead.getAPropertyRead(entityName)
670677
)
671678
}
672679

673-
DataFlow::SourceNode getEntities() { result = entities }
680+
DataFlow::SourceNode getEntities() { result = entitiesAccess }
674681

675682
DataFlow::Node getReceiver() { result = receiver }
676683

677684
string getEntityName() { result = entityName }
678685

679686
abstract override CdlEntity getCqlDefinition();
687+
688+
abstract UserDefinedApplicationService getServiceDefinition();
680689
}
681690

682691
/**
@@ -686,13 +695,7 @@ class EntityReferenceFromUserDefinedServiceEntities extends EntityReferenceFromE
686695
{
687696
ServiceInstance service;
688697

689-
EntityReferenceFromUserDefinedServiceEntities() {
690-
this.getReceiver() = service.(ServiceInstanceFromThisNode)
691-
or
692-
this.getEntities() = service.(ServiceInstanceFromCdsConnectTo).getAMemberCall("entities")
693-
or
694-
this.getEntities() = service.(ServiceInstanceFromCdsConnectTo).getAPropertyRead("entities")
695-
}
698+
EntityReferenceFromUserDefinedServiceEntities() { this.getReceiver().getALocalSource() = service }
696699

697700
override CdlEntity getCqlDefinition() {
698701
this.getEntities() instanceof PropRead and
@@ -709,28 +712,31 @@ class EntityReferenceFromUserDefinedServiceEntities extends EntityReferenceFromE
709712
.getEntity(this.getEntities().(MethodCallNode).getArgument(0).getStringValue() + "." +
710713
entityName)
711714
}
715+
716+
override UserDefinedApplicationService getServiceDefinition() { result = service.getDefinition() }
712717
}
713718

714719
/**
715720
* db.entities, db.entities(...), cds.entities, cds.entities(...)
716721
*/
717722
class EntityReferenceFromDbOrCdsEntities extends EntityReferenceFromEntities {
718723
EntityReferenceFromDbOrCdsEntities() {
719-
exists(DBServiceInstanceFromCdsConnectTo db |
720-
entities = db.getAMemberCall("entities") or entities = db.getAPropertyRead("entities")
721-
)
722-
or
723-
exists(CdsFacade cds |
724-
entities = cds.getMember("entities").getACall() or
725-
entities = cds.getMember("entities").asSource()
726-
)
724+
this.getReceiver().getALocalSource() instanceof DBServiceInstanceFromCdsConnectTo or
725+
exists(CdsFacade cds | this.getReceiver().getALocalSource() = cds.getNode()) or
726+
exists(CdsFacade cds | this.getReceiver().getALocalSource() = cds.getMember("db").asSource())
727727
}
728728

729729
override CdlEntity getCqlDefinition() {
730730
/* NOTE: the result may be multiple; but they are all identical so we don't really care. */
731731
result.getName() =
732732
this.getEntities().(MethodCallNode).getArgument(0).getStringValue() + "." + entityName
733733
}
734+
735+
override UserDefinedApplicationService getServiceDefinition() {
736+
/* TODO: Always get the DB service definition. */
737+
none()
738+
// result.getServiceName() = this.(CdsEntitiesCall).getNamespace()
739+
}
734740
}
735741

736742
class EntityReferenceFromCqlClause extends EntityReference, ExprNode {

javascript/frameworks/cap/lib/advanced_security/javascript/frameworks/cap/CQL.qll

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,11 @@ class CqlClause extends TCqlClause {
299299
result = this.getRunner().getDefinition().getCdsDeclaration().getAnEntity()
300300
or
301301
/* 2. Variable whose value is a reference to an entity */
302-
exists(ExprNode entityReference | entityReference = this.getAccessingEntityReference() |
303-
result = entityReference.getALocalSource().(EntityReferenceFromEntities).getCqlDefinition()
304-
)
302+
result =
303+
this.getAccessingEntityReference()
304+
.getALocalSource()
305+
.(EntityReferenceFromEntities)
306+
.getCqlDefinition()
305307
}
306308
}
307309

0 commit comments

Comments
 (0)