mirror of
https://github.com/github/codeql.git
synced 2026-04-20 06:24:03 +02:00
JavaScript: Add support for Google Cloud Spanner.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
* Support for popular libraries has been improved. Consequently, queries may produce more results on code bases that use the following features:
|
||||
- file system access, for example through [fs-extra](https://github.com/jprichardson/node-fs-extra) or [globby](https://www.npmjs.com/package/globby)
|
||||
- the [Google Cloud Spanner](https://cloud.google.com/spanner) database
|
||||
|
||||
* The type inference now handles nested imports (that is, imports not appearing at the toplevel). This may yield fewer false-positive results on projects that use this non-standard language feature.
|
||||
|
||||
|
||||
@@ -387,3 +387,105 @@ private module Sequelize {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modelling the Google Cloud Spanner library.
|
||||
*/
|
||||
private module Spanner {
|
||||
/**
|
||||
* Gets a node that refers to the `Spanner` class
|
||||
*/
|
||||
DataFlow::SourceNode spanner() {
|
||||
// older versions
|
||||
result = DataFlow::moduleImport("@google-cloud/spanner")
|
||||
or
|
||||
// newer versions
|
||||
result = DataFlow::moduleMember("@google-cloud/spanner", "Spanner")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that refers to an instance of the `Database` class.
|
||||
*/
|
||||
DataFlow::SourceNode database() {
|
||||
result = spanner().getAnInvocation().getAMethodCall("instance").getAMethodCall("database")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that refers to an instance of the `v1.SpannerClient` class.
|
||||
*/
|
||||
DataFlow::SourceNode v1SpannerClient() {
|
||||
result = spanner().getAPropertyRead("v1").getAPropertyRead("SpannerClient").getAnInstantiation()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node that refers to a transaction object.
|
||||
*/
|
||||
DataFlow::SourceNode transaction() {
|
||||
result = database().getAMethodCall("runTransaction").getCallback(0).getParameter(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a Spanner method that executes a SQL query.
|
||||
*/
|
||||
abstract class SqlExecution extends DatabaseAccess, DataFlow::InvokeNode {
|
||||
/**
|
||||
* Gets the position of the query argument; default is zero, which can be overridden
|
||||
* by subclasses.
|
||||
*/
|
||||
int getQueryArgumentPosition() {
|
||||
result = 0
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
result = getArgument(getQueryArgumentPosition()) or
|
||||
result = getOptionArgument(getQueryArgumentPosition(), "sql")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `Database.run` or `Database.runStream`.
|
||||
*/
|
||||
class DatabaseRunCall extends SqlExecution {
|
||||
DatabaseRunCall() {
|
||||
exists (string run | run = "run" or run = "runPartitionedUpdate" or run = "runStream" |
|
||||
this = database().getAMethodCall(run)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `Transaction.run` or `Database.runStream`.
|
||||
*/
|
||||
class TransactionRunCall extends SqlExecution {
|
||||
TransactionRunCall() {
|
||||
exists (string run | run = "run" or run = "runStream" or run = "runUpdate" |
|
||||
this = transaction().getAMethodCall(run)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `v1.SpannerClient.executeSql` or `v1.SpannerClient.executeStreamingSql`.
|
||||
*/
|
||||
class ExecuteSqlCall extends SqlExecution {
|
||||
ExecuteSqlCall() {
|
||||
exists (string exec | exec = "executeSql" or exec = "executeStreamingSql" |
|
||||
this = v1SpannerClient().getAMethodCall(exec)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
// `executeSql` and `executeStreamingSql` do not accept query strings directly
|
||||
result = getOptionArgument(0, "sql")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is interpreted as a SQL string.
|
||||
*/
|
||||
class QueryString extends SQL::SqlString {
|
||||
QueryString() {
|
||||
this = any(SqlExecution se).getAQueryArgument().asExpr()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,4 +14,24 @@
|
||||
| postgres3.js:15:16:15:40 | 'SELECT ... s name' |
|
||||
| sequelize2.js:10:17:10:118 | 'SELECT ... Y name' |
|
||||
| sequelize.js:8:17:8:118 | 'SELECT ... Y name' |
|
||||
| spanner2.js:5:26:5:35 | "SQL code" |
|
||||
| spanner2.js:7:35:7:44 | "SQL code" |
|
||||
| spanner.js:6:8:6:17 | "SQL code" |
|
||||
| spanner.js:7:8:7:26 | { sql: "SQL code" } |
|
||||
| spanner.js:7:15:7:24 | "SQL code" |
|
||||
| spanner.js:8:25:8:34 | "SQL code" |
|
||||
| spanner.js:9:25:9:43 | { sql: "SQL code" } |
|
||||
| spanner.js:9:32:9:41 | "SQL code" |
|
||||
| spanner.js:10:14:10:23 | "SQL code" |
|
||||
| spanner.js:11:14:11:31 | { sql: "SQL code"} |
|
||||
| spanner.js:11:21:11:30 | "SQL code" |
|
||||
| spanner.js:14:10:14:19 | "SQL code" |
|
||||
| spanner.js:15:10:15:28 | { sql: "SQL code" } |
|
||||
| spanner.js:15:17:15:26 | "SQL code" |
|
||||
| spanner.js:16:16:16:25 | "SQL code" |
|
||||
| spanner.js:17:16:17:34 | { sql: "SQL code" } |
|
||||
| spanner.js:17:23:17:32 | "SQL code" |
|
||||
| spanner.js:18:16:18:25 | "SQL code" |
|
||||
| spanner.js:19:16:19:34 | { sql: "SQL code" } |
|
||||
| spanner.js:19:23:19:32 | "SQL code" |
|
||||
| sqlite.js:7:8:7:45 | "UPDATE ... id = ?" |
|
||||
|
||||
20
javascript/ql/test/library-tests/frameworks/SQL/spanner.js
Normal file
20
javascript/ql/test/library-tests/frameworks/SQL/spanner.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const { Spanner } = require("@google-cloud/spanner");
|
||||
const spanner = new Spanner();
|
||||
const instance = spanner.instance('inst');
|
||||
const db = instance.database('db');
|
||||
|
||||
db.run("SQL code", (err, rows) => {});
|
||||
db.run({ sql: "SQL code" }, (err, rows) => {});
|
||||
db.runPartitionedUpdate("SQL code", (err, rows) => {});
|
||||
db.runPartitionedUpdate({ sql: "SQL code" }, (err, rows) => {});
|
||||
db.runStream("SQL code");
|
||||
db.runStream({ sql: "SQL code"});
|
||||
|
||||
db.runTransaction((err, tx) => {
|
||||
tx.run("SQL code");
|
||||
tx.run({ sql: "SQL code" });
|
||||
tx.runStream("SQL code");
|
||||
tx.runStream({ sql: "SQL code" });
|
||||
tx.runUpdate("SQL code");
|
||||
tx.runUpdate({ sql: "SQL code" });
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
const spanner = require("@google-cloud/spanner");
|
||||
const client = new spanner.v1.SpannerClient({});
|
||||
|
||||
client.executeSql("not SQL code", (err, rows) => {});
|
||||
client.executeSql({ sql: "SQL code" }, (err, rows) => {});
|
||||
client.executeStreamingSql("not SQL code", (err, rows) => {});
|
||||
client.executeStreamingSql({ sql: "SQL code" }, (err, rows) => {});
|
||||
Reference in New Issue
Block a user