Skip to content

Commit 290b0fc

Browse files
authored
Merge pull request #16308 from asgerf/js/model-generation-quote
JS: Fix naming issue in generated models
2 parents 332d118 + db07c16 commit 290b0fc

File tree

6 files changed

+40
-24
lines changed

6 files changed

+40
-24
lines changed

javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,11 @@ module ModelExport<ModelExportSig S> {
108108
}
109109

110110
predicate exposedName(API::Node node, string type, string path) {
111-
node = API::moduleExport(type) and path = ""
111+
exists(string moduleName |
112+
node = API::moduleExport(moduleName) and
113+
path = "" and
114+
type = "(" + moduleName + ")"
115+
)
112116
}
113117

114118
predicate suggestedName(API::Node node, string type) {

javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ class Location = JS::Location;
3434
*
3535
* Type names have form `package.type` or just `package` if referring to the package export
3636
* object. If `package` contains a `.` character it must be enclosed in single quotes, such as `'package'.type`.
37+
*
38+
* A type name of form `(package)` may also be used when refering to the package export object.
39+
* We allow this syntax as an alternative to the above, so models generated based on `EndpointNaming` look more consistent.
40+
* However, access paths are deliberately not parsed here, as we can not handle aliasing at this stage.
41+
* The model generator must explicitly generate the step between `(package)` and `(package).foo`, for example.
3742
*/
3843
bindingset[rawType]
3944
predicate parseTypeString(string rawType, string package, string qualifiedName) {
@@ -42,6 +47,9 @@ predicate parseTypeString(string rawType, string package, string qualifiedName)
4247
package = rawType.regexpCapture(regexp, 1).regexpReplaceAll("^'|'$", "") and
4348
qualifiedName = rawType.regexpCapture(regexp, 2).regexpReplaceAll("^\\.", "")
4449
)
50+
or
51+
package = rawType.regexpCapture("[(]([^)]+)[)]", 1) and
52+
qualifiedName = ""
4553
}
4654

4755
/**

javascript/ql/test/library-tests/ModelGeneration/ModelGeneration.expected

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
typeModel
2-
| (aliases).Alias1 | aliases | Member[Alias1] |
3-
| (aliases).Alias1 | aliases | Member[Alias2] |
4-
| (aliases).Alias1 | aliases | Member[Alias3].Member[x] |
5-
| (aliases).Alias1 | aliases | Member[Alias4].Member[x].Member[x] |
6-
| (aliases).Alias1 | aliases | Member[AliasedClass] |
2+
| (aliases).Alias1 | (aliases) | Member[Alias1] |
3+
| (aliases).Alias1 | (aliases) | Member[Alias2] |
4+
| (aliases).Alias1 | (aliases) | Member[Alias3].Member[x] |
5+
| (aliases).Alias1 | (aliases) | Member[Alias4].Member[x].Member[x] |
6+
| (aliases).Alias1 | (aliases) | Member[AliasedClass] |
77
| (aliases).Alias1.prototype | (aliases).Alias1 | Instance |
88
| (aliases).Alias1.prototype | (aliases).Alias1.prototype.foo | ReturnValue |
99
| (aliases).Alias1.prototype.foo | (aliases).Alias1.prototype | Member[foo] |
10-
| (long-access-path).a.shortcut.d | long-access-path | Member[a].Member[b].Member[c].Member[d] |
11-
| (long-access-path).a.shortcut.d | long-access-path | Member[a].Member[shortcut].Member[d] |
10+
| (long-access-path).a.shortcut.d | (long-access-path) | Member[a].Member[b].Member[c].Member[d] |
11+
| (long-access-path).a.shortcut.d | (long-access-path) | Member[a].Member[shortcut].Member[d] |
1212
| (long-access-path).a.shortcut.d.e | (long-access-path).a.shortcut.d | Member[e] |
13-
| (reexport).func | reexport | Member[func] |
14-
| (return-this).FluentInterface | return-this | Member[FluentInterface] |
13+
| (reexport).func | (reexport) | Member[func] |
14+
| (return-this).FluentInterface | (return-this) | Member[FluentInterface] |
1515
| (return-this).FluentInterface.prototype | (return-this).FluentInterface | Instance |
1616
| (return-this).FluentInterface.prototype | (return-this).FluentInterface.prototype.bar | ReturnValue |
1717
| (return-this).FluentInterface.prototype | (return-this).FluentInterface.prototype.baz | ReturnValue |
@@ -21,45 +21,45 @@ typeModel
2121
| (return-this).FluentInterface.prototype.foo | (return-this).FluentInterface.prototype | Member[foo] |
2222
| (return-this).FluentInterface.prototype.notFluent | (return-this).FluentInterface.prototype | Member[notFluent] |
2323
| (return-this).FluentInterface.prototype.notFluent2 | (return-this).FluentInterface.prototype | Member[notFluent2] |
24-
| (root-function).PublicClass | root-function | Member[PublicClass] |
24+
| (root-function).PublicClass | (root-function) | Member[PublicClass] |
25+
| (root-function).PublicClass.prototype | (root-function) | ReturnValue |
2526
| (root-function).PublicClass.prototype | (root-function).PublicClass | Instance |
26-
| (root-function).PublicClass.prototype | root-function | ReturnValue |
2727
| (root-function).PublicClass.prototype.method | (root-function).PublicClass.prototype | Member[method] |
28-
| (semi-internal-class).PublicClass | semi-internal-class | Member[PublicClass] |
28+
| (semi-internal-class).PublicClass | (semi-internal-class) | Member[PublicClass] |
2929
| (semi-internal-class).PublicClass.prototype | (semi-internal-class).PublicClass | Instance |
3030
| (semi-internal-class).PublicClass.prototype | (semi-internal-class).SemiInternalClass.prototype.method | ReturnValue |
3131
| (semi-internal-class).PublicClass.prototype | (semi-internal-class).getAnonymous~expr2 | ReturnValue |
3232
| (semi-internal-class).PublicClass.prototype.publicMethod | (semi-internal-class).PublicClass.prototype | Member[publicMethod] |
3333
| (semi-internal-class).SemiInternalClass.prototype | (semi-internal-class).get | ReturnValue |
3434
| (semi-internal-class).SemiInternalClass.prototype.method | (semi-internal-class).SemiInternalClass.prototype | Member[method] |
35-
| (semi-internal-class).get | semi-internal-class | Member[get] |
36-
| (semi-internal-class).getAnonymous | semi-internal-class | Member[getAnonymous] |
35+
| (semi-internal-class).get | (semi-internal-class) | Member[get] |
36+
| (semi-internal-class).getAnonymous | (semi-internal-class) | Member[getAnonymous] |
3737
| (semi-internal-class).getAnonymous~expr1 | (semi-internal-class).getAnonymous | ReturnValue |
3838
| (semi-internal-class).getAnonymous~expr2 | (semi-internal-class).getAnonymous~expr1 | Member[method] |
39-
| (subclass).A | subclass | Member[A] |
39+
| (subclass).A | (subclass) | Member[A] |
4040
| (subclass).A.prototype | (subclass).A | Instance |
4141
| (subclass).A.prototype | (subclass).B.prototype | |
4242
| (subclass).A.prototype | (subclass).ExposedMidSubClass.prototype~expr1 | |
4343
| (subclass).A.prototype.a | (subclass).A.prototype | Member[a] |
44-
| (subclass).B | subclass | Member[B] |
44+
| (subclass).B | (subclass) | Member[B] |
4545
| (subclass).B.prototype | (subclass).B | Instance |
4646
| (subclass).B.prototype | (subclass).C.prototype | |
4747
| (subclass).B.prototype.b | (subclass).B.prototype | Member[b] |
48-
| (subclass).C | subclass | Member[C] |
48+
| (subclass).C | (subclass) | Member[C] |
4949
| (subclass).C.prototype | (subclass).C | Instance |
5050
| (subclass).C.prototype.c | (subclass).C.prototype | Member[c] |
51-
| (subclass).D | subclass | Member[D] |
51+
| (subclass).D | (subclass) | Member[D] |
5252
| (subclass).D.prototype | (subclass).D | Instance |
5353
| (subclass).D.prototype.d | (subclass).D.prototype | Member[d] |
54-
| (subclass).ExposedMidSubClass | subclass | Member[ExposedMidSubClass] |
54+
| (subclass).ExposedMidSubClass | (subclass) | Member[ExposedMidSubClass] |
5555
| (subclass).ExposedMidSubClass.prototype | (subclass).ExposedMidSubClass | Instance |
5656
| (subclass).ExposedMidSubClass.prototype.m | (subclass).ExposedMidSubClass.prototype | Member[m] |
5757
| (subclass).ExposedMidSubClass.prototype~expr1 | (subclass).ExposedMidSubClass.prototype | |
58+
| upstream-lib | (reexport) | Member[lib] |
5859
| upstream-lib | (reexport).func | ReturnValue |
59-
| upstream-lib | reexport | Member[lib] |
6060
| upstream-lib.Type | (subclass).D.prototype | |
61-
| upstream-lib.XYZ | reexport | Member[x].Member[y].Member[z] |
62-
| upstream-lib.XYZ | reexport | Member[xy].Member[z] |
61+
| upstream-lib.XYZ | (reexport) | Member[x].Member[y].Member[z] |
62+
| upstream-lib.XYZ | (reexport) | Member[xy].Member[z] |
6363
summaryModel
6464
| (aliases).Alias1.prototype | | | Member[foo].ReturnValue | type |
6565
| (return-this).FluentInterface.prototype | | | Member[bar].ReturnValue | type |

javascript/ql/test/library-tests/frameworks/data/test.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ taintFlow
7878
| test.js:265:6:265:39 | new MyS ... ource() | test.js:265:6:265:39 | new MyS ... ource() |
7979
| test.js:269:10:269:31 | this.ba ... ource() | test.js:269:10:269:31 | this.ba ... ource() |
8080
| test.js:272:6:272:40 | new MyS ... ource() | test.js:272:6:272:40 | new MyS ... ource() |
81+
| test.js:274:6:274:39 | testlib ... eName() | test.js:274:6:274:39 | testlib ... eName() |
8182
isSink
8283
| test.js:54:18:54:25 | source() | test-sink |
8384
| test.js:55:22:55:29 | source() | test-sink |

javascript/ql/test/library-tests/frameworks/data/test.ext.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ extensions:
1010
- ['testlib', 'Member[MethodDecorator].DecoratedMember.Parameter[0]', 'test-source']
1111
- ['testlib', 'Member[ParamDecoratorSource].DecoratedParameter', 'test-source']
1212
- ['testlib', 'Member[getSource].ReturnValue', 'test-source']
13+
- ['(testlib)', 'Member[parenthesizedPackageName].ReturnValue', 'test-source']
1314

1415
- addsTo:
1516
pack: codeql/javascript-all
@@ -73,4 +74,4 @@ extensions:
7374
data:
7475
- ['ABC', 'Member[a].Member[b].WithArity[0].ReturnValue.Member[c]']
7576
- ['LeftRight', 'Member[left].TypeVar[LeftRight].Member[right]']
76-
- ['LeftRight', 'Member[x]']
77+
- ['LeftRight', 'Member[x]']

javascript/ql/test/library-tests/frameworks/data/test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,3 +270,5 @@ class MySubclass2 extends MySubclass {
270270
}
271271
}
272272
sink(new MySubclass2().baseclassSource()); // NOT OK
273+
274+
sink(testlib.parenthesizedPackageName()); // NOT OK

0 commit comments

Comments
 (0)