Skip to content

Commit a19f06f

Browse files
committed
JS: Port checks to JS
1 parent 7f82056 commit a19f06f

File tree

4 files changed

+103
-4
lines changed

4 files changed

+103
-4
lines changed

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,42 @@ Specific::InvokeNode getInvocationFromPath(string package, string type, AccessPa
363363
result = getInvocationFromPath(package, type, path, path.getNumToken())
364364
}
365365

366+
/**
367+
* Holds if `name` is a valid name for an access path token in the identifying access path.
368+
*/
369+
bindingset[name]
370+
predicate isValidTokenNameInIdentifyingAccessPath(string name) {
371+
name = ["Argument", "Parameter", "ReturnValue", "WithArity"]
372+
or
373+
Specific::isExtraValidTokenNameInIdentifyingAccessPath(name)
374+
}
375+
376+
/**
377+
* Holds if `name` is a valid name for an access path token with no arguments, occuring
378+
* in an identifying access path.
379+
*/
380+
bindingset[name]
381+
predicate isValidNoArgumentTokenInIdentifyingAccessPath(string name) {
382+
name = "ReturnValue"
383+
or
384+
Specific::isExtraValidNoArgumentTokenInIdentifyingAccessPath(name)
385+
}
386+
387+
/**
388+
* Holds if `argument` is a valid argument to an access path token with the given `name`, occurring
389+
* in an identifying access path.
390+
*/
391+
bindingset[name, argument]
392+
predicate isValidTokenArgumentInIdentifyingAccessPath(string name, string argument) {
393+
name = ["Argument", "Parameter"] and
394+
argument.regexpMatch("(N-|-)?\\d+(\\.\\.(N-|-)?\\d+)?")
395+
or
396+
name = "WithArity" and
397+
argument.regexpMatch("\\d+(\\.\\.\\d+)?")
398+
or
399+
Specific::isExtraValidTokenArgumentInIdentifyingAccessPath(name, argument)
400+
}
401+
366402
/**
367403
* Module providing access to the imported models in terms of API graph nodes.
368404
*/
@@ -441,5 +477,27 @@ module ModelOutput {
441477
"CSV " + kind + " row should have " + expectedArity + " columns but has " + actualArity +
442478
": " + row
443479
)
480+
or
481+
// Check names and arguments of access path tokens
482+
exists(AccessPath path, AccessPathToken token |
483+
isRelevantFullPath(_, _, path) and
484+
token = path.getToken(_)
485+
|
486+
not isValidTokenNameInIdentifyingAccessPath(token.getName()) and
487+
result = "Invalid token name '" + token.getName() + "' in access path: " + path
488+
or
489+
isValidTokenNameInIdentifyingAccessPath(token.getName()) and
490+
exists(string argument |
491+
argument = token.getAnArgument() and
492+
not isValidTokenArgumentInIdentifyingAccessPath(token.getName(), argument) and
493+
result =
494+
"Invalid argument '" + argument + "' in token '" + token + "' in access path: " + path
495+
)
496+
or
497+
isValidTokenNameInIdentifyingAccessPath(token.getName()) and
498+
token.getNumArgument() = 0 and
499+
not isValidNoArgumentTokenInIdentifyingAccessPath(token.getName()) and
500+
result = "Invalid token '" + token + "' is missing its arguments, in access path: " + path
501+
)
444502
}
445503
}

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,29 @@ class InvokeNode = API::InvokeNode;
190190

191191
/** Gets an `InvokeNode` corresponding to an invocation of `node`. */
192192
InvokeNode getAnInvocationOf(API::Node node) { result = node.getAnInvocation() }
193+
194+
/**
195+
* Holds if `name` is a valid name for an access path token in the identifying access path.
196+
*/
197+
bindingset[name]
198+
predicate isExtraValidTokenNameInIdentifyingAccessPath(string name) {
199+
name = ["Member", "Instance", "Awaited", "ArrayElement", "Element", "MapValue", "NewCall", "Call"]
200+
}
201+
202+
/**
203+
* Holds if `name` is a valid name for an access path token with no arguments, occuring
204+
* in an identifying access path.
205+
*/
206+
predicate isExtraValidNoArgumentTokenInIdentifyingAccessPath(string name) {
207+
name = ["Instance", "Awaited", "ArrayElement", "Element", "MapValue", "NewCall", "Call"]
208+
}
209+
210+
/**
211+
* Holds if `argument` is a valid argument to an access path token with the given `name`, occurring
212+
* in an identifying access path.
213+
*/
214+
bindingset[name, argument]
215+
predicate isExtraValidTokenArgumentInIdentifyingAccessPath(string name, string argument) {
216+
name = ["Member"] and
217+
argument = any(string s)
218+
}

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,15 @@ syntaxErrors
8989
| Member[foo]] |
9090
| Member[foo]].Member[bar] |
9191
warning
92-
| CSV type row should have 5 columns but has 2: test;TooFewColumns |
93-
| CSV type row should have 5 columns but has 8: test;TooManyColumns;;;Member[Foo].Instance;too;many;columns |
92+
| CSV type row should have 5 columns but has 2: testlib;TooFewColumns |
93+
| CSV type row should have 5 columns but has 8: testlib;TooManyColumns;;;Member[Foo].Instance;too;many;columns |
94+
| Invalid argument '0-1' in token 'Argument[0-1]' in access path: Method[foo].Argument[0-1] |
95+
| Invalid argument '*' in token 'Argument[*]' in access path: Method[foo].Argument[*] |
96+
| Invalid token 'Argument' is missing its arguments, in access path: Method[foo].Argument |
97+
| Invalid token 'Member' is missing its arguments, in access path: Method[foo].Member |
98+
| Invalid token name 'Arg' in access path: Method[foo].Arg[0] |
99+
| Invalid token name 'Method' in access path: Method[foo].Arg[0] |
100+
| Invalid token name 'Method' in access path: Method[foo].Argument |
101+
| Invalid token name 'Method' in access path: Method[foo].Argument[0-1] |
102+
| Invalid token name 'Method' in access path: Method[foo].Argument[*] |
103+
| Invalid token name 'Method' in access path: Method[foo].Member |

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,13 @@ private class InvalidTypeModel extends ModelInput::TypeModelCsv {
7878
override predicate row(string row) {
7979
row =
8080
[
81-
"test;TooManyColumns;;;Member[Foo].Instance;too;many;columns", //
82-
"test;TooFewColumns", //
81+
"testlib;TooManyColumns;;;Member[Foo].Instance;too;many;columns", //
82+
"testlib;TooFewColumns", //
83+
"testlib;X;testlib;Y;Method[foo].Arg[0]", //
84+
"testlib;X;testlib;Y;Method[foo].Argument[0-1]", //
85+
"testlib;X;testlib;Y;Method[foo].Argument[*]", //
86+
"testlib;X;testlib;Y;Method[foo].Argument", //
87+
"testlib;X;testlib;Y;Method[foo].Member", //
8388
]
8489
}
8590
}

0 commit comments

Comments
 (0)