Skip to content

Commit 19e9deb

Browse files
committed
Draft out getImportedModule and getSubclassedModule
1 parent ad612bb commit 19e9deb

File tree

2 files changed

+88
-11
lines changed
  • javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5

2 files changed

+88
-11
lines changed

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

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,17 @@ class SapDefineModule extends AmdModuleDefinition::Range, MethodCallExpr, UserMo
165165
sap.getName() = "sap" and
166166
sapUi.getBase() = sap and
167167
sapUi.getPropertyName() = "ui" and
168-
this.getReceiver() = sapUiDefine
169-
// and this.getMethodName() = "define"
168+
this.getReceiver() = sapUiDefine and
169+
this.getMethodName() = ["define", "require"] // TODO: Treat sap.ui.declare in its own class
170170
)
171171
}
172172

173+
SapExtendCall getExtendCall() { result.getDefine() = this }
174+
175+
string getName() { result = this.getExtendCall().getName() }
176+
177+
Module asModule() { result = this.getTopLevel() }
178+
173179
string getDependency(int i) {
174180
result = this.(AmdModuleDefinition).getDependencyExpr(i).getStringValue()
175181
}
@@ -185,20 +191,67 @@ class SapDefineModule extends AmdModuleDefinition::Range, MethodCallExpr, UserMo
185191
WebApp getWebApp() { this.getFile() = result.getAResource() }
186192

187193
/**
188-
* Gets the module defined with sap.ui.define that imports and extends this module.
194+
* Gets the module defined with sap.ui.define that imports and extends (subclasses) this module.
189195
*/
190196
SapDefineModule getExtendingModule() {
191-
exists(SapExtendCall baseExtendCall, SapExtendCall subclassExtendCall |
192-
baseExtendCall.getDefine() = this and
193-
result = subclassExtendCall.getDefine() and
194-
result
195-
.getRequiredObject(baseExtendCall.getName().replaceAll(".", "/"))
196-
.asSourceNode()
197-
.flowsTo(subclassExtendCall.getReceiver())
198-
)
197+
// exists(SapExtendCall baseExtendCall, SapExtendCall subclassExtendCall |
198+
// baseExtendCall.getDefine() = this and
199+
// result = subclassExtendCall.getDefine() and
200+
// result
201+
// .getRequiredObject(baseExtendCall.getName().replaceAll(".", "/"))
202+
// .asSourceNode()
203+
// .flowsTo(subclassExtendCall.getReceiver())
204+
// )
205+
none() // TODO
199206
}
200207
}
201208

209+
/**
210+
* Holds if the `importingModule` "imports" the `importedModule` via path `importPath`.
211+
*/
212+
private predicate importerAndImportee(
213+
SapDefineModule importingModule, SapDefineModule importedModule, string importPath
214+
) {
215+
/* 1. Absolute import paths: We resolve this ourselves. */
216+
exists(string importedModuleDefinitionPath, string importedModuleDefinitionPathSlashNormalized |
217+
/*
218+
* Let `importPath` = "my/app/path1/path2/controller/Some.controller",
219+
* `importedModuleDefinitionPath` = "my.app.path1.path2.controller.Some",
220+
* `importedModuleDefinitionPathSlashNormalized` = "my/app/path1/path2/controller/Some".
221+
* Then, `importedModuleDefinitionPathSlashNormalized` matches `importPath`.
222+
*/
223+
224+
importPath = importingModule.asModule().getAnImport().getImportedPathExpr().getStringValue() and
225+
importedModuleDefinitionPath = importedModule.getExtendCall().getName() and
226+
importedModuleDefinitionPathSlashNormalized = importedModuleDefinitionPath.replaceAll(".", "/") and
227+
importPath.matches(importedModuleDefinitionPathSlashNormalized + "%")
228+
)
229+
or
230+
/*
231+
* 2. Relative import paths: We delegate the heaving lifting of resolving to
232+
* `Import.resolveImportedPath/0`.
233+
*/
234+
235+
exists(Import import_ |
236+
importPath = import_.getImportedPathExpr().getStringValue() and
237+
import_ = importingModule.asModule().getAnImport() and
238+
import_.resolveImportedPath() = importedModule.getTopLevel()
239+
)
240+
}
241+
242+
/**
243+
* Holds if the `importingModule` extends the `importedModule`, imported via path `importPath`.
244+
*/
245+
private predicate importerExtendsImportee(
246+
SapDefineModule importingModule, SapDefineModule importedModule, string importPath
247+
) {
248+
importerAndImportee(importingModule, importedModule, importPath) and
249+
importingModule
250+
.getRequiredObject(importPath)
251+
.asSourceNode()
252+
.flowsTo(importingModule.getExtendCall().getReceiver())
253+
}
254+
202255
class JQuerySap extends DataFlow::SourceNode {
203256
JQuerySap() {
204257
exists(DataFlow::GlobalVarRefNode global |
@@ -738,6 +791,11 @@ abstract class UI5InternalModel extends UI5Model, NewNode {
738791
abstract string getPathString();
739792

740793
abstract string getPathString(Property property);
794+
795+
/**
796+
* Holds if the content of the model is statically determinable.
797+
*/
798+
abstract predicate contentIsStaticallyVisible();
741799
}
742800

743801
import ManifestJson
@@ -1118,6 +1176,16 @@ class JsonModel extends UI5InternalModel {
11181176
)
11191177
}
11201178

1179+
override predicate contentIsStaticallyVisible() {
1180+
/* 1. There is at least one path string that can be constructed out of the path string. */
1181+
exists(this.getPathString())
1182+
or
1183+
/* 2. There is a JSON file that can be loaded from. */
1184+
exists(JsonObject jsonObject |
1185+
jsonObject = resolveDirectPath(this.getArgument(0).getStringValue())
1186+
)
1187+
}
1188+
11211189
/**
11221190
* A model possibly supporting two-way binding explicitly set as a one-way binding model.
11231191
*/
@@ -1175,6 +1243,8 @@ class XmlModel extends UI5InternalModel {
11751243
}
11761244

11771245
override string getPathString() { result = "TODO" }
1246+
1247+
override predicate contentIsStaticallyVisible() { exists(this.getPathString()) }
11781248
}
11791249

11801250
class ResourceModel extends UI5Model, ModelReference {

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,13 @@ abstract class UI5BindingPath extends BindingPath {
162162
inSameWebApp(this.getLocation().getFile(), result.getFile())
163163
)
164164
or
165+
exists(JsonModel model, CustomController controller |
166+
not model.contentIsStaticallyVisible() and
167+
result = model and
168+
this.getView() = controller.getAViewReference().getDefinition() and
169+
controller.getModel() = result
170+
)
171+
or
165172
/* 2. External (Server-side) model */
166173
result = this.getModel().(UI5ExternalModel) and
167174
/* Restrict search to inside the same webapp. */

0 commit comments

Comments
 (0)