mirror of
https://github.com/github/codeql.git
synced 2025-12-16 08:43:11 +01:00
Merge branch 'main' into post-release-prep/codeql-cli-2.23.6
This commit is contained in:
@@ -171,12 +171,14 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
* Gets the nth parameter of this function. There is no result for the
|
||||
* implicit `this` parameter, and there is no `...` varargs pseudo-parameter.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
Parameter getParameter(int n) { params(unresolveElement(result), underlyingElement(this), n, _) }
|
||||
|
||||
/**
|
||||
* Gets a parameter of this function. There is no result for the implicit
|
||||
* `this` parameter, and there is no `...` varargs pseudo-parameter.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
Parameter getAParameter() { params(unresolveElement(result), underlyingElement(this), _, _) }
|
||||
|
||||
/**
|
||||
|
||||
@@ -360,5 +360,22 @@ namespace Semmle.Extraction.CSharp
|
||||
return versionString.InformationalVersion;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly HashSet<string> errorsToIgnore = new HashSet<string>
|
||||
{
|
||||
"CS7027", // Code signing failure
|
||||
"CS1589", // XML referencing not supported
|
||||
"CS1569" // Error writing XML documentation
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the diagnostics from the compilation, filtering out those that should be ignored.
|
||||
/// </summary>
|
||||
protected List<Diagnostic> GetFilteredDiagnostics() =>
|
||||
compilation is not null
|
||||
? compilation.GetDiagnostics()
|
||||
.Where(e => e.Severity >= DiagnosticSeverity.Error && !errorsToIgnore.Contains(e.Id))
|
||||
.ToList()
|
||||
: [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,14 @@ namespace Semmle.Extraction.CSharp
|
||||
{
|
||||
}
|
||||
|
||||
private void LogDiagnostics()
|
||||
{
|
||||
foreach (var error in GetFilteredDiagnostics())
|
||||
{
|
||||
Logger.LogDebug($" Compilation error: {error}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize(string outputPath, IEnumerable<(string, string)> compilationInfos, CSharpCompilation compilationIn, CommonOptions options)
|
||||
{
|
||||
compilation = compilationIn;
|
||||
@@ -20,6 +28,7 @@ namespace Semmle.Extraction.CSharp
|
||||
this.options = options;
|
||||
LogExtractorInfo();
|
||||
SetReferencePaths();
|
||||
LogDiagnostics();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,11 +136,7 @@ namespace Semmle.Extraction.CSharp
|
||||
|
||||
private int LogDiagnostics()
|
||||
{
|
||||
var filteredDiagnostics = compilation!
|
||||
.GetDiagnostics()
|
||||
.Where(e => e.Severity >= DiagnosticSeverity.Error && !errorsToIgnore.Contains(e.Id))
|
||||
.ToList();
|
||||
|
||||
var filteredDiagnostics = GetFilteredDiagnostics();
|
||||
foreach (var error in filteredDiagnostics)
|
||||
{
|
||||
Logger.LogError($" Compilation error: {error}");
|
||||
@@ -148,7 +144,7 @@ namespace Semmle.Extraction.CSharp
|
||||
|
||||
if (filteredDiagnostics.Count != 0)
|
||||
{
|
||||
foreach (var reference in compilation.References)
|
||||
foreach (var reference in compilation!.References)
|
||||
{
|
||||
Logger.LogInfo($" Resolved reference {reference.Display}");
|
||||
}
|
||||
@@ -156,12 +152,5 @@ namespace Semmle.Extraction.CSharp
|
||||
|
||||
return filteredDiagnostics.Count;
|
||||
}
|
||||
|
||||
private static readonly HashSet<string> errorsToIgnore = new HashSet<string>
|
||||
{
|
||||
"CS7027", // Code signing failure
|
||||
"CS1589", // XML referencing not supported
|
||||
"CS1569" // Error writing XML documentation
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Compilation errors are now included in the debug log when using build-mode none.
|
||||
@@ -1,2 +1,3 @@
|
||||
- `CodeQL queries for Rust <https://github.com/github/codeql/tree/main/rust/ql/src>`__
|
||||
- `Example queries for Rust <https://github.com/github/codeql/tree/main/rust/ql/examples>`__
|
||||
- `CodeQL library reference for Rust <https://codeql.github.com/codeql-standard-libraries/rust/>`__
|
||||
|
||||
4
rust/ql/examples/qlpack.lock.yml
Normal file
4
rust/ql/examples/qlpack.lock.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
dependencies: {}
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
7
rust/ql/examples/qlpack.yml
Normal file
7
rust/ql/examples/qlpack.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
name: codeql/rust-examples
|
||||
groups:
|
||||
- rust
|
||||
- examples
|
||||
dependencies:
|
||||
codeql/rust-all: ${workspace}
|
||||
warnOnImplicitThis: true
|
||||
18
rust/ql/examples/snippets/empty_if.ql
Normal file
18
rust/ql/examples/snippets/empty_if.ql
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @name Empty 'if' expression
|
||||
* @description Finds 'if' expressions where the "then" branch is empty and no
|
||||
* "else" branch exists.
|
||||
* @id rust/examples/empty-if
|
||||
* @tags example
|
||||
*/
|
||||
|
||||
import rust
|
||||
|
||||
// find 'if' expressions...
|
||||
from IfExpr ifExpr
|
||||
where
|
||||
// where the 'then' branch is empty
|
||||
ifExpr.getThen().getStmtList().getNumberOfStmtOrExpr() = 0 and
|
||||
// and no 'else' branch exists
|
||||
not ifExpr.hasElse()
|
||||
select ifExpr, "This 'if' expression is redundant."
|
||||
48
rust/ql/examples/snippets/simple_constant_password.ql
Normal file
48
rust/ql/examples/snippets/simple_constant_password.ql
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @name Constant password
|
||||
* @description Finds places where a string literal is used in a function call
|
||||
* argument that looks like a password.
|
||||
* @id rust/examples/simple-constant-password
|
||||
* @tags example
|
||||
*/
|
||||
|
||||
import rust
|
||||
import codeql.rust.dataflow.DataFlow
|
||||
import codeql.rust.dataflow.TaintTracking
|
||||
|
||||
/**
|
||||
* A data flow configuration for tracking flow from a string literal to a function
|
||||
* call argument that looks like a password. For example:
|
||||
* ```
|
||||
* fn set_password(password: &str) { ... }
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* let pwd = "123456"; // source
|
||||
* set_password(pwd); // sink (argument 0)
|
||||
* ```
|
||||
*/
|
||||
module ConstantPasswordConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
// `node` is a string literal
|
||||
node.asExpr().getExpr() instanceof StringLiteralExpr
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
// `node` is an argument whose corresponding parameter name matches the pattern "pass%"
|
||||
exists(CallExpr call, Function target, int argIndex, Variable v |
|
||||
call.getStaticTarget() = target and
|
||||
v.getParameter() = target.getParam(argIndex) and
|
||||
v.getText().matches("pass%") and
|
||||
call.getArg(argIndex) = node.asExpr().getExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// instantiate the data flow configuration as a global taint tracking module
|
||||
module ConstantPasswordFlow = TaintTracking::Global<ConstantPasswordConfig>;
|
||||
|
||||
// report flows from sources to sinks
|
||||
from DataFlow::Node sourceNode, DataFlow::Node sinkNode
|
||||
where ConstantPasswordFlow::flow(sourceNode, sinkNode)
|
||||
select sinkNode, "The value $@ is used as a constant password.", sourceNode, sourceNode.toString()
|
||||
39
rust/ql/examples/snippets/simple_sql_injection.ql
Normal file
39
rust/ql/examples/snippets/simple_sql_injection.ql
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @name Database query built from user-controlled sources
|
||||
* @description Finds places where a value from a remote or local user input
|
||||
* is used as the first argument of a call to `sqlx_core::query::query`.
|
||||
* @id rust/examples/simple-sql-injection
|
||||
* @tags example
|
||||
*/
|
||||
|
||||
import rust
|
||||
import codeql.rust.dataflow.DataFlow
|
||||
import codeql.rust.dataflow.TaintTracking
|
||||
import codeql.rust.Concepts
|
||||
|
||||
/**
|
||||
* A data flow configuration for tracking flow from a user input (threat model
|
||||
* source) to the first argument of a call to `sqlx_core::query::query`.
|
||||
*/
|
||||
module SqlInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node node) {
|
||||
// `node` is a user input (threat model source)
|
||||
node instanceof ActiveThreatModelSource
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node) {
|
||||
// `node` is the first argument of a call to `sqlx_core::query::query`
|
||||
exists(CallExpr call |
|
||||
call.getStaticTarget().getCanonicalPath() = "sqlx_core::query::query" and
|
||||
call.getArg(0) = node.asExpr().getExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// instantiate the data flow configuration as a global taint tracking module
|
||||
module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;
|
||||
|
||||
// report flows from sources to sinks
|
||||
from DataFlow::Node sourceNode, DataFlow::Node sinkNode
|
||||
where SqlInjectionFlow::flow(sourceNode, sinkNode)
|
||||
select sinkNode, "This query depends on a $@.", sourceNode, "user-provided value"
|
||||
4
rust/ql/src/change-notes/2025-11-07-example-queries.md
Normal file
4
rust/ql/src/change-notes/2025-11-07-example-queries.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* Added three example queries (`rust/examples/empty-if`, `rust/examples/simple-sql-injection` and `rust/examples/simple-constant-password`) to help developers learn to write CodeQL queries for Rust.
|
||||
Reference in New Issue
Block a user