mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Rust: first running tests
This commit is contained in:
6
rust/.generated.list
generated
6
rust/.generated.list
generated
@@ -3,8 +3,6 @@ ql/lib/codeql/rust/elements/DbFileConstructor.qll ea93dc49b23b1c6d800ab9d0b9cacf
|
||||
ql/lib/codeql/rust/elements/DbLocation.qll 1f694594e8e4ab65a8781cd443ad4f864447ca88e2cb65504aee5a779393c84d 003ec72275406eb8f5ddd6ccc2b258fb7c906d4bb2c0ef1ba235f291624321ca
|
||||
ql/lib/codeql/rust/elements/DbLocationConstructor.qll 8848abace985818a5d3a6eddfc4cb200795970146d282b037b4f22ae6230b894 44dba880e17bb1072fa12451ccaae4830fd04dcc61f7403d35510309fde6906e
|
||||
ql/lib/codeql/rust/elements/Declaration.qll d4ec5c83728f1837243caf2f27d06fd05ecdd2ca440112accff99bfd37b45e5f c1cd9b297be8b69207e75d24b29949b9f71c78406ee0ffd38d0b0810288d6140
|
||||
ql/lib/codeql/rust/elements/Element.qll 2bffdeb8863a9853d019e56afa268b3d39fb3687785ad636b159656c199997ca 18020582c7d1b89f4073b6deaf793c3072fdc52503a6cc53172c96282f141de4
|
||||
ql/lib/codeql/rust/elements/File.qll 75144234638417347107b75db80c561379e6372859ebc463276aef716e0ed42b 55bb468873acf24e6828faf7be3ff8963c9a4eb344bfedd95328a51b6f00a226
|
||||
ql/lib/codeql/rust/elements/Function.qll 220eb1d0e6b49e83b7674a9f505d3f529cf7f4d022ddca44fa6367e0d75daa0f d156cff59ecdcffc0d62041b801025b1aaedbc92d44efd107f93f6fd06c34a6d
|
||||
ql/lib/codeql/rust/elements/FunctionConstructor.qll a9269b37182c0bf432f9b2b015691da5dbd64819b9bd25445af229d873014a91 69107a7503af14a51e091e6918094a4e9fc316a72de2e1514f001872ce0f2c0c
|
||||
ql/lib/codeql/rust/elements/Locatable.qll dfc0235cf5aff0ec91d85375ac03998b0e6a69f3722b099330ab0a2161af988a bb1055f59ef7e95e89748765c79f1b5832aa18226f227e689a6801adfc6247ad
|
||||
@@ -30,6 +28,6 @@ ql/lib/codeql/rust/generated/Synth.qll d278de9c2d06cb7549cd8f2e10ed186827a2ceab6
|
||||
ql/lib/codeql/rust/generated/SynthConstructors.qll 35b36df0c4fff05bcbd4ed10b1e6fa2e58fe8d8c818e7805111044825788fc01 35b36df0c4fff05bcbd4ed10b1e6fa2e58fe8d8c818e7805111044825788fc01
|
||||
ql/lib/codeql/rust/generated/UnknownFile.qll ec9d1a3f15ecbf1743d4e39cb3b2f217aa9b54951c93302c2c4c238c3f0ce595 ec9d1a3f15ecbf1743d4e39cb3b2f217aa9b54951c93302c2c4c238c3f0ce595
|
||||
ql/lib/codeql/rust/generated/UnknownLocation.qll a19e2838c52d702d268ae530f3dbd6fcd8bb28a237a52636a960f225454103cf a19e2838c52d702d268ae530f3dbd6fcd8bb28a237a52636a960f225454103cf
|
||||
ql/test/extractor-tests/generated/File/MISSING_SOURCE.txt cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e
|
||||
ql/test/extractor-tests/generated/Function/MISSING_SOURCE.txt cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e
|
||||
ql/test/extractor-tests/generated/File/File.ql dec43be882fad904fab0c6447ca93633d801cb08ff8bec309befde7d2b9e5dda 74e1f1d698558c35fa03935cc34f4c8145d376b56d7657b18aeb338f5ca752cf
|
||||
ql/test/extractor-tests/generated/Function/Function.ql ae5d44a85047d50d8fbd3b62290c6935f061f07076b0070998173957e54eb43f 3e7fb6fb82463b96577394213915d8deae5332acdec2fcc07aa3eb8560420edd
|
||||
ql/test/extractor-tests/generated/Module/MISSING_SOURCE.txt cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e cc7c395e7c651d62596826b1a0bedf10f35d01b8afeef47600b4ddaf804f406e
|
||||
|
||||
6
rust/.gitattributes
generated
vendored
6
rust/.gitattributes
generated
vendored
@@ -5,8 +5,6 @@
|
||||
/ql/lib/codeql/rust/elements/DbLocation.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/DbLocationConstructor.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/Declaration.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/Element.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/File.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/Function.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/FunctionConstructor.qll linguist-generated
|
||||
/ql/lib/codeql/rust/elements/Locatable.qll linguist-generated
|
||||
@@ -32,6 +30,6 @@
|
||||
/ql/lib/codeql/rust/generated/SynthConstructors.qll linguist-generated
|
||||
/ql/lib/codeql/rust/generated/UnknownFile.qll linguist-generated
|
||||
/ql/lib/codeql/rust/generated/UnknownLocation.qll linguist-generated
|
||||
/ql/test/extractor-tests/generated/File/MISSING_SOURCE.txt linguist-generated
|
||||
/ql/test/extractor-tests/generated/Function/MISSING_SOURCE.txt linguist-generated
|
||||
/ql/test/extractor-tests/generated/File/File.ql linguist-generated
|
||||
/ql/test/extractor-tests/generated/Function/Function.ql linguist-generated
|
||||
/ql/test/extractor-tests/generated/Module/MISSING_SOURCE.txt linguist-generated
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
This package aliases [`misc/codegen`](../misc/codegen) providing the Rust-specific options
|
||||
in [`rust/codegen.conf`](../codegen.conf).
|
||||
|
||||
Running `bazel run //rust/codegen` will generate all checked in
|
||||
files ([dbscheme](../ql/lib/swift.dbscheme), [QL generated code](../ql/lib/codeql/swift/generated),
|
||||
[generated QL stubs](../ql/lib/codeql/swift/elements), [generated QL tests](../ql/test/extractor-tests/generated)).
|
||||
@@ -2,6 +2,7 @@ name: "rust"
|
||||
display_name: "Rust"
|
||||
version: 0.1.0
|
||||
column_kind: "utf8"
|
||||
legacy_qltest_extraction: true
|
||||
build_modes:
|
||||
- none
|
||||
github_api_languages:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use std::path::PathBuf;
|
||||
use anyhow::Context;
|
||||
use serde::{Deserialize, Serialize, Serializer, Deserializer};
|
||||
use serde_with;
|
||||
use figment::{Figment, providers::{Env, Serialized}};
|
||||
@@ -48,7 +49,9 @@ struct CliArgs {
|
||||
#[arg(long)]
|
||||
compression: Option<Compression>,
|
||||
#[arg(short, long, action = ArgAction::Count)]
|
||||
pub verbose: u8,
|
||||
verbose: u8,
|
||||
#[arg(long)]
|
||||
inputs_file: Option<PathBuf>,
|
||||
|
||||
inputs: Vec<PathBuf>,
|
||||
}
|
||||
@@ -58,10 +61,15 @@ fn is_default<T: Default + PartialEq>(t: &T) -> bool {
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn extract() -> figment::Result<Config> {
|
||||
Figment::new()
|
||||
pub fn extract() -> anyhow::Result<Config> {
|
||||
let mut cli_args = CliArgs::parse();
|
||||
if let Some(inputs_file) = cli_args.inputs_file.take() {
|
||||
let inputs_list = std::fs::read_to_string(inputs_file).context("reading file list")?;
|
||||
cli_args.inputs.extend(inputs_list.split("\n").map(PathBuf::from));
|
||||
}
|
||||
Ok(Figment::new()
|
||||
.merge(Env::prefixed("CODEQL_EXTRACTOR_RUST_"))
|
||||
.merge(Serialized::defaults(CliArgs::parse()))
|
||||
.extract()
|
||||
.merge(Serialized::defaults(cli_args))
|
||||
.extract().context("loading configuration")?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,7 @@ fn main() -> anyhow::Result<()> {
|
||||
prefill_caches: false,
|
||||
};
|
||||
for input in cfg.inputs {
|
||||
load_workspace_at(&input, &config, &load_config, &no_progress)?;
|
||||
let (db, vfs, _macro_server) = load_workspace_at(&input, &config, &load_config, &no_progress)?;
|
||||
let (db, vfs, _macro_server) = load_workspace_at(&input, &config, &load_config, &no_progress).context("loading inputs")?;
|
||||
let crates = <dyn DefDatabase>::crate_graph(&db);
|
||||
for crate_id in crates.iter().take(1) {
|
||||
let krate = Crate::from(crate_id);
|
||||
@@ -49,7 +48,7 @@ fn main() -> anyhow::Result<()> {
|
||||
&krate,
|
||||
&vfs,
|
||||
&archiver,
|
||||
).emit_crate()?;
|
||||
).emit_crate().context("writing trap file")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// generated by codegen, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `Element`.
|
||||
*/
|
||||
|
||||
private import codeql.rust.generated.Element
|
||||
|
||||
class Element extends Generated::Element { }
|
||||
class Element extends Generated::Element {
|
||||
predicate isUnknown() { none() } // compatibility with test generation, to be fixed
|
||||
}
|
||||
|
||||
@@ -1,8 +1,111 @@
|
||||
// generated by codegen, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `File`.
|
||||
*/
|
||||
|
||||
private import codeql.rust.generated.File
|
||||
private import codeql.rust.elements.Location
|
||||
private import codeql.rust.elements.UnknownLocation
|
||||
|
||||
class File extends Generated::File { }
|
||||
class File extends Generated::File {
|
||||
/** toString */
|
||||
override string toString() { result = this.getAbsolutePath() }
|
||||
|
||||
/** Gets the absolute path of this file. */
|
||||
string getAbsolutePath() { result = this.getName() }
|
||||
|
||||
/** Gets the full name of this file. */
|
||||
string getFullName() { result = this.getAbsolutePath() }
|
||||
|
||||
/** Gets the URL of this file. */
|
||||
string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" }
|
||||
|
||||
/**
|
||||
* Holds if either,
|
||||
* - `part` is the base name of this container and `i = 1`, or
|
||||
* - `part` is the stem of this container and `i = 2`, or
|
||||
* - `part` is the extension of this container and `i = 3`.
|
||||
*/
|
||||
cached
|
||||
private predicate splitAbsolutePath(string part, int i) {
|
||||
part = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", i)
|
||||
}
|
||||
|
||||
/** Gets the base name of this file. */
|
||||
string getBaseName() { this.splitAbsolutePath(result, 1) }
|
||||
|
||||
/**
|
||||
* Gets the extension of this container, that is, the suffix of its base name
|
||||
* after the last dot character, if any.
|
||||
*
|
||||
* In particular,
|
||||
*
|
||||
* - if the name does not include a dot, there is no extension, so this
|
||||
* predicate has no result;
|
||||
* - if the name ends in a dot, the extension is the empty string;
|
||||
* - if the name contains multiple dots, the extension follows the last dot.
|
||||
*
|
||||
* Here are some examples of absolute paths and the corresponding extensions
|
||||
* (surrounded with quotes to avoid ambiguity):
|
||||
*
|
||||
* <table border="1">
|
||||
* <tr><th>Absolute path</th><th>Extension</th></tr>
|
||||
* <tr><td>"/tmp/tst.txt"</td><td>"txt"</td></tr>
|
||||
* <tr><td>"/tmp/.classpath"</td><td>"classpath"</td></tr>
|
||||
* <tr><td>"/bin/bash"</td><td>not defined</td></tr>
|
||||
* <tr><td>"/tmp/tst2."</td><td>""</td></tr>
|
||||
* <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
string getExtension() { this.splitAbsolutePath(result, 3) }
|
||||
|
||||
/**
|
||||
* Gets the stem of this container, that is, the prefix of its base name up to
|
||||
* (but not including) the last dot character if there is one, or the entire
|
||||
* base name if there is not.
|
||||
*
|
||||
* Here are some examples of absolute paths and the corresponding stems
|
||||
* (surrounded with quotes to avoid ambiguity):
|
||||
*
|
||||
* <table border="1">
|
||||
* <tr><th>Absolute path</th><th>Stem</th></tr>
|
||||
* <tr><td>"/tmp/tst.txt"</td><td>"tst"</td></tr>
|
||||
* <tr><td>"/tmp/.classpath"</td><td>""</td></tr>
|
||||
* <tr><td>"/bin/bash"</td><td>"bash"</td></tr>
|
||||
* <tr><td>"/tmp/tst2."</td><td>"tst2"</td></tr>
|
||||
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
string getStem() { this.splitAbsolutePath(result, 2) }
|
||||
|
||||
/**
|
||||
* Gets the number of lines containing code in this file. This value
|
||||
* is approximate.
|
||||
*/
|
||||
int getNumberOfLinesOfCode() {
|
||||
result =
|
||||
count(int line |
|
||||
exists(Location loc |
|
||||
not loc instanceof UnknownLocation and loc.getFile() = this and loc.getStartLine() = line
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the relative path of this file from the root folder of the
|
||||
* analyzed source location. The relative path of the root folder itself
|
||||
* would be the empty string.
|
||||
*
|
||||
* This has no result if the file is outside the source root, that is,
|
||||
* if the root folder is not a reflexive, transitive parent of this file.
|
||||
*/
|
||||
string getRelativePath() {
|
||||
exists(string absPath, string pref |
|
||||
absPath = this.getAbsolutePath() and sourceLocationPrefix(pref)
|
||||
|
|
||||
absPath = pref and result = ""
|
||||
or
|
||||
absPath = pref.regexpReplaceAll("/$", "") + "/" + result and
|
||||
not result.matches("/%")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
5
rust/ql/lib/codeql/rust/elements/Function.qll
generated
5
rust/ql/lib/codeql/rust/elements/Function.qll
generated
@@ -1,8 +1,9 @@
|
||||
// generated by codegen, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `Function`.
|
||||
*/
|
||||
|
||||
private import codeql.rust.generated.Function
|
||||
|
||||
class Function extends Generated::Function { }
|
||||
class Function extends Generated::Function {
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
18
rust/ql/lib/codeql/rust/elements/Locatable.qll
generated
18
rust/ql/lib/codeql/rust/elements/Locatable.qll
generated
@@ -1,8 +1,22 @@
|
||||
// generated by codegen, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `Locatable`.
|
||||
*/
|
||||
|
||||
private import codeql.rust.generated.Locatable
|
||||
private import codeql.rust.elements.File
|
||||
private import codeql.rust.elements.UnknownLocation
|
||||
|
||||
class Locatable extends Generated::Locatable { }
|
||||
class Locatable extends Generated::Locatable {
|
||||
pragma[nomagic]
|
||||
override Location getLocation() {
|
||||
result = Generated::Locatable.super.getLocation()
|
||||
or
|
||||
not exists(Generated::Locatable.super.getLocation()) and
|
||||
result instanceof UnknownLocation
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the primary file where this element occurs.
|
||||
*/
|
||||
File getFile() { result = this.getLocation().getFile() }
|
||||
}
|
||||
|
||||
25
rust/ql/lib/codeql/rust/elements/Location.qll
generated
25
rust/ql/lib/codeql/rust/elements/Location.qll
generated
@@ -1,8 +1,29 @@
|
||||
// generated by codegen, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `Location`.
|
||||
*/
|
||||
|
||||
private import codeql.rust.generated.Location
|
||||
|
||||
class Location extends Generated::Location { }
|
||||
class Location extends Generated::Location {
|
||||
/**
|
||||
* Holds if this location is described by `path`, `startLine`, `startColumn`, `endLine` and `endColumn`.
|
||||
*/
|
||||
predicate hasLocationInfo(string path, int startLine, int startColumn, int endLine, int endColumn) {
|
||||
path = this.getFile().getFullName() and
|
||||
startLine = this.getStartLine() and
|
||||
startColumn = this.getStartColumn() and
|
||||
endLine = this.getEndLine() and
|
||||
endColumn = this.getEndColumn()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a textual representation of this location.
|
||||
*/
|
||||
override string toString() {
|
||||
exists(string filePath, int startLine, int startColumn, int endLine, int endColumn |
|
||||
this.hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn)
|
||||
|
|
||||
toUrl(filePath, startLine, startColumn, endLine, endColumn, result)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
5
rust/ql/lib/codeql/rust/elements/UnknownFile.qll
generated
5
rust/ql/lib/codeql/rust/elements/UnknownFile.qll
generated
@@ -1,8 +1,9 @@
|
||||
// generated by codegen, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `UnknownFile`.
|
||||
*/
|
||||
|
||||
private import codeql.rust.generated.UnknownFile
|
||||
|
||||
class UnknownFile extends Generated::UnknownFile { }
|
||||
class UnknownFile extends Generated::UnknownFile {
|
||||
override string getName() { result = "" }
|
||||
}
|
||||
|
||||
17
rust/ql/lib/codeql/rust/elements/UnknownLocation.qll
generated
17
rust/ql/lib/codeql/rust/elements/UnknownLocation.qll
generated
@@ -1,8 +1,21 @@
|
||||
// generated by codegen, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `UnknownLocation`.
|
||||
*/
|
||||
|
||||
private import codeql.rust.generated.UnknownLocation
|
||||
private import codeql.rust.elements.File
|
||||
private import codeql.rust.elements.UnknownFile
|
||||
|
||||
class UnknownLocation extends Generated::UnknownLocation { }
|
||||
class UnknownLocation extends Generated::UnknownLocation {
|
||||
override File getFile() { result instanceof UnknownFile }
|
||||
|
||||
override int getStartLine() { result = 0 }
|
||||
|
||||
override int getStartColumn() { result = 0 }
|
||||
|
||||
override int getEndLine() { result = 0 }
|
||||
|
||||
override int getEndColumn() { result = 0 }
|
||||
|
||||
override string toString() { result = "UnknownLocation" }
|
||||
}
|
||||
|
||||
49
rust/ql/lib/codeql/rust/printast/PrintAst.qll
Normal file
49
rust/ql/lib/codeql/rust/printast/PrintAst.qll
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Provides queries to pretty-print a Swift AST as a graph.
|
||||
*/
|
||||
|
||||
import PrintAstNode
|
||||
|
||||
cached
|
||||
private int getOrder(PrintAstNode node) {
|
||||
node =
|
||||
rank[result](PrintAstNode n, Location loc |
|
||||
loc = n.getLocation()
|
||||
|
|
||||
n
|
||||
order by
|
||||
loc.getFile().getName(), loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(),
|
||||
loc.getEndColumn()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
|
||||
query predicate nodes(PrintAstNode node, string key, string value) {
|
||||
node.shouldBePrinted() and
|
||||
(
|
||||
key = "semmle.label" and value = node.toString()
|
||||
or
|
||||
key = "semmle.order" and value = getOrder(node).toString()
|
||||
or
|
||||
value = node.getProperty(key)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `target` is a child of `source` in the AST, and property `key` of the edge has the
|
||||
* given `value`.
|
||||
*/
|
||||
query predicate edges(PrintAstNode source, PrintAstNode target, string key, string value) {
|
||||
source.shouldBePrinted() and
|
||||
target.shouldBePrinted() and
|
||||
exists(int index, string accessor | source.hasChild(target, index, accessor) |
|
||||
key = "semmle.label" and value = accessor
|
||||
or
|
||||
key = "semmle.order" and value = index.toString()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if property `key` of the graph has the given `value`. */
|
||||
query predicate graphProperties(string key, string value) {
|
||||
key = "semmle.graphKind" and value = "tree"
|
||||
}
|
||||
129
rust/ql/lib/codeql/rust/printast/PrintAstNode.qll
Normal file
129
rust/ql/lib/codeql/rust/printast/PrintAstNode.qll
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* Provides classes used to pretty-print a Swift AST as a graph.
|
||||
* This is factored out of `PrintAst.qll` for testing purposes.
|
||||
*/
|
||||
|
||||
import rust
|
||||
import codeql.rust.generated.ParentChild
|
||||
|
||||
private newtype TPrintAstConfiguration = TMakePrintAstConfiguration()
|
||||
|
||||
/**
|
||||
* The hook to customize the files and functions printed by this module.
|
||||
*/
|
||||
class PrintAstConfiguration extends TPrintAstConfiguration {
|
||||
/**
|
||||
* Gets the string representation of this singleton
|
||||
*/
|
||||
string toString() { result = "PrintAstConfiguration" }
|
||||
|
||||
/**
|
||||
* Holds if the AST for `e` should be printed. By default, holds for all.
|
||||
*/
|
||||
predicate shouldPrint(Locatable e) { not e instanceof Diagnostics and not e instanceof MacroRole }
|
||||
}
|
||||
|
||||
private predicate shouldPrint(Locatable e) { any(PrintAstConfiguration config).shouldPrint(e) }
|
||||
|
||||
/**
|
||||
* An AST node that should be printed.
|
||||
*/
|
||||
private newtype TPrintAstNode = TPrintLocatable(Locatable ast)
|
||||
|
||||
/**
|
||||
* A node in the output tree.
|
||||
*/
|
||||
class PrintAstNode extends TPrintAstNode {
|
||||
/**
|
||||
* Gets a textual representation of this node.
|
||||
*/
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
* Gets the child node at index `index`. Child indices must be unique,
|
||||
* but need not be contiguous.
|
||||
*/
|
||||
abstract predicate hasChild(PrintAstNode child, int index, string label);
|
||||
|
||||
/**
|
||||
* Holds if this node should be printed in the output.
|
||||
*/
|
||||
abstract predicate shouldBePrinted();
|
||||
|
||||
/**
|
||||
* Gets the location of this node in the source code.
|
||||
*/
|
||||
abstract Location getLocation();
|
||||
|
||||
/**
|
||||
* Gets the value of an additional property of this node, where the name of
|
||||
* the property is `key`.
|
||||
*/
|
||||
string getProperty(string key) { none() }
|
||||
|
||||
/**
|
||||
* Gets the underlying AST node, if any.
|
||||
*/
|
||||
abstract Locatable getAstNode();
|
||||
}
|
||||
|
||||
private string prettyPrint(Locatable e) {
|
||||
result = "[" + concat(e.getPrimaryQlClasses(), ", ") + "] " + e
|
||||
}
|
||||
|
||||
private class Unresolved extends Locatable {
|
||||
Unresolved() { this != this.resolve() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A graph node representing a real Locatable node.
|
||||
*/
|
||||
class PrintLocatable extends PrintAstNode, TPrintLocatable {
|
||||
Locatable ast;
|
||||
|
||||
PrintLocatable() { this = TPrintLocatable(ast) }
|
||||
|
||||
override string toString() { result = prettyPrint(ast) }
|
||||
|
||||
final override predicate shouldBePrinted() { shouldPrint(ast) }
|
||||
|
||||
override predicate hasChild(PrintAstNode child, int index, string label) {
|
||||
exists(Locatable c, int i, string accessor |
|
||||
c = getChildAndAccessor(ast, i, accessor) and
|
||||
(
|
||||
// use even indexes for normal children, leaving odd slots for conversions if any
|
||||
child = TPrintLocatable(c) and index = 2 * i and label = accessor
|
||||
or
|
||||
child = TPrintLocatable(c.getFullyUnresolved().(Unresolved)) and
|
||||
index = 2 * i + 1 and
|
||||
(
|
||||
if c instanceof Expr
|
||||
then label = accessor + ".getFullyConverted()"
|
||||
else label = accessor + ".getFullyUnresolved()"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override Locatable getAstNode() { result = ast }
|
||||
|
||||
final override Location getLocation() { result = ast.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A specialization of graph node for "unresolved" children, that is nodes in
|
||||
* the parallel conversion AST.
|
||||
*/
|
||||
class PrintUnresolved extends PrintLocatable {
|
||||
override Unresolved ast;
|
||||
|
||||
override predicate hasChild(PrintAstNode child, int index, string label) {
|
||||
// only print immediate unresolved children from the "parallel" AST
|
||||
child = TPrintLocatable(getImmediateChildAndAccessor(ast, index, label).(Unresolved))
|
||||
}
|
||||
}
|
||||
|
||||
private predicate hasPropertyWrapperElement(VarDecl d, Locatable a) {
|
||||
a = [d.getPropertyWrapperBackingVar(), d.getPropertyWrapperProjectionVar()] or
|
||||
a = [d.getPropertyWrapperBackingVarBinding(), d.getPropertyWrapperProjectionVarBinding()]
|
||||
}
|
||||
4
rust/ql/lib/qlpack.lock.yml
Normal file
4
rust/ql/lib/qlpack.lock.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
dependencies: {}
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
15
rust/ql/lib/qlpack.yml
Normal file
15
rust/ql/lib/qlpack.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
name: codeql/rust-all
|
||||
version: 0.1.0-dev
|
||||
groups: rust
|
||||
extractor: rust
|
||||
dbscheme: rust.dbscheme
|
||||
library: true
|
||||
dependencies:
|
||||
codeql/controlflow: ${workspace}
|
||||
codeql/dataflow: ${workspace}
|
||||
codeql/regex: ${workspace}
|
||||
codeql/mad: ${workspace}
|
||||
codeql/ssa: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
warnOnImplicitThis: true
|
||||
3
rust/ql/lib/rust.qll
Normal file
3
rust/ql/lib/rust.qll
Normal file
@@ -0,0 +1,3 @@
|
||||
/** Top-level import for the Rust language pack */
|
||||
|
||||
import codeql.rust.elements
|
||||
4
rust/ql/src/qlpack.lock.yml
Normal file
4
rust/ql/src/qlpack.lock.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
dependencies: {}
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
12
rust/ql/src/qlpack.yml
Normal file
12
rust/ql/src/qlpack.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
name: codeql/rust-queries
|
||||
version: 0.1.0-dev
|
||||
groups:
|
||||
- rust
|
||||
- queries
|
||||
suites: codeql-suites
|
||||
extractor: rust
|
||||
dependencies:
|
||||
codeql/rust-all: ${workspace}
|
||||
codeql/suite-helpers: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
warnOnImplicitThis: true
|
||||
33
rust/ql/src/queries/ide-contextual-queries/printAst.ql
Normal file
33
rust/ql/src/queries/ide-contextual-queries/printAst.ql
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @name Print AST
|
||||
* @description Outputs a representation of a file's Abstract Syntax Tree. This
|
||||
* query is used by the VS Code extension.
|
||||
* @id rust/print-ast
|
||||
* @kind graph
|
||||
* @tags ide-contextual-queries/print-ast
|
||||
*/
|
||||
|
||||
import rust
|
||||
import codeql.rust.printast.PrintAst
|
||||
import codeql.IDEContextual
|
||||
import codeql.rust.generated.ParentChild
|
||||
|
||||
/**
|
||||
* Gets the source file to generate an AST from.
|
||||
*/
|
||||
external string selectedSourceFile();
|
||||
|
||||
class PrintAstConfigurationOverride extends PrintAstConfiguration {
|
||||
/**
|
||||
* Holds if the location matches the selected file in the VS Code extension and
|
||||
* the element is `e`.
|
||||
*/
|
||||
override predicate shouldPrint(Locatable e) {
|
||||
super.shouldPrint(e) and
|
||||
(
|
||||
e.getFile() = getFileBySourceArchiveName(selectedSourceFile())
|
||||
or
|
||||
exists(Locatable parent | this.shouldPrint(parent) and parent = getImmediateParent(e))
|
||||
)
|
||||
}
|
||||
}
|
||||
3
rust/ql/test/.gitignore
vendored
Normal file
3
rust/ql/test/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Cargo.toml
|
||||
Cargo.lock
|
||||
target/
|
||||
13
rust/ql/test/TestUtils.qll
Normal file
13
rust/ql/test/TestUtils.qll
Normal file
@@ -0,0 +1,13 @@
|
||||
private import codeql.rust.elements
|
||||
|
||||
cached
|
||||
predicate toBeTested(Element e) {
|
||||
exists(File f |
|
||||
f.getName().matches("%rust/ql/test%") and
|
||||
(
|
||||
e = f
|
||||
or
|
||||
e.(Locatable).getLocation().getFile() = f
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
| test.rs:0:0:0:0 | test.rs | DbFile | getName: | test.rs |
|
||||
10
rust/ql/test/extractor-tests/generated/File/File.ql
generated
Normal file
10
rust/ql/test/extractor-tests/generated/File/File.ql
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
// generated by codegen
|
||||
import codeql.rust.elements
|
||||
import TestUtils
|
||||
|
||||
from File x, string getName
|
||||
where
|
||||
toBeTested(x) and
|
||||
not x.isUnknown() and
|
||||
getName = x.getName()
|
||||
select x, x.getPrimaryQlClasses(), "getName:", getName
|
||||
@@ -1,4 +0,0 @@
|
||||
// generated by codegen
|
||||
|
||||
After a source file is added in this directory and codegen is run again, test queries
|
||||
will appear and this file will be deleted
|
||||
1
rust/ql/test/extractor-tests/generated/File/test.rs
Normal file
1
rust/ql/test/extractor-tests/generated/File/test.rs
Normal file
@@ -0,0 +1 @@
|
||||
fn main() {}
|
||||
@@ -0,0 +1,3 @@
|
||||
| test.rs:0:0:0:11 | foo | getName: | foo |
|
||||
| test.rs:1:0:1:11 | bar | getName: | bar |
|
||||
| test.rs:2:0:2:11 | baz | getName: | baz |
|
||||
10
rust/ql/test/extractor-tests/generated/Function/Function.ql
generated
Normal file
10
rust/ql/test/extractor-tests/generated/Function/Function.ql
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
// generated by codegen
|
||||
import codeql.rust.elements
|
||||
import TestUtils
|
||||
|
||||
from Function x, string getName
|
||||
where
|
||||
toBeTested(x) and
|
||||
not x.isUnknown() and
|
||||
getName = x.getName()
|
||||
select x, "getName:", getName
|
||||
@@ -1,4 +0,0 @@
|
||||
// generated by codegen
|
||||
|
||||
After a source file is added in this directory and codegen is run again, test queries
|
||||
will appear and this file will be deleted
|
||||
3
rust/ql/test/extractor-tests/generated/Function/test.rs
Normal file
3
rust/ql/test/extractor-tests/generated/Function/test.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
fn foo() {}
|
||||
fn bar() {}
|
||||
fn baz() {}
|
||||
4
rust/ql/test/qlpack.lock.yml
Normal file
4
rust/ql/test/qlpack.lock.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
dependencies: {}
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
8
rust/ql/test/qlpack.yml
Normal file
8
rust/ql/test/qlpack.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
name: codeql/rust-tests
|
||||
groups: [rust, test]
|
||||
dependencies:
|
||||
codeql/rust-queries: ${workspace}
|
||||
codeql/rust-all: ${workspace}
|
||||
extractor: rust
|
||||
tests: .
|
||||
warnOnImplicitThis: true
|
||||
@@ -2,8 +2,6 @@ load("//misc/bazel:pkg.bzl", "codeql_pkg_files")
|
||||
|
||||
codeql_pkg_files(
|
||||
name = "tools",
|
||||
exes = [
|
||||
"index.sh",
|
||||
],
|
||||
exes = glob(["*.sh"]),
|
||||
visibility = ["//rust:__pkg__"],
|
||||
)
|
||||
|
||||
5
rust/tools/index-files.sh
Executable file
5
rust/tools/index-files.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
exec "$CODEQL_EXTRACTOR_RUST_ROOT/tools/$CODEQL_PLATFORM/extractor" --inputs-file="$1"
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
# TODO move this to rust code
|
||||
|
||||
inputs=($(find -name Cargo.toml))
|
||||
|
||||
if [ "${#inputs}" -eq 0 ]; then
|
||||
inputs=($(find -name rust-project.json))
|
||||
if [ "${#inputs}" -eq 0 ]; then
|
||||
inputs=($(find -name '*.rs'))
|
||||
if [ "${#inputs}" -eq 0 ]; then
|
||||
echo "no source files found" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "$CODEQL_EXTRACTOR_RUST_ROOT/tools/$CODEQL_PLATFORM/extractor" "${inputs[@]}"
|
||||
32
rust/tools/qltest.sh
Executable file
32
rust/tools/qltest.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir -p "$CODEQL_EXTRACTOR_RUST_TRAP_DIR"
|
||||
|
||||
export RUST_BACKTRACE=full
|
||||
|
||||
QLTEST_LOG="$CODEQL_EXTRACTOR_RUST_LOG_DIR"/qltest.log
|
||||
|
||||
EXTRACTOR="$CODEQL_EXTRACTOR_RUST_ROOT/tools/$CODEQL_PLATFORM/extractor"
|
||||
for src in *.rs; do
|
||||
echo -e "[package]\nname = \"test\"\n[lib]\npath=\"$src\"\n" > Cargo.toml
|
||||
env=()
|
||||
opts=("$src")
|
||||
opts+=($(sed -n '1 s=//codeql-extractor-options:==p' $src))
|
||||
expected_status=$(sed -n 's=//codeql-extractor-expected-status:[[:space:]]*==p' $src)
|
||||
expected_status=${expected_status:-0}
|
||||
env+=($(sed -n '1 s=//codeql-extractor-env:==p' $src))
|
||||
echo >> $QLTEST_LOG
|
||||
echo "env ${env[@]} $EXTRACTOR ${opts[@]}" >> "$QLTEST_LOG"
|
||||
env "${env[@]}" "$EXTRACTOR" "${opts[@]}" >> $QLTEST_LOG 2>&1
|
||||
actual_status=$?
|
||||
if [[ $actual_status != $expected_status ]]; then
|
||||
FAILED=1
|
||||
fi
|
||||
done
|
||||
|
||||
rm -rf Cargo.*
|
||||
|
||||
if [ -n "$FAILED" ]; then
|
||||
cat "$QLTEST_LOG" # Show compiler errors on extraction failure
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user