mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
add JS support the using keyword
This commit is contained in:
@@ -51,6 +51,9 @@ import java.util.Set;
|
||||
public class ESNextParser extends JSXParser {
|
||||
public ESNextParser(Options options, String input, int startPos) {
|
||||
super(options.allowImportExportEverywhere(true), input, startPos);
|
||||
|
||||
// recognise `using` as a keyword. See https://github.com/tc39/proposal-explicit-resource-management
|
||||
this.keywords.add("using");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -2737,7 +2737,7 @@ public class Parser {
|
||||
return this.parseThrowStatement(startLoc);
|
||||
} else if (starttype == TokenType._try) {
|
||||
return this.parseTryStatement(startLoc);
|
||||
} else if (starttype == TokenType._const || starttype == TokenType._var) {
|
||||
} else if (starttype == TokenType._const || starttype == TokenType._var || starttype == TokenType._using) {
|
||||
if (kind == null) kind = String.valueOf(this.value);
|
||||
if (!declaration && !kind.equals("var")) this.unexpected();
|
||||
return this.parseVarStatement(startLoc, kind);
|
||||
@@ -2840,7 +2840,7 @@ public class Parser {
|
||||
this.expect(TokenType.parenL);
|
||||
if (this.type == TokenType.semi) return this.parseFor(startLoc, null);
|
||||
boolean isLet = this.isLet();
|
||||
if (this.type == TokenType._var || this.type == TokenType._const || isLet) {
|
||||
if (this.type == TokenType._var || this.type == TokenType._const || isLet || this.type == TokenType._using) { // TODO: Add test for this.
|
||||
Position initStartLoc = this.startLoc;
|
||||
String kind = isLet ? "let" : String.valueOf(this.value);
|
||||
this.next();
|
||||
@@ -3122,7 +3122,7 @@ public class Parser {
|
||||
Expression init = null;
|
||||
if (this.eat(TokenType.eq)) {
|
||||
init = this.parseMaybeAssign(isFor, null, null);
|
||||
} else if (kind.equals("const")
|
||||
} else if ((kind.equals("const") || kind.equals("using"))
|
||||
&& !(this.type == TokenType._in
|
||||
|| (this.options.ecmaVersion() >= 6 && this.isContextual("of")))) {
|
||||
this.raiseRecoverable(
|
||||
|
||||
@@ -180,6 +180,7 @@ public class TokenType {
|
||||
_try = new TokenType(kw("try")),
|
||||
_var = new TokenType(kw("var")),
|
||||
_const = new TokenType(kw("const")),
|
||||
_using = new TokenType(kw("using")),
|
||||
_while = new TokenType(kw("while").isLoop()),
|
||||
_with = new TokenType(kw("with")),
|
||||
_new = new TokenType(kw("new").beforeExpr().startsExpr()),
|
||||
|
||||
@@ -28,8 +28,8 @@ public class VariableDeclaration extends Statement {
|
||||
}
|
||||
|
||||
/**
|
||||
* The kind of this variable declaration statement; one of <code>"var"</code>, <code>"let"</code>
|
||||
* or <code>"const"</code>.
|
||||
* The kind of this variable declaration statement; one of <code>"var"</code>, <code>"let"</code>,
|
||||
* <code>"const"</code>, or <code>"using"</code>.
|
||||
*/
|
||||
public String getKind() {
|
||||
return kind;
|
||||
@@ -42,6 +42,7 @@ public class VariableDeclaration extends Statement {
|
||||
*/
|
||||
public boolean isBlockScoped(ECMAVersion ecmaVersion) {
|
||||
return "let".equals(kind)
|
||||
|| "using".equals(kind)
|
||||
|| ecmaVersion.compareTo(ECMAVersion.ECMA2015) >= 0 && "const".equals(kind);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ public class StmtKinds {
|
||||
declKinds.put("var", 18);
|
||||
declKinds.put("const", 22);
|
||||
declKinds.put("let", 23);
|
||||
declKinds.put("using", 40);
|
||||
}
|
||||
|
||||
public static int getStmtKind(final Statement stmt) {
|
||||
|
||||
@@ -246,13 +246,15 @@ private module PrintJavaScript {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets "var" or "const" or "let" depending on what type of declaration `decl` is.
|
||||
* Gets "var" or "const" or "let" or "using" depending on what type of declaration `decl` is.
|
||||
*/
|
||||
private string getDeclarationKeyword(DeclStmt decl) {
|
||||
decl instanceof VarDeclStmt and result = "var"
|
||||
or
|
||||
decl instanceof ConstDeclStmt and result = "const"
|
||||
or
|
||||
decl instanceof UsingDeclStmt and result = "using"
|
||||
or
|
||||
decl instanceof LetStmt and result = "let"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1041,6 +1041,17 @@ class VarDeclStmt extends @var_decl_stmt, DeclStmt { }
|
||||
*/
|
||||
class ConstDeclStmt extends @const_decl_stmt, DeclStmt { }
|
||||
|
||||
/**
|
||||
* A `using` declaration statement.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* using file = new TextFile("file.txt");
|
||||
* ```
|
||||
*/
|
||||
class UsingDeclStmt extends @using_decl_stmt, DeclStmt { }
|
||||
|
||||
/**
|
||||
* A `let` declaration statement.
|
||||
*
|
||||
|
||||
@@ -162,9 +162,10 @@ case @stmt.kind of
|
||||
| 37 = @external_module_declaration
|
||||
| 38 = @export_as_namespace_declaration
|
||||
| 39 = @global_augmentation_declaration
|
||||
| 40 = @using_decl_stmt
|
||||
;
|
||||
|
||||
@decl_stmt = @var_decl_stmt | @const_decl_stmt | @let_stmt | @legacy_let_stmt;
|
||||
@decl_stmt = @var_decl_stmt | @const_decl_stmt | @let_stmt | @legacy_let_stmt | @using_decl_stmt;
|
||||
|
||||
@export_declaration = @export_all_declaration | @export_default_declaration | @export_named_declaration;
|
||||
|
||||
|
||||
@@ -13,8 +13,9 @@
|
||||
import javascript
|
||||
import semmle.javascript.RestrictedLocations
|
||||
|
||||
from ConstDeclStmt cds, VariableDeclarator decl, VarDef def, Variable v
|
||||
from DeclStmt cds, VariableDeclarator decl, VarDef def, Variable v
|
||||
where
|
||||
(cds instanceof ConstDeclStmt or cds instanceof UsingDeclStmt) and
|
||||
decl = cds.getADecl() and
|
||||
def.getAVariable() = v and
|
||||
decl.getBindingPattern().getAVariable() = v and
|
||||
|
||||
@@ -39,6 +39,8 @@ predicate isSymbolicConstant(Variable v) {
|
||||
exists(VarDef vd | vd = getSingleDef(v) |
|
||||
vd.(VariableDeclarator).getDeclStmt() instanceof ConstDeclStmt
|
||||
or
|
||||
vd.(VariableDeclarator).getDeclStmt() instanceof UsingDeclStmt
|
||||
or
|
||||
isConstant(vd.getSource())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
nodes
|
||||
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
|
||||
| tst.js:1:1:9:1 | [FunctionDeclStmt] functio ... } } | semmle.label | [FunctionDeclStmt] functio ... } } |
|
||||
| tst.js:1:1:9:1 | [FunctionDeclStmt] functio ... } } | semmle.order | 1 |
|
||||
| tst.js:1:10:1:10 | [VarDecl] g | semmle.label | [VarDecl] g |
|
||||
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | semmle.label | [BlockStmt] { u ... } } |
|
||||
| tst.js:2:5:2:33 | [DeclStmt] using stream = ... | semmle.label | [DeclStmt] using stream = ... |
|
||||
| tst.js:2:11:2:16 | [VarDecl] stream | semmle.label | [VarDecl] stream |
|
||||
| tst.js:2:11:2:32 | [VariableDeclarator] stream ... ource() | semmle.label | [VariableDeclarator] stream ... ource() |
|
||||
| tst.js:2:20:2:30 | [VarRef] getResource | semmle.label | [VarRef] getResource |
|
||||
| tst.js:2:20:2:32 | [CallExpr] getResource() | semmle.label | [CallExpr] getResource() |
|
||||
| tst.js:4:5:4:7 | [VarRef] let | semmle.label | [VarRef] let |
|
||||
| tst.js:4:5:4:19 | [CallExpr] let (test = 20) | semmle.label | [CallExpr] let (test = 20) |
|
||||
| tst.js:4:5:4:20 | [ExprStmt] let (test = 20); | semmle.label | [ExprStmt] let (test = 20); |
|
||||
| tst.js:4:10:4:13 | [VarRef] test | semmle.label | [VarRef] test |
|
||||
| tst.js:4:10:4:18 | [AssignExpr] test = 20 | semmle.label | [AssignExpr] test = 20 |
|
||||
| tst.js:4:17:4:18 | [Literal] 20 | semmle.label | [Literal] 20 |
|
||||
| tst.js:6:5:8:5 | [ForStmt] for (us ... . } | semmle.label | [ForStmt] for (us ... . } |
|
||||
| tst.js:6:10:6:38 | [DeclStmt] using stream2 = ... | semmle.label | [DeclStmt] using stream2 = ... |
|
||||
| tst.js:6:16:6:22 | [VarDecl] stream2 | semmle.label | [VarDecl] stream2 |
|
||||
| tst.js:6:16:6:38 | [VariableDeclarator] stream2 ... ource() | semmle.label | [VariableDeclarator] stream2 ... ource() |
|
||||
| tst.js:6:26:6:36 | [VarRef] getResource | semmle.label | [VarRef] getResource |
|
||||
| tst.js:6:26:6:38 | [CallExpr] getResource() | semmle.label | [CallExpr] getResource() |
|
||||
| tst.js:6:45:8:5 | [BlockStmt] { ... . } | semmle.label | [BlockStmt] { ... . } |
|
||||
edges
|
||||
| file://:0:0:0:0 | (Arguments) | tst.js:4:10:4:18 | [AssignExpr] test = 20 | semmle.label | 0 |
|
||||
| file://:0:0:0:0 | (Arguments) | tst.js:4:10:4:18 | [AssignExpr] test = 20 | semmle.order | 0 |
|
||||
| tst.js:1:1:9:1 | [FunctionDeclStmt] functio ... } } | tst.js:1:10:1:10 | [VarDecl] g | semmle.label | 0 |
|
||||
| tst.js:1:1:9:1 | [FunctionDeclStmt] functio ... } } | tst.js:1:10:1:10 | [VarDecl] g | semmle.order | 0 |
|
||||
| tst.js:1:1:9:1 | [FunctionDeclStmt] functio ... } } | tst.js:1:14:9:1 | [BlockStmt] { u ... } } | semmle.label | 5 |
|
||||
| tst.js:1:1:9:1 | [FunctionDeclStmt] functio ... } } | tst.js:1:14:9:1 | [BlockStmt] { u ... } } | semmle.order | 5 |
|
||||
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | tst.js:2:5:2:33 | [DeclStmt] using stream = ... | semmle.label | 1 |
|
||||
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | tst.js:2:5:2:33 | [DeclStmt] using stream = ... | semmle.order | 1 |
|
||||
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | tst.js:4:5:4:20 | [ExprStmt] let (test = 20); | semmle.label | 2 |
|
||||
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | tst.js:4:5:4:20 | [ExprStmt] let (test = 20); | semmle.order | 2 |
|
||||
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | tst.js:6:5:8:5 | [ForStmt] for (us ... . } | semmle.label | 3 |
|
||||
| tst.js:1:14:9:1 | [BlockStmt] { u ... } } | tst.js:6:5:8:5 | [ForStmt] for (us ... . } | semmle.order | 3 |
|
||||
| tst.js:2:5:2:33 | [DeclStmt] using stream = ... | tst.js:2:11:2:32 | [VariableDeclarator] stream ... ource() | semmle.label | 1 |
|
||||
| tst.js:2:5:2:33 | [DeclStmt] using stream = ... | tst.js:2:11:2:32 | [VariableDeclarator] stream ... ource() | semmle.order | 1 |
|
||||
| tst.js:2:11:2:32 | [VariableDeclarator] stream ... ource() | tst.js:2:11:2:16 | [VarDecl] stream | semmle.label | 1 |
|
||||
| tst.js:2:11:2:32 | [VariableDeclarator] stream ... ource() | tst.js:2:11:2:16 | [VarDecl] stream | semmle.order | 1 |
|
||||
| tst.js:2:11:2:32 | [VariableDeclarator] stream ... ource() | tst.js:2:20:2:32 | [CallExpr] getResource() | semmle.label | 2 |
|
||||
| tst.js:2:11:2:32 | [VariableDeclarator] stream ... ource() | tst.js:2:20:2:32 | [CallExpr] getResource() | semmle.order | 2 |
|
||||
| tst.js:2:20:2:32 | [CallExpr] getResource() | tst.js:2:20:2:30 | [VarRef] getResource | semmle.label | 0 |
|
||||
| tst.js:2:20:2:32 | [CallExpr] getResource() | tst.js:2:20:2:30 | [VarRef] getResource | semmle.order | 0 |
|
||||
| tst.js:4:5:4:19 | [CallExpr] let (test = 20) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
|
||||
| tst.js:4:5:4:19 | [CallExpr] let (test = 20) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
|
||||
| tst.js:4:5:4:19 | [CallExpr] let (test = 20) | tst.js:4:5:4:7 | [VarRef] let | semmle.label | 0 |
|
||||
| tst.js:4:5:4:19 | [CallExpr] let (test = 20) | tst.js:4:5:4:7 | [VarRef] let | semmle.order | 0 |
|
||||
| tst.js:4:5:4:20 | [ExprStmt] let (test = 20); | tst.js:4:5:4:19 | [CallExpr] let (test = 20) | semmle.label | 1 |
|
||||
| tst.js:4:5:4:20 | [ExprStmt] let (test = 20); | tst.js:4:5:4:19 | [CallExpr] let (test = 20) | semmle.order | 1 |
|
||||
| tst.js:4:10:4:18 | [AssignExpr] test = 20 | tst.js:4:10:4:13 | [VarRef] test | semmle.label | 1 |
|
||||
| tst.js:4:10:4:18 | [AssignExpr] test = 20 | tst.js:4:10:4:13 | [VarRef] test | semmle.order | 1 |
|
||||
| tst.js:4:10:4:18 | [AssignExpr] test = 20 | tst.js:4:17:4:18 | [Literal] 20 | semmle.label | 2 |
|
||||
| tst.js:4:10:4:18 | [AssignExpr] test = 20 | tst.js:4:17:4:18 | [Literal] 20 | semmle.order | 2 |
|
||||
| tst.js:6:5:8:5 | [ForStmt] for (us ... . } | tst.js:6:10:6:38 | [DeclStmt] using stream2 = ... | semmle.label | 1 |
|
||||
| tst.js:6:5:8:5 | [ForStmt] for (us ... . } | tst.js:6:10:6:38 | [DeclStmt] using stream2 = ... | semmle.order | 1 |
|
||||
| tst.js:6:5:8:5 | [ForStmt] for (us ... . } | tst.js:6:45:8:5 | [BlockStmt] { ... . } | semmle.label | 2 |
|
||||
| tst.js:6:5:8:5 | [ForStmt] for (us ... . } | tst.js:6:45:8:5 | [BlockStmt] { ... . } | semmle.order | 2 |
|
||||
| tst.js:6:10:6:38 | [DeclStmt] using stream2 = ... | tst.js:6:16:6:38 | [VariableDeclarator] stream2 ... ource() | semmle.label | 1 |
|
||||
| tst.js:6:10:6:38 | [DeclStmt] using stream2 = ... | tst.js:6:16:6:38 | [VariableDeclarator] stream2 ... ource() | semmle.order | 1 |
|
||||
| tst.js:6:16:6:38 | [VariableDeclarator] stream2 ... ource() | tst.js:6:16:6:22 | [VarDecl] stream2 | semmle.label | 1 |
|
||||
| tst.js:6:16:6:38 | [VariableDeclarator] stream2 ... ource() | tst.js:6:16:6:22 | [VarDecl] stream2 | semmle.order | 1 |
|
||||
| tst.js:6:16:6:38 | [VariableDeclarator] stream2 ... ource() | tst.js:6:26:6:38 | [CallExpr] getResource() | semmle.label | 2 |
|
||||
| tst.js:6:16:6:38 | [VariableDeclarator] stream2 ... ource() | tst.js:6:26:6:38 | [CallExpr] getResource() | semmle.order | 2 |
|
||||
| tst.js:6:26:6:38 | [CallExpr] getResource() | tst.js:6:26:6:36 | [VarRef] getResource | semmle.label | 0 |
|
||||
| tst.js:6:26:6:38 | [CallExpr] getResource() | tst.js:6:26:6:36 | [VarRef] getResource | semmle.order | 0 |
|
||||
graphProperties
|
||||
| semmle.graphKind | tree |
|
||||
@@ -0,0 +1,2 @@
|
||||
import javascript
|
||||
import semmle.javascript.PrintAst
|
||||
@@ -0,0 +1,9 @@
|
||||
function g() {
|
||||
using stream = getResource();
|
||||
|
||||
let (test = 20); // <- I didn't know this was a thing
|
||||
|
||||
for (using stream2 = getResource(); ; ) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user