Skip to content

Commit 7c2cff3

Browse files
committed
JS: Factor out AccessPathSyntax.qll
1 parent e2cbf47 commit 7c2cff3

2 files changed

Lines changed: 67 additions & 47 deletions

File tree

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Module for parsing access paths from CSV models, both the identifying access path used
3+
* by dynamic languages, and the input/output specifications for summary steps.
4+
*
5+
* This file is used by shared data flow library and by the JavaScript libraries
6+
* (which does not use the shared data flow libraries).
7+
*/
8+
9+
/** Companion module to the `AccessPath` class. */
10+
module AccessPath {
11+
/** A string that should be parsed as an access path. */
12+
abstract class Range extends string {
13+
bindingset[this]
14+
Range() { any() }
15+
}
16+
}
17+
18+
/**
19+
* A string that occurs as an access path (either identifying or input/output spec)
20+
* which might be relevant for this database.
21+
*/
22+
class AccessPath extends string instanceof AccessPath::Range {
23+
/** Gets the `n`th token on the access path as a string. */
24+
string getRawToken(int n) {
25+
this != "" and // The empty path should have zero tokens, not a single empty token
26+
result = this.splitAt(".", n)
27+
}
28+
29+
/** Gets the `n`th token on the access path. */
30+
AccessPathToken getToken(int n) { result = this.getRawToken(n) }
31+
32+
/** Gets the number of tokens on the path. */
33+
int getNumToken() { result = count(int n | exists(this.getRawToken(n))) }
34+
}
35+
36+
/**
37+
* An access part token such as `Argument[1]` or `ReturnValue`, appearing in one or more access paths.
38+
*/
39+
class AccessPathToken extends string {
40+
AccessPathToken() { this = any(AccessPath path).getRawToken(_) }
41+
42+
private string getPart(int part) {
43+
result = this.regexpCapture("([^\\[]+)(?:\\[([^\\]]*)\\])?", part)
44+
}
45+
46+
/** Gets the name of the token, such as `Member` from `Member[x]` */
47+
string getName() { result = this.getPart(1) }
48+
49+
/**
50+
* Gets the argument list, such as `1,2` from `Member[1,2]`,
51+
* or has no result if there are no arguments.
52+
*/
53+
string getArgumentList() { result = this.getPart(2) }
54+
55+
/** Gets the `n`th argument to this token, such as `x` or `y` from `Member[x,y]`. */
56+
string getArgument(int n) { result = this.getArgumentList().splitAt(",", n) }
57+
58+
/** Gets an argument to this token, such as `x` or `y` from `Member[x,y]`. */
59+
string getAnArgument() { result = this.getArgument(_) }
60+
61+
/** Gets the number of arguments to this token, such as 2 for `Member[x,y]` or zero for `ReturnValue`. */
62+
int getNumArgument() { result = count(int n | exists(this.getArgument(n))) }
63+
}

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

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
*/
5858

5959
private import Impl as Impl
60+
import AccessPathSyntax
6061

6162
private class Unit = Impl::Unit;
6263

@@ -257,31 +258,16 @@ predicate isRelevantFullPath(string package, string type, string path) {
257258
)
258259
}
259260

260-
/**
261-
* A string that occurs as an access path (either identifying or input/output spec)
262-
* which might be relevant for this database.
263-
*/
264-
class AccessPath extends string {
265-
AccessPath() {
261+
/** A string from a CSV row that should be parsed as an access path. */
262+
private class AccessPathRange extends AccessPath::Range {
263+
AccessPathRange() {
266264
isRelevantFullPath(_, _, this)
267265
or
268266
exists(string package | isRelevantPackage(package) |
269267
summaryModel(package, _, _, this, _, _) or
270268
summaryModel(package, _, _, _, this, _)
271269
)
272270
}
273-
274-
/** Gets the `n`th token on the access path as a string. */
275-
string getRawToken(int n) {
276-
this != "" and // The empty path should have zero tokens, not a single empty token
277-
result = this.splitAt(".", n)
278-
}
279-
280-
/** Gets the `n`th token on the access path. */
281-
AccessPathToken getToken(int n) { result = this.getRawToken(n) }
282-
283-
/** Gets the number of tokens on the path. */
284-
int getNumToken() { result = count(int n | exists(this.getRawToken(n))) }
285271
}
286272

287273
/**
@@ -431,35 +417,6 @@ private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPat
431417
result = getNodeFromInputOutputPath(baseNode, path, path.getNumToken())
432418
}
433419

434-
/**
435-
* An access part token such as `Argument[1]` or `ReturnValue`, appearing in one or more access paths.
436-
*/
437-
class AccessPathToken extends string {
438-
AccessPathToken() { this = any(AccessPath path).getRawToken(_) }
439-
440-
private string getPart(int part) {
441-
result = this.regexpCapture("([^\\[]+)(?:\\[([^\\]]*)\\])?", part)
442-
}
443-
444-
/** Gets the name of the token, such as `Member` from `Member[x]` */
445-
string getName() { result = this.getPart(1) }
446-
447-
/**
448-
* Gets the argument list, such as `1,2` from `Member[1,2]`,
449-
* or has no result if there are no arguments.
450-
*/
451-
string getArgumentList() { result = this.getPart(2) }
452-
453-
/** Gets the `n`th argument to this token, such as `x` or `y` from `Member[x,y]`. */
454-
string getArgument(int n) { result = this.getArgumentList().splitAt(",", n) }
455-
456-
/** Gets an argument to this token, such as `x` or `y` from `Member[x,y]`. */
457-
string getAnArgument() { result = this.getArgument(_) }
458-
459-
/** Gets the number of arguments to this token, such as 2 for `Member[x,y]` or zero for `ReturnValue`. */
460-
int getNumArgument() { result = count(int n | exists(this.getArgument(n))) }
461-
}
462-
463420
/**
464421
* Convenience-predicate for extracting two capture groups at once.
465422
*/

0 commit comments

Comments
 (0)