Rust: first running tests

This commit is contained in:
Paolo Tranquilli
2024-08-30 17:45:51 +02:00
parent 7e1290aa74
commit 885e89a927
37 changed files with 531 additions and 64 deletions

6
rust/.generated.list generated
View File

@@ -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
View File

@@ -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

View File

@@ -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)).

View File

@@ -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:

View File

@@ -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")?)
}
}

View File

@@ -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(())

View File

@@ -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
}

View File

@@ -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("/%")
)
}
}

View File

@@ -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() }
}

View File

@@ -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() }
}

View File

@@ -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)
)
}
}

View File

@@ -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 = "" }
}

View File

@@ -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" }
}

View 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"
}

View 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()]
}

View File

@@ -0,0 +1,4 @@
---
dependencies: {}
compiled: false
lockVersion: 1.0.0

15
rust/ql/lib/qlpack.yml Normal file
View 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
View File

@@ -0,0 +1,3 @@
/** Top-level import for the Rust language pack */
import codeql.rust.elements

View File

@@ -0,0 +1,4 @@
---
dependencies: {}
compiled: false
lockVersion: 1.0.0

12
rust/ql/src/qlpack.yml Normal file
View 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

View 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
View File

@@ -0,0 +1,3 @@
Cargo.toml
Cargo.lock
target/

View 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
)
)
}

View File

@@ -0,0 +1 @@
| test.rs:0:0:0:0 | test.rs | DbFile | getName: | test.rs |

View 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

View File

@@ -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

View File

@@ -0,0 +1 @@
fn main() {}

View File

@@ -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 |

View 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

View File

@@ -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

View File

@@ -0,0 +1,3 @@
fn foo() {}
fn bar() {}
fn baz() {}

View File

@@ -0,0 +1,4 @@
---
dependencies: {}
compiled: false
lockVersion: 1.0.0

8
rust/ql/test/qlpack.yml Normal file
View 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

View File

@@ -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
View File

@@ -0,0 +1,5 @@
#!/bin/sh
set -eu
exec "$CODEQL_EXTRACTOR_RUST_ROOT/tools/$CODEQL_PLATFORM/extractor" --inputs-file="$1"

View File

@@ -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
View 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