mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge branch 'main' into js/vue_tanstack_model
This commit is contained in:
2
.github/codeql/codeql-config.yml
vendored
2
.github/codeql/codeql-config.yml
vendored
@@ -10,4 +10,6 @@ paths-ignore:
|
||||
- '/javascript/ql/test'
|
||||
- '/javascript/ql/integration-tests'
|
||||
- '/javascript/extractor/tests'
|
||||
- '/javascript/extractor/parser-tests'
|
||||
- '/javascript/ql/src/'
|
||||
- '/rust/ql'
|
||||
|
||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -409,6 +409,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argfile",
|
||||
"chalk-ir",
|
||||
"chrono",
|
||||
"clap",
|
||||
"codeql-extractor",
|
||||
@@ -422,6 +423,7 @@ dependencies = [
|
||||
"ra_ap_hir",
|
||||
"ra_ap_hir_def",
|
||||
"ra_ap_hir_expand",
|
||||
"ra_ap_hir_ty",
|
||||
"ra_ap_ide_db",
|
||||
"ra_ap_intern",
|
||||
"ra_ap_load-cargo",
|
||||
|
||||
@@ -73,6 +73,7 @@ use_repo(
|
||||
tree_sitter_extractors_deps,
|
||||
"vendor_ts__anyhow-1.0.96",
|
||||
"vendor_ts__argfile-0.2.1",
|
||||
"vendor_ts__chalk-ir-0.99.0",
|
||||
"vendor_ts__chrono-0.4.39",
|
||||
"vendor_ts__clap-4.5.31",
|
||||
"vendor_ts__dunce-1.0.5",
|
||||
@@ -94,6 +95,7 @@ use_repo(
|
||||
"vendor_ts__ra_ap_hir-0.0.266",
|
||||
"vendor_ts__ra_ap_hir_def-0.0.266",
|
||||
"vendor_ts__ra_ap_hir_expand-0.0.266",
|
||||
"vendor_ts__ra_ap_hir_ty-0.0.266",
|
||||
"vendor_ts__ra_ap_ide_db-0.0.266",
|
||||
"vendor_ts__ra_ap_intern-0.0.266",
|
||||
"vendor_ts__ra_ap_load-cargo-0.0.266",
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
- description: Security-and-quality queries for GitHub Actions
|
||||
- import: codeql-suites/actions-security-extended.qls
|
||||
- queries: .
|
||||
- apply: security-and-quality-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
- description: Extended and experimental security queries for GitHub Actions
|
||||
- import: codeql-suites/actions-code-scanning.qls
|
||||
- queries: .
|
||||
- apply: security-experimental-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
|
||||
4
cpp/ql/lib/change-notes/2025-03-13-ascertaindef.md
Normal file
4
cpp/ql/lib/change-notes/2025-03-13-ascertaindef.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added `Node.asUncertainDefinition` and `Node.asCertainDefinition` to the `DataFlow::Node` class for querying whether a definition overwrites the entire destination buffer.
|
||||
@@ -313,13 +313,79 @@ class Node extends TIRDataFlowNode {
|
||||
* `n.asExpr() instanceof IncrementOperation` since the result of evaluating
|
||||
* the expression `x++` is passed to `sink`.
|
||||
*/
|
||||
Expr asDefinition() {
|
||||
exists(StoreInstruction store |
|
||||
Expr asDefinition() { result = this.asDefinition(_) }
|
||||
|
||||
/**
|
||||
* Gets the definition associated with this node, if any.
|
||||
*
|
||||
* For example, consider the following example
|
||||
* ```cpp
|
||||
* int x = 42; // 1
|
||||
* x = 34; // 2
|
||||
* ++x; // 3
|
||||
* x++; // 4
|
||||
* x += 1; // 5
|
||||
* int y = x += 2; // 6
|
||||
* ```
|
||||
* - For (1) the result is `42`.
|
||||
* - For (2) the result is `x = 34`.
|
||||
* - For (3) the result is `++x`.
|
||||
* - For (4) the result is `x++`.
|
||||
* - For (5) the result is `x += 1`.
|
||||
* - For (6) there are two results:
|
||||
* - For the definition generated by `x += 2` the result is `x += 2`
|
||||
* - For the definition generated by `int y = ...` the result is
|
||||
* also `x += 2`.
|
||||
*
|
||||
* For assignments, `node.asDefinition(_)` and `node.asExpr()` will both exist
|
||||
* for the same dataflow node. However, for expression such as `x++` that
|
||||
* both write to `x` and read the current value of `x`, `node.asDefinition(_)`
|
||||
* will give the node corresponding to the value after the increment, and
|
||||
* `node.asExpr()` will give the node corresponding to the value before the
|
||||
* increment. For an example of this, consider the following:
|
||||
*
|
||||
* ```cpp
|
||||
* sink(x++);
|
||||
* ```
|
||||
* in the above program, there will not be flow from a node `n` such that
|
||||
* `n.asDefinition(_) instanceof IncrementOperation` to the argument of `sink`
|
||||
* since the value passed to `sink` is the value before to the increment.
|
||||
* However, there will be dataflow from a node `n` such that
|
||||
* `n.asExpr() instanceof IncrementOperation` since the result of evaluating
|
||||
* the expression `x++` is passed to `sink`.
|
||||
*
|
||||
* If `uncertain = false` then the definition is guaranteed to overwrite
|
||||
* the entire buffer pointed to by the destination address of the definition.
|
||||
* Otherwise, `uncertain = true`.
|
||||
*
|
||||
* For example, the write `int x; x = 42;` is guaranteed to overwrite all the
|
||||
* bytes allocated to `x`, while the assignment `int p[10]; p[3] = 42;` has
|
||||
* `uncertain = true` since the write will not overwrite the entire buffer
|
||||
* pointed to by `p`.
|
||||
*/
|
||||
Expr asDefinition(boolean uncertain) {
|
||||
exists(StoreInstruction store, Ssa::DefinitionExt def |
|
||||
store = this.asInstruction() and
|
||||
result = asDefinitionImpl(store)
|
||||
result = asDefinitionImpl(store) and
|
||||
Ssa::defToNode(this, def, _, _, _, _) and
|
||||
if def.isCertain() then uncertain = false else uncertain = true
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the definition associated with this node, if this node is a certain definition.
|
||||
*
|
||||
* See `Node.asDefinition/1` for a description of certain and uncertain definitions.
|
||||
*/
|
||||
Expr asCertainDefinition() { result = this.asDefinition(false) }
|
||||
|
||||
/**
|
||||
* Gets the definition associated with this node, if this node is an uncertain definition.
|
||||
*
|
||||
* See `Node.asDefinition/1` for a description of certain and uncertain definitions.
|
||||
*/
|
||||
Expr asUncertainDefinition() { result = this.asDefinition(true) }
|
||||
|
||||
/**
|
||||
* Gets the indirect definition at a given indirection corresponding to this
|
||||
* node, if any.
|
||||
|
||||
@@ -12,7 +12,11 @@
|
||||
import cpp
|
||||
|
||||
predicate allowedTypedefs(TypedefType t) {
|
||||
t.getName() = ["I64", "U64", "I32", "U32", "I16", "U16", "I8", "U8", "F64", "F32"]
|
||||
t.getName() =
|
||||
[
|
||||
"I64", "U64", "I32", "U32", "I16", "U16", "I8", "U8", "F64", "F32", "int64_t", "uint64_t",
|
||||
"int32_t", "uint32_t", "int16_t", "uint16_t", "int8_t", "uint8_t"
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,6 +50,8 @@ from Declaration d, Type usedType
|
||||
where
|
||||
usedType = getAUsedType*(getAnImmediateUsedType(d)) and
|
||||
problematic(usedType) and
|
||||
// Allow uses of boolean types where defined by the language.
|
||||
not usedType instanceof BoolType and
|
||||
// Ignore violations for which we do not have a valid location.
|
||||
not d.getLocation() instanceof UnknownLocation
|
||||
select d,
|
||||
|
||||
@@ -37,7 +37,7 @@ module Config implements DataFlow::ConfigSig {
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
isSink(node) and node.asExpr().getUnspecifiedType() instanceof ArithmeticType
|
||||
or
|
||||
node.asInstruction().(StoreInstruction).getResultType() instanceof ArithmeticType
|
||||
node.asCertainDefinition().getUnspecifiedType() instanceof ArithmeticType
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ module Config implements DataFlow::ConfigSig {
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
isSink(node) and node.asExpr().getUnspecifiedType() instanceof ArithmeticType
|
||||
or
|
||||
node.asInstruction().(StoreInstruction).getResultType() instanceof ArithmeticType
|
||||
node.asCertainDefinition().getUnspecifiedType() instanceof ArithmeticType
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ module Config implements DataFlow::ConfigSig {
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
isSink(node) and isArithmeticNonCharType(node.asExpr().getUnspecifiedType())
|
||||
or
|
||||
isArithmeticNonCharType(node.asInstruction().(StoreInstruction).getResultType())
|
||||
isArithmeticNonCharType(node.asCertainDefinition().getUnspecifiedType())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ private module Config implements DataFlow::ConfigSig {
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
isSink(node) and node.asExpr().getUnspecifiedType() instanceof ArithmeticType
|
||||
or
|
||||
node.asInstruction().(StoreInstruction).getResultType() instanceof ArithmeticType
|
||||
node.asCertainDefinition().getUnspecifiedType() instanceof ArithmeticType
|
||||
or
|
||||
mayAddNullTerminator(_, node.asIndirectExpr())
|
||||
}
|
||||
|
||||
@@ -75,9 +75,11 @@ module Config implements DataFlow::ConfigSig {
|
||||
predicate isSink(DataFlow::Node sink) { isSink(sink, _, _) }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
exists(StoreInstruction store | store = node.asInstruction() |
|
||||
exists(StoreInstruction store, Expr e |
|
||||
store = node.asInstruction() and e = node.asCertainDefinition()
|
||||
|
|
||||
// Block flow to "likely small expressions"
|
||||
bounded(store.getSourceValue().getUnconvertedResultExpression())
|
||||
bounded(e)
|
||||
or
|
||||
// Block flow to "small types"
|
||||
store.getResultType().getUnspecifiedType().(IntegralType).getSize() <= 1
|
||||
|
||||
4
cpp/ql/src/change-notes/2025-03-11-basic-int-types.md
Normal file
4
cpp/ql/src/change-notes/2025-03-11-basic-int-types.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The query "Use of basic integral type" (`cpp/jpl-c/basic-int-types`) no longer produces alerts for the standard fixed width integer types (`int8_t`, `uint8_t`, etc.), and the `_Bool` and `bool` types.
|
||||
@@ -1,3 +1 @@
|
||||
| test.c:6:26:6:26 | x | x uses the basic integral type unsigned char rather than a typedef with size and signedness. |
|
||||
| test.c:7:20:7:20 | x | x uses the basic integral type unsigned char rather than a typedef with size and signedness. |
|
||||
| test.c:10:16:10:20 | test7 | test7 uses the basic integral type unsigned char rather than a typedef with size and signedness. |
|
||||
|
||||
@@ -16,5 +16,12 @@ import semmle.code.csharp.frameworks.System
|
||||
from MethodCall mc, IntegralType t
|
||||
where
|
||||
mc.getTarget() instanceof GetHashCodeMethod and
|
||||
t = mc.getQualifier().getType()
|
||||
t = mc.getQualifier().getType() and
|
||||
(
|
||||
t instanceof ByteType or
|
||||
t instanceof SByteType or
|
||||
t instanceof ShortType or
|
||||
t instanceof UShortType or
|
||||
t instanceof IntType
|
||||
)
|
||||
select mc, "Calling GetHashCode() on type " + t.toStringWithTypes() + " is redundant."
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Increase query precision for `cs/useless-gethashcode-call` by not flagging calls to `GetHashCode` on `uint`, `long` and `ulong`.
|
||||
@@ -9,3 +9,5 @@
|
||||
- cs/inefficient-containskey
|
||||
- cs/call-to-object-tostring
|
||||
- cs/local-not-disposed
|
||||
- cs/constant-condition
|
||||
- cs/useless-gethashcode-call
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace DisposalTests
|
||||
{
|
||||
public class MyType : IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class Class1 : IDisposable
|
||||
{
|
||||
public void DisposesParameter(IDisposable p1, IDisposable p2)
|
||||
{
|
||||
p1.Dispose();
|
||||
}
|
||||
|
||||
public void CapturesDisposable(MyType p1, MyType p2)
|
||||
{
|
||||
field1 = p1;
|
||||
field2 = p2;
|
||||
}
|
||||
|
||||
public void DisposesSelf()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
MyType field1, field2;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
field1.Dispose();
|
||||
}
|
||||
|
||||
public static void Dispose(IDisposable d)
|
||||
{
|
||||
d.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Xml;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
class Test
|
||||
{
|
||||
@@ -48,9 +49,9 @@ class Test
|
||||
}
|
||||
|
||||
// BAD: No Dispose call
|
||||
var c1d = new Timer(TimerProc);
|
||||
var fs = new FileStream("", FileMode.CreateNew, FileAccess.Write);
|
||||
new FileStream("", FileMode.CreateNew, FileAccess.Write).Fluent();
|
||||
var c1d = new Timer(TimerProc); // $ Alert
|
||||
var fs = new FileStream("", FileMode.CreateNew, FileAccess.Write); // $ Alert
|
||||
new FileStream("", FileMode.CreateNew, FileAccess.Write).Fluent(); // $ Alert
|
||||
|
||||
// GOOD: Disposed via wrapper
|
||||
fs = new FileStream("", FileMode.CreateNew, FileAccess.Write);
|
||||
@@ -72,13 +73,10 @@ class Test
|
||||
;
|
||||
|
||||
// GOOD: XmlDocument.Load disposes incoming XmlReader (False positive as this is disposed in library code)
|
||||
var xmlReader = XmlReader.Create(new StringReader("xml"), null);
|
||||
var xmlReader = XmlReader.Create(new StringReader("xml"), null); // $ Alert
|
||||
var xmlDoc = new XmlDocument();
|
||||
xmlDoc.Load(xmlReader);
|
||||
|
||||
// GOOD: Passed to a library (False positive as this is disposed in library code).
|
||||
DisposalTests.Class1.Dispose(new StreamWriter("output.txt"));
|
||||
|
||||
// GOOD: Disposed automatically.
|
||||
using var c2 = new Timer(TimerProc);
|
||||
|
||||
@@ -97,6 +95,15 @@ class Test
|
||||
return null;
|
||||
}
|
||||
|
||||
public void M(IHttpClientFactory factory)
|
||||
{
|
||||
// GOOD: Factory tracks and disposes.
|
||||
HttpClient client1 = factory.CreateClient();
|
||||
|
||||
// BAD: No Dispose call
|
||||
var client2 = new HttpClient(); // $ Alert
|
||||
}
|
||||
|
||||
// GOOD: Escapes
|
||||
IDisposable Create() => new Timer(TimerProc);
|
||||
|
||||
@@ -107,6 +114,15 @@ class Test
|
||||
public void Dispose() { }
|
||||
}
|
||||
|
||||
class Bad
|
||||
{
|
||||
long GetLength(string file)
|
||||
{
|
||||
var stream = new FileStream(file, FileMode.Open); // $ Alert
|
||||
return stream.Length;
|
||||
}
|
||||
}
|
||||
|
||||
static class Extensions
|
||||
{
|
||||
public static FileStream Fluent(this FileStream fs) => fs;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
| NoDisposeCallOnLocalIDisposable.cs:51:19:51:38 | object creation of type Timer | Disposable 'Timer' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposable.cs:52:18:52:73 | object creation of type FileStream | Disposable 'FileStream' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposable.cs:53:9:53:64 | object creation of type FileStream | Disposable 'FileStream' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposable.cs:75:25:75:71 | call to method Create | Disposable 'XmlReader' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposable.cs:75:42:75:64 | object creation of type StringReader | Disposable 'StringReader' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposable.cs:80:38:80:67 | object creation of type StreamWriter | Disposable 'StreamWriter' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposableBad.cs:8:22:8:56 | object creation of type FileStream | Disposable 'FileStream' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposable.cs:52:19:52:38 | object creation of type Timer | Disposable 'Timer' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposable.cs:53:18:53:73 | object creation of type FileStream | Disposable 'FileStream' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposable.cs:54:9:54:64 | object creation of type FileStream | Disposable 'FileStream' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposable.cs:76:25:76:71 | call to method Create | Disposable 'XmlReader' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposable.cs:76:42:76:64 | object creation of type StringReader | Disposable 'StringReader' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposable.cs:104:23:104:38 | object creation of type HttpClient | Disposable 'HttpClient' is created but not disposed. |
|
||||
| NoDisposeCallOnLocalIDisposable.cs:121:22:121:56 | object creation of type FileStream | Disposable 'FileStream' is created but not disposed. |
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
API Abuse/NoDisposeCallOnLocalIDisposable.ql
|
||||
query: API Abuse/NoDisposeCallOnLocalIDisposable.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
class Bad
|
||||
{
|
||||
long GetLength(string file)
|
||||
{
|
||||
var stream = new FileStream(file, FileMode.Open);
|
||||
return stream.Length;
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
semmle-extractor-options: /r:System.Private.Xml.dll /r:System.IO.Compression.dll
|
||||
semmle-extractor-options: /nostdlib /noconfig
|
||||
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj
|
||||
|
||||
@@ -3,16 +3,16 @@ class IntGetHashCode
|
||||
void Test()
|
||||
{
|
||||
// These are all bad:
|
||||
default(uint).GetHashCode();
|
||||
default(int).GetHashCode();
|
||||
default(long).GetHashCode();
|
||||
default(ulong).GetHashCode();
|
||||
default(short).GetHashCode();
|
||||
default(ushort).GetHashCode();
|
||||
default(byte).GetHashCode();
|
||||
default(sbyte).GetHashCode();
|
||||
default(int).GetHashCode(); // $ Alert
|
||||
default(short).GetHashCode(); // $ Alert
|
||||
default(ushort).GetHashCode(); // $ Alert
|
||||
default(byte).GetHashCode(); // $ Alert
|
||||
default(sbyte).GetHashCode(); // $ Alert
|
||||
|
||||
// These are all good:
|
||||
default(uint).GetHashCode();
|
||||
default(long).GetHashCode();
|
||||
default(ulong).GetHashCode();
|
||||
default(double).GetHashCode();
|
||||
default(float).GetHashCode();
|
||||
default(char).GetHashCode();
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
| IntGetHashCode.cs:6:9:6:35 | call to method GetHashCode | Calling GetHashCode() on type uint is redundant. |
|
||||
| IntGetHashCode.cs:7:9:7:34 | call to method GetHashCode | Calling GetHashCode() on type int is redundant. |
|
||||
| IntGetHashCode.cs:8:9:8:35 | call to method GetHashCode | Calling GetHashCode() on type long is redundant. |
|
||||
| IntGetHashCode.cs:9:9:9:36 | call to method GetHashCode | Calling GetHashCode() on type ulong is redundant. |
|
||||
| IntGetHashCode.cs:10:9:10:36 | call to method GetHashCode | Calling GetHashCode() on type short is redundant. |
|
||||
| IntGetHashCode.cs:11:9:11:37 | call to method GetHashCode | Calling GetHashCode() on type ushort is redundant. |
|
||||
| IntGetHashCode.cs:12:9:12:35 | call to method GetHashCode | Calling GetHashCode() on type byte is redundant. |
|
||||
| IntGetHashCode.cs:13:9:13:36 | call to method GetHashCode | Calling GetHashCode() on type sbyte is redundant. |
|
||||
| IntGetHashCode.cs:6:9:6:34 | call to method GetHashCode | Calling GetHashCode() on type int is redundant. |
|
||||
| IntGetHashCode.cs:7:9:7:36 | call to method GetHashCode | Calling GetHashCode() on type short is redundant. |
|
||||
| IntGetHashCode.cs:8:9:8:37 | call to method GetHashCode | Calling GetHashCode() on type ushort is redundant. |
|
||||
| IntGetHashCode.cs:9:9:9:35 | call to method GetHashCode | Calling GetHashCode() on type byte is redundant. |
|
||||
| IntGetHashCode.cs:10:9:10:36 | call to method GetHashCode | Calling GetHashCode() on type sbyte is redundant. |
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Useless code/IntGetHashCode.ql
|
||||
query: Useless code/IntGetHashCode.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
4
javascript/ql/lib/change-notes/2025-03-13-unescape.md
Normal file
4
javascript/ql/lib/change-notes/2025-03-13-unescape.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added taint-steps for `unescape()`.
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import javascript
|
||||
private import dataflow.internal.StepSummary
|
||||
private import semmle.javascript.dataflow.internal.FlowSteps
|
||||
|
||||
/**
|
||||
* A call to the `Promise` constructor, such as `new Promise((resolve, reject) => { ... })`.
|
||||
@@ -397,6 +398,17 @@ module PromiseFlow {
|
||||
value = call.getCallback(0).getExceptionalReturn() and
|
||||
obj = call
|
||||
)
|
||||
or
|
||||
exists(DataFlow::FunctionNode f | f.getFunction().isAsync() |
|
||||
// ordinary return
|
||||
prop = valueProp() and
|
||||
value = f.getAReturn() and
|
||||
obj = f.getReturnNode()
|
||||
or
|
||||
// exceptional return
|
||||
prop = errorProp() and
|
||||
localExceptionStepWithAsyncFlag(value, obj, true)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,30 +537,6 @@ private class PromiseTaintStep extends TaintTracking::LegacyTaintStep {
|
||||
* Defines flow steps for return on async functions.
|
||||
*/
|
||||
private module AsyncReturnSteps {
|
||||
private predicate valueProp = Promises::valueProp/0;
|
||||
|
||||
private predicate errorProp = Promises::errorProp/0;
|
||||
|
||||
private import semmle.javascript.dataflow.internal.FlowSteps
|
||||
|
||||
/**
|
||||
* A data-flow step for ordinary and exceptional returns from async functions.
|
||||
*/
|
||||
private class AsyncReturn extends LegacyPreCallGraphStep {
|
||||
override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
|
||||
exists(DataFlow::FunctionNode f | f.getFunction().isAsync() |
|
||||
// ordinary return
|
||||
prop = valueProp() and
|
||||
pred = f.getAReturn() and
|
||||
succ = f.getReturnNode()
|
||||
or
|
||||
// exceptional return
|
||||
prop = errorProp() and
|
||||
localExceptionStepWithAsyncFlag(pred, succ, true)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A data-flow step for ordinary return from an async function in a taint configuration.
|
||||
*/
|
||||
|
||||
@@ -494,7 +494,7 @@ module TaintTracking {
|
||||
succ = c and
|
||||
c =
|
||||
DataFlow::globalVarRef([
|
||||
"encodeURI", "decodeURI", "encodeURIComponent", "decodeURIComponent"
|
||||
"encodeURI", "decodeURI", "encodeURIComponent", "decodeURIComponent", "unescape"
|
||||
]).getACall() and
|
||||
pred = c.getArgument(0)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import * as t from "testlib";
|
||||
|
||||
async function getData1() {
|
||||
const data = await fetch("https://example.com/content");
|
||||
return data.json(); /* def=moduleImport("testlib").getMember("exports").getMember("foo").getParameter(0).getReturn().getPromised() */
|
||||
}
|
||||
|
||||
export function use1() {
|
||||
t.foo(() => getData1());
|
||||
}
|
||||
|
||||
async function getData2() {
|
||||
const data = await fetch("https://example.com/content");
|
||||
return data.json(); /* def=moduleImport("testlib").getMember("exports").getMember("foo").getParameter(0).getReturn().getPromised() */
|
||||
}
|
||||
|
||||
export function use2() {
|
||||
t.foo(getData2);
|
||||
}
|
||||
|
||||
export function use3() {
|
||||
t.foo(async () => {
|
||||
const data = await fetch("https://example.com/content");
|
||||
return data.json(); /* def=moduleImport("testlib").getMember("exports").getMember("foo").getParameter(0).getReturn().getPromised() */
|
||||
});
|
||||
}
|
||||
@@ -223,6 +223,7 @@
|
||||
| tst.js:477:18:477:40 | locatio ... bstr(1) | tst.js:477:18:477:30 | location.hash | tst.js:477:18:477:40 | locatio ... bstr(1) | Cross-site scripting vulnerability due to $@. | tst.js:477:18:477:30 | location.hash | user-provided value |
|
||||
| tst.js:484:33:484:63 | decodeU ... n.hash) | tst.js:484:43:484:62 | window.location.hash | tst.js:484:33:484:63 | decodeU ... n.hash) | Cross-site scripting vulnerability due to $@. | tst.js:484:43:484:62 | window.location.hash | user-provided value |
|
||||
| tst.js:492:18:492:54 | target. ... "), '') | tst.js:491:16:491:39 | documen ... .search | tst.js:492:18:492:54 | target. ... "), '') | Cross-site scripting vulnerability due to $@. | tst.js:491:16:491:39 | documen ... .search | user-provided value |
|
||||
| tst.js:499:18:499:33 | unescape(source) | tst.js:498:16:498:26 | window.name | tst.js:499:18:499:33 | unescape(source) | Cross-site scripting vulnerability due to $@. | tst.js:498:16:498:26 | window.name | user-provided value |
|
||||
| typeahead.js:25:18:25:20 | val | typeahead.js:20:22:20:45 | documen ... .search | typeahead.js:25:18:25:20 | val | Cross-site scripting vulnerability due to $@. | typeahead.js:20:22:20:45 | documen ... .search | user-provided value |
|
||||
| v-html.vue:2:8:2:23 | v-html=tainted | v-html.vue:6:42:6:58 | document.location | v-html.vue:2:8:2:23 | v-html=tainted | Cross-site scripting vulnerability due to $@. | v-html.vue:6:42:6:58 | document.location | user-provided value |
|
||||
| various-concat-obfuscations.js:4:4:4:31 | "<div>" ... </div>" | various-concat-obfuscations.js:2:16:2:39 | documen ... .search | various-concat-obfuscations.js:4:4:4:31 | "<div>" ... </div>" | Cross-site scripting vulnerability due to $@. | various-concat-obfuscations.js:2:16:2:39 | documen ... .search | user-provided value |
|
||||
@@ -745,6 +746,9 @@ edges
|
||||
| tst.js:491:7:491:39 | target | tst.js:492:18:492:23 | target | provenance | |
|
||||
| tst.js:491:16:491:39 | documen ... .search | tst.js:491:7:491:39 | target | provenance | |
|
||||
| tst.js:492:18:492:23 | target | tst.js:492:18:492:54 | target. ... "), '') | provenance | |
|
||||
| tst.js:498:7:498:26 | source | tst.js:499:27:499:32 | source | provenance | |
|
||||
| tst.js:498:16:498:26 | window.name | tst.js:498:7:498:26 | source | provenance | |
|
||||
| tst.js:499:27:499:32 | source | tst.js:499:18:499:33 | unescape(source) | provenance | |
|
||||
| typeahead.js:20:13:20:45 | target | typeahead.js:21:12:21:17 | target | provenance | |
|
||||
| typeahead.js:20:22:20:45 | documen ... .search | typeahead.js:20:13:20:45 | target | provenance | |
|
||||
| typeahead.js:21:12:21:17 | target | typeahead.js:24:30:24:32 | val | provenance | |
|
||||
@@ -1397,6 +1401,10 @@ nodes
|
||||
| tst.js:491:16:491:39 | documen ... .search | semmle.label | documen ... .search |
|
||||
| tst.js:492:18:492:23 | target | semmle.label | target |
|
||||
| tst.js:492:18:492:54 | target. ... "), '') | semmle.label | target. ... "), '') |
|
||||
| tst.js:498:7:498:26 | source | semmle.label | source |
|
||||
| tst.js:498:16:498:26 | window.name | semmle.label | window.name |
|
||||
| tst.js:499:18:499:33 | unescape(source) | semmle.label | unescape(source) |
|
||||
| tst.js:499:27:499:32 | source | semmle.label | source |
|
||||
| typeahead.js:20:13:20:45 | target | semmle.label | target |
|
||||
| typeahead.js:20:22:20:45 | documen ... .search | semmle.label | documen ... .search |
|
||||
| typeahead.js:21:12:21:17 | target | semmle.label | target |
|
||||
|
||||
@@ -607,6 +607,10 @@ nodes
|
||||
| tst.js:491:16:491:39 | documen ... .search | semmle.label | documen ... .search |
|
||||
| tst.js:492:18:492:23 | target | semmle.label | target |
|
||||
| tst.js:492:18:492:54 | target. ... "), '') | semmle.label | target. ... "), '') |
|
||||
| tst.js:498:7:498:26 | source | semmle.label | source |
|
||||
| tst.js:498:16:498:26 | window.name | semmle.label | window.name |
|
||||
| tst.js:499:18:499:33 | unescape(source) | semmle.label | unescape(source) |
|
||||
| tst.js:499:27:499:32 | source | semmle.label | source |
|
||||
| typeahead.js:9:28:9:30 | loc | semmle.label | loc |
|
||||
| typeahead.js:10:16:10:18 | loc | semmle.label | loc |
|
||||
| typeahead.js:20:13:20:45 | target | semmle.label | target |
|
||||
@@ -1186,6 +1190,9 @@ edges
|
||||
| tst.js:491:7:491:39 | target | tst.js:492:18:492:23 | target | provenance | |
|
||||
| tst.js:491:16:491:39 | documen ... .search | tst.js:491:7:491:39 | target | provenance | |
|
||||
| tst.js:492:18:492:23 | target | tst.js:492:18:492:54 | target. ... "), '') | provenance | |
|
||||
| tst.js:498:7:498:26 | source | tst.js:499:27:499:32 | source | provenance | |
|
||||
| tst.js:498:16:498:26 | window.name | tst.js:498:7:498:26 | source | provenance | |
|
||||
| tst.js:499:27:499:32 | source | tst.js:499:18:499:33 | unescape(source) | provenance | |
|
||||
| typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc | provenance | |
|
||||
| typeahead.js:20:13:20:45 | target | typeahead.js:21:12:21:17 | target | provenance | |
|
||||
| typeahead.js:20:22:20:45 | documen ... .search | typeahead.js:20:13:20:45 | target | provenance | |
|
||||
|
||||
@@ -493,3 +493,8 @@ function nonGlobalSanitizer() {
|
||||
$("#foo").html(target.replace(new RegExp("<|>", unknownFlags()), '')); // OK - most likely good. We don't know what the flags are.
|
||||
$("#foo").html(target.replace(new RegExp("<|>", "g"), ''));
|
||||
}
|
||||
|
||||
function FooBar() {
|
||||
let source = window.name; // $ Source
|
||||
$('myId').html(unescape(source)) // $ Alert
|
||||
}
|
||||
|
||||
24
misc/bazel/3rdparty/tree_sitter_extractors_deps/BUILD.bazel
generated
vendored
24
misc/bazel/3rdparty/tree_sitter_extractors_deps/BUILD.bazel
generated
vendored
@@ -55,6 +55,18 @@ alias(
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "chalk-ir-0.99.0",
|
||||
actual = "@vendor_ts__chalk-ir-0.98.0//:chalk_ir",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "chalk-ir",
|
||||
actual = "@vendor_ts__chalk-ir-0.99.0//:chalk_ir",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "chrono-0.4.39",
|
||||
actual = "@vendor_ts__chrono-0.4.39//:chrono",
|
||||
@@ -307,6 +319,18 @@ alias(
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "ra_ap_hir_ty-0.0.266",
|
||||
actual = "@vendor_ts__ra_ap_hir_ty-0.0.266//:ra_ap_hir_ty",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "ra_ap_hir_ty",
|
||||
actual = "@vendor_ts__ra_ap_hir_ty-0.0.266//:ra_ap_hir_ty",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "ra_ap_ide_db-0.0.266",
|
||||
actual = "@vendor_ts__ra_ap_ide_db-0.0.266//:ra_ap_ide_db",
|
||||
|
||||
4
misc/bazel/3rdparty/tree_sitter_extractors_deps/defs.bzl
generated
vendored
4
misc/bazel/3rdparty/tree_sitter_extractors_deps/defs.bzl
generated
vendored
@@ -327,6 +327,7 @@ _NORMAL_DEPENDENCIES = {
|
||||
_COMMON_CONDITION: {
|
||||
"anyhow": Label("@vendor_ts__anyhow-1.0.96//:anyhow"),
|
||||
"argfile": Label("@vendor_ts__argfile-0.2.1//:argfile"),
|
||||
"chalk-ir": Label("@vendor_ts__chalk-ir-0.99.0//:chalk_ir"),
|
||||
"chrono": Label("@vendor_ts__chrono-0.4.39//:chrono"),
|
||||
"clap": Label("@vendor_ts__clap-4.5.31//:clap"),
|
||||
"dunce": Label("@vendor_ts__dunce-1.0.5//:dunce"),
|
||||
@@ -339,6 +340,7 @@ _NORMAL_DEPENDENCIES = {
|
||||
"ra_ap_hir": Label("@vendor_ts__ra_ap_hir-0.0.266//:ra_ap_hir"),
|
||||
"ra_ap_hir_def": Label("@vendor_ts__ra_ap_hir_def-0.0.266//:ra_ap_hir_def"),
|
||||
"ra_ap_hir_expand": Label("@vendor_ts__ra_ap_hir_expand-0.0.266//:ra_ap_hir_expand"),
|
||||
"ra_ap_hir_ty": Label("@vendor_ts__ra_ap_hir_ty-0.0.266//:ra_ap_hir_ty"),
|
||||
"ra_ap_ide_db": Label("@vendor_ts__ra_ap_ide_db-0.0.266//:ra_ap_ide_db"),
|
||||
"ra_ap_intern": Label("@vendor_ts__ra_ap_intern-0.0.266//:ra_ap_intern"),
|
||||
"ra_ap_load-cargo": Label("@vendor_ts__ra_ap_load-cargo-0.0.266//:ra_ap_load_cargo"),
|
||||
@@ -3476,6 +3478,7 @@ def crate_repositories():
|
||||
return [
|
||||
struct(repo = "vendor_ts__anyhow-1.0.96", is_dev_dep = False),
|
||||
struct(repo = "vendor_ts__argfile-0.2.1", is_dev_dep = False),
|
||||
struct(repo = "vendor_ts__chalk-ir-0.99.0", is_dev_dep = False),
|
||||
struct(repo = "vendor_ts__chrono-0.4.39", is_dev_dep = False),
|
||||
struct(repo = "vendor_ts__clap-4.5.31", is_dev_dep = False),
|
||||
struct(repo = "vendor_ts__dunce-1.0.5", is_dev_dep = False),
|
||||
@@ -3497,6 +3500,7 @@ def crate_repositories():
|
||||
struct(repo = "vendor_ts__ra_ap_hir-0.0.266", is_dev_dep = False),
|
||||
struct(repo = "vendor_ts__ra_ap_hir_def-0.0.266", is_dev_dep = False),
|
||||
struct(repo = "vendor_ts__ra_ap_hir_expand-0.0.266", is_dev_dep = False),
|
||||
struct(repo = "vendor_ts__ra_ap_hir_ty-0.0.266", is_dev_dep = False),
|
||||
struct(repo = "vendor_ts__ra_ap_ide_db-0.0.266", is_dev_dep = False),
|
||||
struct(repo = "vendor_ts__ra_ap_intern-0.0.266", is_dev_dep = False),
|
||||
struct(repo = "vendor_ts__ra_ap_load-cargo-0.0.266", is_dev_dep = False),
|
||||
|
||||
@@ -79,6 +79,11 @@ Element getImmediateParent(Element e) {
|
||||
result = unique(Element x | e = Impl::getImmediateChild(x, _, _) | x)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the immediate child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct.
|
||||
*/
|
||||
Element getImmediateChild(Element e, int index) { result = Impl::getImmediateChild(e, index, _) }
|
||||
|
||||
/**
|
||||
* Gets the immediate child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct. `accessor` is bound the member predicate call resulting in the given child.
|
||||
*/
|
||||
@@ -92,3 +97,10 @@ Element getImmediateChildAndAccessor(Element e, int index, string accessor) {
|
||||
Element getChildAndAccessor(Element e, int index, string accessor) {
|
||||
exists(string partialAccessor | result = Impl::getImmediateChild(e, index, partialAccessor).resolve() and accessor = "get" + partialAccessor)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct. `accessor` is bound the member predicate call resulting in the given child.
|
||||
*/
|
||||
Element getChild(Element e, int index) {
|
||||
result = Impl::getImmediateChild(e, index, _).resolve()
|
||||
}
|
||||
|
||||
@@ -203,7 +203,8 @@ class NotBooleanTestVisitor(ASTVisitor):
|
||||
self.nodes = set()
|
||||
|
||||
def visit_MatchLiteralPattern(self, node):
|
||||
# MatchLiteralPatterns _look_ like boolean tests, but are not.
|
||||
# MatchLiteralPatterns _look_ like boolean tests in that they have both a true ("matched")
|
||||
# and false ("didn't match") successor, but are not.
|
||||
# Thus, without this check, we would interpret
|
||||
#
|
||||
# match x:
|
||||
@@ -212,8 +213,7 @@ class NotBooleanTestVisitor(ASTVisitor):
|
||||
#
|
||||
# (and similarly for True) as if it was a boolean test. This would cause the true edge
|
||||
# (leading to pass) to be pruned later on.
|
||||
if isinstance(node.literal, ast.Name) and node.literal.id in ('True', 'False'):
|
||||
self.nodes.add(node.literal)
|
||||
self.nodes.add(node.literal)
|
||||
|
||||
class NonlocalVisitor(ASTVisitor):
|
||||
def __init__(self):
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
|
||||
- `MatchLiteralPattern`s such as `case None: ...` are now never pruned from the extracted source code. This fixes some situations where code was wrongly identified as unreachable.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
|
||||
- Added the methods `getMinArguments` and `getMaxArguments` to the `Function` class. These return the minimum and maximum positional arguments that the given function accepts.
|
||||
@@ -746,6 +746,24 @@ class Guard extends Guard_ {
|
||||
override Expr getASubExpression() { result = this.getTest() }
|
||||
}
|
||||
|
||||
/** An annotation, such as the `int` part of `x: int` */
|
||||
class Annotation extends Expr {
|
||||
Annotation() {
|
||||
this = any(AnnAssign a).getAnnotation()
|
||||
or
|
||||
exists(Arguments args |
|
||||
this in [
|
||||
args.getAnAnnotation(),
|
||||
args.getAKwAnnotation(),
|
||||
args.getKwargannotation(),
|
||||
args.getVarargannotation()
|
||||
]
|
||||
)
|
||||
or
|
||||
this = any(FunctionExpr f).getReturns()
|
||||
}
|
||||
}
|
||||
|
||||
/* Expression Contexts */
|
||||
/** A context in which an expression used */
|
||||
class ExprContext extends ExprContext_ { }
|
||||
|
||||
@@ -163,6 +163,24 @@ class Function extends Function_, Scope, AstNode {
|
||||
ret.getValue() = result.getNode()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the minimum number of positional arguments that can be correctly passed to this function. */
|
||||
int getMinPositionalArguments() {
|
||||
result = count(this.getAnArg()) - count(this.getDefinition().getArgs().getADefault())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum number of positional arguments that can be correctly passed to this function.
|
||||
*
|
||||
* If the function has a `*vararg` parameter, there is no upper limit on the number of positional
|
||||
* arguments that can be passed to the function. In this case, this method returns a very large
|
||||
* number (currently `INT_MAX`, 2147483647, but this may change in the future).
|
||||
*/
|
||||
int getMaxPositionalArguments() {
|
||||
if exists(this.getVararg())
|
||||
then result = 2147483647 // INT_MAX
|
||||
else result = count(this.getAnArg())
|
||||
}
|
||||
}
|
||||
|
||||
/** A def statement. Note that FunctionDef extends Assign as a function definition binds the newly created function */
|
||||
|
||||
@@ -738,21 +738,9 @@ class PythonFunctionValue extends FunctionValue {
|
||||
else result = "function " + this.getQualifiedName()
|
||||
}
|
||||
|
||||
override int minParameters() {
|
||||
exists(Function f |
|
||||
f = this.getScope() and
|
||||
result = count(f.getAnArg()) - count(f.getDefinition().getArgs().getADefault())
|
||||
)
|
||||
}
|
||||
override int minParameters() { result = this.getScope().getMinPositionalArguments() }
|
||||
|
||||
override int maxParameters() {
|
||||
exists(Function f |
|
||||
f = this.getScope() and
|
||||
if exists(f.getVararg())
|
||||
then result = 2147483647 // INT_MAX
|
||||
else result = count(f.getAnArg())
|
||||
)
|
||||
}
|
||||
override int maxParameters() { result = this.getScope().getMaxPositionalArguments() }
|
||||
|
||||
/** Gets a control flow node corresponding to a return statement in this function */
|
||||
ControlFlowNode getAReturnedNode() { result = this.getScope().getAReturnValueFlowNode() }
|
||||
|
||||
@@ -34,6 +34,14 @@ predicate complex_all(Module m) {
|
||||
)
|
||||
}
|
||||
|
||||
predicate used_in_forward_declaration(Name used, Module mod) {
|
||||
exists(StringLiteral s, Annotation annotation |
|
||||
s.getS() = used.getId() and
|
||||
s.getEnclosingModule() = mod and
|
||||
annotation.getASubExpression*() = s
|
||||
)
|
||||
}
|
||||
|
||||
predicate unused_global(Name unused, GlobalVariable v) {
|
||||
not exists(ImportingStmt is | is.contains(unused)) and
|
||||
forex(DefinitionNode defn | defn.getNode() = unused |
|
||||
@@ -55,7 +63,8 @@ predicate unused_global(Name unused, GlobalVariable v) {
|
||||
unused.defines(v) and
|
||||
not name_acceptable_for_unused_variable(v) and
|
||||
not complex_all(unused.getEnclosingModule())
|
||||
)
|
||||
) and
|
||||
not used_in_forward_declaration(unused, unused.getEnclosingModule())
|
||||
}
|
||||
|
||||
from Name unused, GlobalVariable v
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
|
||||
- The `py/unused-global-variable` now no longer flags variables that are only used in forward references (e.g. the `Foo` in `def bar(x: "Foo"): ...`).
|
||||
@@ -4,6 +4,3 @@
|
||||
| test.py:21:5:21:38 | For | This statement is unreachable. |
|
||||
| test.py:28:9:28:21 | ExprStmt | This statement is unreachable. |
|
||||
| test.py:84:5:84:21 | ExceptStmt | This statement is unreachable. |
|
||||
| test.py:158:9:159:16 | Case | This statement is unreachable. |
|
||||
| test.py:162:13:162:16 | Pass | This statement is unreachable. |
|
||||
| test.py:167:13:167:16 | Pass | This statement is unreachable. |
|
||||
|
||||
@@ -137,3 +137,21 @@ def test_dict_unpacking(queryset, field_name, value):
|
||||
for tag in value.split(','):
|
||||
queryset = queryset.filter(**{field_name + '__name': tag})
|
||||
return queryset
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
ParamAnnotation = int
|
||||
ReturnAnnotation = int
|
||||
AssignmentAnnotation = int
|
||||
ForwardParamAnnotation = int
|
||||
ForwardReturnAnnotation = int
|
||||
ForwardAssignmentAnnotation = int
|
||||
|
||||
def test_direct_annotation(x: ParamAnnotation) -> ReturnAnnotation:
|
||||
if x:
|
||||
y : AssignmentAnnotation = 1
|
||||
|
||||
def test_forward_annotation(x: "ForwardParamAnnotation") -> "ForwardReturnAnnotation":
|
||||
if x:
|
||||
y : "ForwardAssignmentAnnotation" = 1
|
||||
|
||||
@@ -14,6 +14,7 @@ ra_ap_base_db = "0.0.266"
|
||||
ra_ap_hir = "0.0.266"
|
||||
ra_ap_hir_def = "0.0.266"
|
||||
ra_ap_ide_db = "0.0.266"
|
||||
ra_ap_hir_ty = "0.0.266"
|
||||
ra_ap_hir_expand = "0.0.266"
|
||||
ra_ap_load-cargo = "0.0.266"
|
||||
ra_ap_paths = "0.0.266"
|
||||
@@ -39,3 +40,4 @@ toml = "0.8.20"
|
||||
tracing = "0.1.41"
|
||||
tracing-flame = "0.2.0"
|
||||
tracing-subscriber = "0.3.19"
|
||||
chalk-ir = "0.99.0"
|
||||
|
||||
1311
rust/extractor/src/crate_graph.rs
Normal file
1311
rust/extractor/src/crate_graph.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -83,6 +83,7 @@ pub enum ExtractionStepKind {
|
||||
LoadSource,
|
||||
Parse,
|
||||
Extract,
|
||||
CrateGraph,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
@@ -128,6 +129,10 @@ impl ExtractionStep {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn crate_graph(start: Instant) -> Self {
|
||||
Self::new(start, ExtractionStepKind::CrateGraph, None)
|
||||
}
|
||||
|
||||
pub fn load_source(start: Instant, target: &Path) -> Self {
|
||||
Self::new(
|
||||
start,
|
||||
|
||||
2
rust/extractor/src/generated/.generated.list
generated
2
rust/extractor/src/generated/.generated.list
generated
@@ -1,2 +1,2 @@
|
||||
mod.rs 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7
|
||||
top.rs da0f43b99d3a173520048275597e2b052a7351f6fcb2ad5fc912257976742bb7 da0f43b99d3a173520048275597e2b052a7351f6fcb2ad5fc912257976742bb7
|
||||
top.rs 4b7dee6ebdbb2f8bd2f387cbb71e0481475de0a94c0baaac4699f19551256d65 4b7dee6ebdbb2f8bd2f387cbb71e0481475de0a94c0baaac4699f19551256d65
|
||||
|
||||
48
rust/extractor/src/generated/top.rs
generated
48
rust/extractor/src/generated/top.rs
generated
@@ -22,6 +22,54 @@ impl trap::TrapClass for Element {
|
||||
fn class_name() -> &'static str { "Element" }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Crate {
|
||||
pub id: trap::TrapId<Crate>,
|
||||
pub name: Option<String>,
|
||||
pub version: Option<String>,
|
||||
pub module: Option<trap::Label<Module>>,
|
||||
pub cfg_options: Vec<String>,
|
||||
pub dependencies: Vec<trap::Label<Crate>>,
|
||||
}
|
||||
|
||||
impl trap::TrapEntry for Crate {
|
||||
fn extract_id(&mut self) -> trap::TrapId<Self> {
|
||||
std::mem::replace(&mut self.id, trap::TrapId::Star)
|
||||
}
|
||||
|
||||
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
|
||||
out.add_tuple("crates", vec![id.into()]);
|
||||
if let Some(v) = self.name {
|
||||
out.add_tuple("crate_names", vec![id.into(), v.into()]);
|
||||
}
|
||||
if let Some(v) = self.version {
|
||||
out.add_tuple("crate_versions", vec![id.into(), v.into()]);
|
||||
}
|
||||
if let Some(v) = self.module {
|
||||
out.add_tuple("crate_modules", vec![id.into(), v.into()]);
|
||||
}
|
||||
for (i, v) in self.cfg_options.into_iter().enumerate() {
|
||||
out.add_tuple("crate_cfg_options", vec![id.into(), i.into(), v.into()]);
|
||||
}
|
||||
for (i, v) in self.dependencies.into_iter().enumerate() {
|
||||
out.add_tuple("crate_dependencies", vec![id.into(), i.into(), v.into()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl trap::TrapClass for Crate {
|
||||
fn class_name() -> &'static str { "Crate" }
|
||||
}
|
||||
|
||||
impl From<trap::Label<Crate>> for trap::Label<Element> {
|
||||
fn from(value: trap::Label<Crate>) -> Self {
|
||||
// SAFETY: this is safe because in the dbscheme Crate is a subclass of Element
|
||||
unsafe {
|
||||
Self::from_untyped(value.as_untyped())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ExtractorStep {
|
||||
pub id: trap::TrapId<ExtractorStep>,
|
||||
|
||||
@@ -23,6 +23,7 @@ use tracing_subscriber::util::SubscriberInitExt;
|
||||
|
||||
mod archive;
|
||||
mod config;
|
||||
mod crate_graph;
|
||||
mod diagnostics;
|
||||
pub mod generated;
|
||||
mod qltest;
|
||||
@@ -255,6 +256,11 @@ fn main() -> anyhow::Result<()> {
|
||||
if let Some((ref db, ref vfs)) =
|
||||
extractor.load_manifest(manifest, &cargo_config, &load_cargo_config)
|
||||
{
|
||||
let before_crate_graph = Instant::now();
|
||||
crate_graph::extract_crate_graph(extractor.traps, db, vfs);
|
||||
extractor
|
||||
.steps
|
||||
.push(ExtractionStep::crate_graph(before_crate_graph));
|
||||
let semantics = Semantics::new(db);
|
||||
for file in files {
|
||||
match extractor.load_source(file, &semantics, vfs) {
|
||||
|
||||
@@ -74,7 +74,7 @@ macro_rules! trap_key {
|
||||
$(
|
||||
key.push_str(&$x.as_key_part());
|
||||
)*
|
||||
$crate::TrapId::Key(key)
|
||||
trap::TrapId::Key(key)
|
||||
}};
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ impl<T: TrapClass> From<Label<T>> for trap::Arg {
|
||||
}
|
||||
|
||||
pub struct TrapFile {
|
||||
path: PathBuf,
|
||||
pub path: PathBuf,
|
||||
pub writer: Writer,
|
||||
compression: Compression,
|
||||
}
|
||||
@@ -171,6 +171,26 @@ impl TrapFile {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn emit_file_only_location<E: TrapClass>(
|
||||
&mut self,
|
||||
file_label: Label<generated::File>,
|
||||
entity_label: Label<E>,
|
||||
) {
|
||||
let location_label = extractor::location_label(
|
||||
&mut self.writer,
|
||||
trap::Location {
|
||||
file_label: file_label.as_untyped(),
|
||||
start_line: 0,
|
||||
start_column: 0,
|
||||
end_line: 0,
|
||||
end_column: 0,
|
||||
},
|
||||
);
|
||||
self.writer.add_tuple(
|
||||
"locatable_locations",
|
||||
vec![entity_label.into(), location_label.into()],
|
||||
);
|
||||
}
|
||||
pub fn emit_diagnostic(
|
||||
&mut self,
|
||||
severity: DiagnosticSeverity,
|
||||
|
||||
15
rust/ql/.generated.list
generated
15
rust/ql/.generated.list
generated
@@ -43,6 +43,7 @@ lib/codeql/rust/elements/ConstArg.qll f37b34417503bbd2f3ce09b3211d8fa71f6a954970
|
||||
lib/codeql/rust/elements/ConstBlockPat.qll a25f42b84dbeb33e10955735ef53b8bb7e3258522d6d1a9068f19adaf1af89d9 eeb816d2b54db77a1e7bb70e90b68d040a0cd44e9d44455a223311c3615c5e6e
|
||||
lib/codeql/rust/elements/ConstParam.qll 248db1e3abef6943326c42478a15f148f8cdaa25649ef5578064b15924c53351 28babba3aea28a65c3fe3b3db6cb9c86f70d7391e9d6ef9188eb2e4513072f9f
|
||||
lib/codeql/rust/elements/ContinueExpr.qll 9f27c5d5c819ad0ebc5bd10967ba8d33a9dc95b9aae278fcfb1fcf9216bda79c 0dc061445a6b89854fdce92aaf022fdc76b724511a50bb777496ce75c9ecb262
|
||||
lib/codeql/rust/elements/Crate.qll 67a3b953a04244e2fcebe7a18be13bc7fdb8781669819e473823a9168f3f5412 aef65281efbc8c7e7b3747693626718ca25b3d9a90aa42221de00998eca44efe
|
||||
lib/codeql/rust/elements/DynTraitTypeRepr.qll 5953263ec1e77613170c13b5259b22a71c206a7e08841d2fa1a0b373b4014483 d4380c6cc460687dcd8598df27cad954ef4f508f1117a82460d15d295a7b64ab
|
||||
lib/codeql/rust/elements/Element.qll 0b62d139fef54ed2cf2e2334806aa9bfbc036c9c2085d558f15a42cc3fa84c48 24b999b93df79383ef27ede46e38da752868c88a07fe35fcff5d526684ba7294
|
||||
lib/codeql/rust/elements/Enum.qll 2f122b042519d55e221fceac72fce24b30d4caf1947b25e9b68ee4a2095deb11 83a47445145e4fda8c3631db602a42dbb7a431f259eddf5c09dccd86f6abdd0e
|
||||
@@ -254,6 +255,7 @@ lib/codeql/rust/elements/internal/ConstImpl.qll 7aac2b441a41f21b7d788e3eb042554f
|
||||
lib/codeql/rust/elements/internal/ConstParamConstructor.qll f6645f952aac87c7e00e5e9661275312a1df47172088b4de6b5a253d5c4ed048 eda737470a7b89cf6a02715c9147d074041d6d00fd50d5b2d70266add6e4b571
|
||||
lib/codeql/rust/elements/internal/ConstParamImpl.qll 909d85d857dfb973cd8e148744d3a88506d113d193d35ab0243be745d004ad45 c9e18170c5b4e4d5fca9f175bb139a248055b608ceafdd90c7182d06d67c3cba
|
||||
lib/codeql/rust/elements/internal/ContinueExprConstructor.qll cd93f1b35ccdb031d7e8deba92f6a76187f6009c454f3ea07e89ba459de57ca6 6f658e7d580c4c9068b01d6dd6f72888b8800860668a6653f8c3b27dc9996935
|
||||
lib/codeql/rust/elements/internal/CrateConstructor.qll 2a3710ed6ff4ffdbc773ac16e2cf176415be8908e1d59fd0702bdeddbae096f4 f75a069b0ef71e54089001eb3a34b8a9e4ce8e4f65ffa71b669b38cf86e0af40
|
||||
lib/codeql/rust/elements/internal/DynTraitTypeReprConstructor.qll 6964e6c80fb7f5e283c1d15562cef18ed097452b7fcbc04eff780c7646675c7a f03c4830bf1b958fdfb6563136fa21c911b2e41ce1d1caee14ec572c7232866d
|
||||
lib/codeql/rust/elements/internal/DynTraitTypeReprImpl.qll fa2dc41b441c2e8d663644ca8ae53f473ac54b3c977490b5173787cffe4a62b1 118945a547627b639574c5f8e58bf7dbf5f3882c6d74ebf363c28c8fb88799d3
|
||||
lib/codeql/rust/elements/internal/EnumConstructor.qll eca1a13937faacb1db50e4cf69d175f992f2204a5aaed9144bb6f3cb63814ac5 1bafba78b2729fdb052a25a1ba3f4f70871564aa4df632b4a1d467858a437924
|
||||
@@ -284,7 +286,6 @@ lib/codeql/rust/elements/internal/GenericArgImpl.qll 6b1b804c357425c223f926e560a
|
||||
lib/codeql/rust/elements/internal/GenericArgListConstructor.qll 46859bb3eb09d77987a18642d65ba2e13471a4dc9c0a83a192fddc82e37c335c 2c7d54c876269a88d3461b05745e73b06532b1616cae9b614ac94b28735d8fc4
|
||||
lib/codeql/rust/elements/internal/GenericParamImpl.qll f435f80d7f275803c1311d362467f4a367deb5a2c0245b17a9e12468a2c3ce2f 8e8fcc29f510efa03ce194ad3a1e2ae3fbd7f8e04ab5a4a2d1db03e95f388446
|
||||
lib/codeql/rust/elements/internal/GenericParamListConstructor.qll 7221146d1724e0add3a8e70e0e46670142589eb7143425e1871ac4358a8c8bdb 2fbb7576444d6b2da6164245e2660d592d276ae2c1ca9f2bda5656b1c5c0a73a
|
||||
lib/codeql/rust/elements/internal/GenericParamListImpl.qll 524aa0949df6d4d2cb9bee6226650f63a6f181d7644933fa265673b281074885 27b0210e5eaa2040bc8a093e35e1394befb6994b25369544738d0447ef269a9c
|
||||
lib/codeql/rust/elements/internal/IdentPatConstructor.qll 09792f5a070996b65f095dc6b1b9e0fb096a56648eed26c0643c59f82377cab0 0bb1a9fcdc62b5197aef3dd6e0ea4d679dde10d5be54b57b5209727ba66e078b
|
||||
lib/codeql/rust/elements/internal/IfExprConstructor.qll 03088b54c8fa623f93a5b5a7eb896f680e8b0e9025488157a02c48aaebc6ad56 906f916c3690d0721a31dd31b302dcdcec4233bb507683007d82cf10793a648f
|
||||
lib/codeql/rust/elements/internal/ImplConstructor.qll 24edccca59f70d812d1458b412a45310ddc096d095332f6e3258903c54c1bb44 7eb673b3ab33a0873ee5ce189105425066b376821cce0fc9eb8ace22995f0bc7
|
||||
@@ -501,6 +502,7 @@ lib/codeql/rust/elements/internal/generated/ConstArg.qll e2451cac6ee464f5b64883d
|
||||
lib/codeql/rust/elements/internal/generated/ConstBlockPat.qll 7526d83ee9565d74776f42db58b1a2efff6fb324cfc7137f51f2206fee815d79 0ab3c22908ff790e7092e576a5df3837db33c32a7922a513a0f5e495729c1ac5
|
||||
lib/codeql/rust/elements/internal/generated/ConstParam.qll 310342603959a4d521418caec45b585b97e3a5bf79368769c7150f52596a7266 a5dd92f0b24d7dbdaea2daedba3c8d5f700ec7d3ace81ca368600da2ad610082
|
||||
lib/codeql/rust/elements/internal/generated/ContinueExpr.qll e2010feb14fb6edeb83a991d9357e50edb770172ddfde2e8670b0d3e68169f28 48d09d661e1443002f6d22b8710e22c9c36d9daa9cde09c6366a61e960d717cb
|
||||
lib/codeql/rust/elements/internal/generated/Crate.qll 6d28f07d4ddaf077119590a007a8cfad0c86cf0efabbde689fb4092577b883df d43013163916aa83f281314a72d02d7566e1f505aa36cfd8060a760b06b02683
|
||||
lib/codeql/rust/elements/internal/generated/DynTraitTypeRepr.qll a9d540717af1f00dbea1c683fd6b846cddfb2968c7f3e021863276f123337787 1972efb9bca7aae9a9708ca6dcf398e5e8c6d2416a07d525dba1649b80fbe4d1
|
||||
lib/codeql/rust/elements/internal/generated/Element.qll fb483b636180c699181c8aff83bc471b2c416206694f7028c671015918547663 542d1b9ae80c997974c94db3655887186df3921a8fa3f565eaf292dcfdac3c4c
|
||||
lib/codeql/rust/elements/internal/generated/Enum.qll 4f4cbc9cd758c20d476bc767b916c62ba434d1750067d0ffb63e0821bb95ec86 3da735d54022add50cec0217bbf8ec4cf29b47f4851ee327628bcdd6454989d0
|
||||
@@ -574,7 +576,7 @@ lib/codeql/rust/elements/internal/generated/ParamList.qll c808c9d84dd7800573832b
|
||||
lib/codeql/rust/elements/internal/generated/ParenExpr.qll bc0731505bfe88516205ec360582a4222d2681d11342c93e15258590ddee82f2 d4bd6e0c80cf1d63746c88d4bcb3a01d4c75732e5da09e3ebd9437ced227fb60
|
||||
lib/codeql/rust/elements/internal/generated/ParenPat.qll 4f168ef5d5bb87a903251cc31b2e44a759b099ec69c90af31783fbb15778c940 0e34f94a45a13396fd57d94c245dc64d1adde2ab0e22b56946f7e94c04e297fc
|
||||
lib/codeql/rust/elements/internal/generated/ParenTypeRepr.qll 40ab5c592e7699c621787793743e33988de71ff42ca27599f5ab3ddb70e3f7d8 12c0a6eed2202ee3e892f61da3b3ce77ac3190854cdf3097e8d2be98aa3cb91d
|
||||
lib/codeql/rust/elements/internal/generated/ParentChild.qll 2992505ffc3279d58f2d03e89ec0f7d23aedebb3c3baf990bfbda894a6cc10e8 2f6b721e8244b444b47d41c2303fea166debee208544389c4dd9f2be0d62fe43
|
||||
lib/codeql/rust/elements/internal/generated/ParentChild.qll eec4e7672ef5f07752044348d45882f0a849b295dfb17169e910ed0bfca3c162 29a9cc9b2870b1c6240cc53a9a70c4623381219a8f88ea1656b6828d16ef51c7
|
||||
lib/codeql/rust/elements/internal/generated/ParenthesizedArgList.qll c5fa328ea60d3a3333d7c7bb3480969c1873166c7ac8ebb9d0afad7a8099d1a8 2dbbb6200d96f7db7dea4a55bdeab8d67b14d39a43e0bd54ada019f7e466f163
|
||||
lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4
|
||||
lib/codeql/rust/elements/internal/generated/Path.qll 8e47e91aff3f8c60f1ee8cb3887b8e4936c38e4665d052f2c92a939a969aac29 2c28beb89cabd7c7c91a5bc65c874f414cb96bbefde37b25811b61089a8a0053
|
||||
@@ -589,7 +591,7 @@ lib/codeql/rust/elements/internal/generated/PtrTypeRepr.qll 51d1e9e683fc79dddbff
|
||||
lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f
|
||||
lib/codeql/rust/elements/internal/generated/RangeExpr.qll 23cca03bf43535f33b22a38894f70d669787be4e4f5b8fe5c8f7b964d30e9027 18624cef6c6b679eeace2a98737e472432e0ead354cca02192b4d45330f047c9
|
||||
lib/codeql/rust/elements/internal/generated/RangePat.qll 80826a6a6868a803aa2372e31c52a03e1811a3f1f2abdb469f91ca0bfdd9ecb6 34ee1e208c1690cba505dff2c588837c0cd91e185e2a87d1fe673191962276a9
|
||||
lib/codeql/rust/elements/internal/generated/Raw.qll cfbf960b83fc7f659214a48ced60001366410322a116de255678dec9d765d8dd c0d1ee182ccb916dedf33a272fb37ac394e0fac95ef4fadb8a93c7db8d11feb5
|
||||
lib/codeql/rust/elements/internal/generated/Raw.qll 4b60a7c36b770156d3710d811247bc1607c851a926d1546271f166af5b68c01f f65ba77cb2135b4a0d37d8c3e19e49f368426b14c7e48730f3fb9e65f9d7b9c5
|
||||
lib/codeql/rust/elements/internal/generated/RecordExpr.qll 2131b2cb336caa76170082e69776011bf02576bbfdd34ba68ca84af24209250a 39a2e3ec32352b594c43cc1295e0e8b3f9808173322d3d73cb7d48ef969d5565
|
||||
lib/codeql/rust/elements/internal/generated/RecordExprField.qll 7e9f8663d3b74ebbc9603b10c9912f082febba6bd73d344b100bbd3edf837802 fbe6b578e7fd5d5a6f21bbb8c388957ab7210a6a249ec71510a50fb35b319ea1
|
||||
lib/codeql/rust/elements/internal/generated/RecordExprFieldList.qll 179a97211fe7aa6265085d4d54115cdbc0e1cd7c9b2135591e8f36d6432f13d3 dd44bbbc1e83a1ed3a587afb729d7debf7aeb7b63245de181726af13090e50c0
|
||||
@@ -615,8 +617,8 @@ lib/codeql/rust/elements/internal/generated/Static.qll 0b336767104d2b852b9acd234
|
||||
lib/codeql/rust/elements/internal/generated/Stmt.qll 8473ff532dd5cc9d7decaddcd174b94d610f6ca0aec8e473cc051dad9f3db917 6ef7d2b5237c2dbdcacbf7d8b39109d4dc100229f2b28b5c9e3e4fbf673ba72b
|
||||
lib/codeql/rust/elements/internal/generated/StmtList.qll a667193e32341e17400867c6e359878c4e645ef9f5f4d97676afc0283a33a026 a320ed678ee359302e2fc1b70a9476705cd616fcfa44a499d32f0c7715627f73
|
||||
lib/codeql/rust/elements/internal/generated/Struct.qll 4d57f0db12dc7ad3e31e750a24172ef1505406b4dab16386af0674bd18bf8f4b 1a73c83df926b996f629316f74c61ea775be04532ab61b56af904223354f033e
|
||||
lib/codeql/rust/elements/internal/generated/Synth.qll a00cdbb2ba5213976055f2339ae8bb01a42fdae22c355f171aa2ddfbbd7ec200 f49fbdcc7ab69258e3a86039a95d17b069e64922cc6a32a872dc696067b65507
|
||||
lib/codeql/rust/elements/internal/generated/SynthConstructors.qll 0d7929ad8c03e683500c64d1cfff73da518be9836a5d32e44d2f311fb4ae1b96 0d7929ad8c03e683500c64d1cfff73da518be9836a5d32e44d2f311fb4ae1b96
|
||||
lib/codeql/rust/elements/internal/generated/Synth.qll 554d5979ddb7afa42aa4d373cafcffd086e017104130f4a661264ee1c7b54653 059fa863ddab905050e1bbb4669722a14721b40b193bb91f1642da9a36d09018
|
||||
lib/codeql/rust/elements/internal/generated/SynthConstructors.qll f6321ef2a74bb3c869cb3d3fc7753ec90d03bf2c620597f7f1fea636309a3575 f6321ef2a74bb3c869cb3d3fc7753ec90d03bf2c620597f7f1fea636309a3575
|
||||
lib/codeql/rust/elements/internal/generated/Token.qll 77a91a25ca5669703cf3a4353b591cef4d72caa6b0b9db07bb9e005d69c848d1 2fdffc4882ed3a6ca9ac6d1fb5f1ac5a471ca703e2ffdc642885fa558d6e373b
|
||||
lib/codeql/rust/elements/internal/generated/TokenTree.qll 8577c2b097c1be2f0f7daa5acfcf146f78674a424d99563e08a84dd3e6d91b46 d2f30764e84dbfc0a6a5d3d8a5f935cd432413688cb32da9c94e420fbc10665c
|
||||
lib/codeql/rust/elements/internal/generated/Trait.qll 8fa41b50fa0f68333534f2b66bb4ec8e103ff09ac8fa5c2cc64bc04beafec205 ce1c9aa6d0e2f05d28aab8e1165c3b9fb8e24681ade0cf6a9df2e8617abeae7e
|
||||
@@ -652,7 +654,7 @@ lib/codeql/rust/elements/internal/generated/WhileExpr.qll 7edf1f23fbf953a2baabcd
|
||||
lib/codeql/rust/elements/internal/generated/WildcardPat.qll d74b70b57a0a66bfae017a329352a5b27a6b9e73dd5521d627f680e810c6c59e 4b913b548ba27ff3c82fcd32cf996ff329cb57d176d3bebd0fcef394486ea499
|
||||
lib/codeql/rust/elements/internal/generated/YeetExpr.qll cac328200872a35337b4bcb15c851afb4743f82c080f9738d295571eb01d7392 94af734eea08129b587fed849b643e7572800e8330c0b57d727d41abda47930b
|
||||
lib/codeql/rust/elements/internal/generated/YieldExpr.qll 37e5f0c1e373a22bbc53d8b7f2c0e1f476e5be5080b8437c5e964f4e83fad79a 4a9a68643401637bf48e5c2b2f74a6bf0ddcb4ff76f6bffb61d436b685621e85
|
||||
lib/codeql/rust/elements.qll fd66034a77b69f4741ca1488e8d04879da800bfa8d55492747c2b49d71a8067b fd66034a77b69f4741ca1488e8d04879da800bfa8d55492747c2b49d71a8067b
|
||||
lib/codeql/rust/elements.qll 041993d344a4c10b301ac607075254175f1a1f927328de4f40f4df0260d0dece 041993d344a4c10b301ac607075254175f1a1f927328de4f40f4df0260d0dece
|
||||
test/extractor-tests/generated/Abi/Abi.ql 7f6e7dc4af86eca3ebdc79b10373988cd0871bd78b51997d3cffd969105e5fdd 2f936b6ca005c6157c755121584410c03e4a3949c23bee302fbe05ee10ce118f
|
||||
test/extractor-tests/generated/Abi/Abi_getAbiString.ql a496762fcec5a0887b87023bbf93e9b650f02e20113e25c44d6e4281ae8f5335 14109c7ce11ba25e3cd6e7f1b3fcb4cb00622f2a4eac91bfe43145c5f366bc52
|
||||
test/extractor-tests/generated/ArgList/ArgList.ql e412927756e72165d0e7c5c9bd3fca89d08197bbf760db8fb7683c64bb2229bc 043dba8506946fbb87753e22c387987d7eded6ddb963aa067f9e60ef9024d684
|
||||
@@ -750,6 +752,7 @@ test/extractor-tests/generated/ConstParam/ConstParam_getTypeRepr.ql f25a4695e06a
|
||||
test/extractor-tests/generated/ContinueExpr/ContinueExpr.ql 971ccb238aec663855745fa2669d5f8973a4e6c76bacdf0deaf23522ec1cf80c 4e3ceb4c4cd833ad8311bb02e5cda18163082e341cd8a3def60734a53cca8929
|
||||
test/extractor-tests/generated/ContinueExpr/ContinueExpr_getAttr.ql acb261869d3b3c65e364e7b6fbd7afdf5305806d4417b05044beed9a81e66ea4 af35ce0aee87ddc7a0cd34be4a480c619940d036d5cecce0e4e1fcd75b7c553e
|
||||
test/extractor-tests/generated/ContinueExpr/ContinueExpr_getLifetime.ql 39dae9872d92fa9b15343c93da545c2b0e15b4f27f2296c200fd4611b68858d5 52a209022e3b83260b4ef5513ffbcc1ca1f7c21bad2c721a0d3698793d2161d2
|
||||
test/extractor-tests/generated/Crate/MISSING_SOURCE.txt b6cf5771fdbbe981aeb3f443ec7a40517b6e99ffc9817fd8872c2e344240dae1 b6cf5771fdbbe981aeb3f443ec7a40517b6e99ffc9817fd8872c2e344240dae1
|
||||
test/extractor-tests/generated/DynTraitTypeRepr/DynTraitTypeRepr.ql 513d64b564f359e1022ae6f3d6d4a8ad637f595f01f29a6c2a167d1c2e8f1f99 0c7a7af6ee1005126b9ab77b2a7732821f85f1d2d426312c98206cbbedc19bb2
|
||||
test/extractor-tests/generated/DynTraitTypeRepr/DynTraitTypeRepr_getTypeBoundList.ql b20720ff0b147d55cea6f2de44d5bf297e79991eaf103938ccd7ab9d129e9656 eb8c9db2581cea00c29d7772de0b0a125be02c37092217a419f1a2b6a9711a6c
|
||||
test/extractor-tests/generated/Enum/Enum.ql ed518d828d8e2e4790849284de1d0d5e728dbc2fe5e9f187e8ebfa2d503efd5a 7092b963eb133371e1cbc09d45f8c2308d7093523140b351d67073a8d258643e
|
||||
|
||||
5
rust/ql/.gitattributes
generated
vendored
5
rust/ql/.gitattributes
generated
vendored
@@ -45,6 +45,7 @@
|
||||
/lib/codeql/rust/elements/ConstBlockPat.qll linguist-generated
|
||||
/lib/codeql/rust/elements/ConstParam.qll linguist-generated
|
||||
/lib/codeql/rust/elements/ContinueExpr.qll linguist-generated
|
||||
/lib/codeql/rust/elements/Crate.qll linguist-generated
|
||||
/lib/codeql/rust/elements/DynTraitTypeRepr.qll linguist-generated
|
||||
/lib/codeql/rust/elements/Element.qll linguist-generated
|
||||
/lib/codeql/rust/elements/Enum.qll linguist-generated
|
||||
@@ -256,6 +257,7 @@
|
||||
/lib/codeql/rust/elements/internal/ConstParamConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/ConstParamImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/ContinueExprConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/CrateConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/DynTraitTypeReprConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/DynTraitTypeReprImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/EnumConstructor.qll linguist-generated
|
||||
@@ -286,7 +288,6 @@
|
||||
/lib/codeql/rust/elements/internal/GenericArgListConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/GenericParamImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/GenericParamListConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/GenericParamListImpl.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/IdentPatConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/IfExprConstructor.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/ImplConstructor.qll linguist-generated
|
||||
@@ -503,6 +504,7 @@
|
||||
/lib/codeql/rust/elements/internal/generated/ConstBlockPat.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/generated/ConstParam.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/generated/ContinueExpr.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/generated/Crate.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/generated/DynTraitTypeRepr.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/generated/Element.qll linguist-generated
|
||||
/lib/codeql/rust/elements/internal/generated/Enum.qll linguist-generated
|
||||
@@ -752,6 +754,7 @@
|
||||
/test/extractor-tests/generated/ContinueExpr/ContinueExpr.ql linguist-generated
|
||||
/test/extractor-tests/generated/ContinueExpr/ContinueExpr_getAttr.ql linguist-generated
|
||||
/test/extractor-tests/generated/ContinueExpr/ContinueExpr_getLifetime.ql linguist-generated
|
||||
/test/extractor-tests/generated/Crate/MISSING_SOURCE.txt linguist-generated
|
||||
/test/extractor-tests/generated/DynTraitTypeRepr/DynTraitTypeRepr.ql linguist-generated
|
||||
/test/extractor-tests/generated/DynTraitTypeRepr/DynTraitTypeRepr_getTypeBoundList.ql linguist-generated
|
||||
/test/extractor-tests/generated/Enum/Enum.ql linguist-generated
|
||||
|
||||
8
rust/ql/consistency-queries/PathResolutionConsistency.ql
Normal file
8
rust/ql/consistency-queries/PathResolutionConsistency.ql
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* @name Path resolution inconsistencies
|
||||
* @description Lists the path resolution inconsistencies in the database. This query is intended for internal use.
|
||||
* @kind table
|
||||
* @id rust/diagnostics/path-resolution-consistency
|
||||
*/
|
||||
|
||||
import codeql.rust.internal.PathResolutionConsistency
|
||||
8
rust/ql/consistency-queries/TypeInferenceConsistency.ql
Normal file
8
rust/ql/consistency-queries/TypeInferenceConsistency.ql
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* @name Type inference inconsistencies
|
||||
* @description Lists the type inference inconsistencies in the database. This query is intended for internal use.
|
||||
* @kind table
|
||||
* @id rust/diagnostics/type-inference-consistency
|
||||
*/
|
||||
|
||||
import codeql.rust.internal.TypeInferenceConsistency
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"attributes": {
|
||||
"durations": {
|
||||
"crateGraph": {
|
||||
"ms": "__REDACTED__",
|
||||
"pretty": "__REDACTED__"
|
||||
},
|
||||
"extract": {
|
||||
"ms": "__REDACTED__",
|
||||
"pretty": "__REDACTED__"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import rust
|
||||
|
||||
from Function f
|
||||
where exists(f.getLocation().getFile().getRelativePath())
|
||||
where f.fromSource()
|
||||
select f
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
| Cargo.toml:0:0:0:0 | LoadManifest(Cargo.toml) |
|
||||
| file://:0:0:0:0 | CrateGraph |
|
||||
| file://:0:0:0:0 | FindManifests |
|
||||
| src/directory_module/mod.rs:0:0:0:0 | Extract(src/directory_module/mod.rs) |
|
||||
| src/directory_module/mod.rs:0:0:0:0 | LoadSource(src/directory_module/mod.rs) |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
| file://:0:0:0:0 | CrateGraph |
|
||||
| file://:0:0:0:0 | FindManifests |
|
||||
| rust-project.json:0:0:0:0 | LoadManifest(rust-project.json) |
|
||||
| src/directory_module/mod.rs:0:0:0:0 | Extract(src/directory_module/mod.rs) |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| Elements extracted | 66 |
|
||||
| Elements extracted | 67 |
|
||||
| Elements unextracted | 0 |
|
||||
| Extraction errors | 0 |
|
||||
| Extraction warnings | 1 |
|
||||
@@ -8,6 +8,7 @@
|
||||
| Files extracted - without errors % | 80 |
|
||||
| Inconsistencies - AST | 0 |
|
||||
| Inconsistencies - CFG | 0 |
|
||||
| Inconsistencies - Path resolution | 0 |
|
||||
| Inconsistencies - data flow | 0 |
|
||||
| Lines of code extracted | 6 |
|
||||
| Lines of user code extracted | 6 |
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"attributes": {
|
||||
"durations": {
|
||||
"crateGraph": {
|
||||
"ms": "__REDACTED__",
|
||||
"pretty": "__REDACTED__"
|
||||
},
|
||||
"extract": {
|
||||
"ms": "__REDACTED__",
|
||||
"pretty": "__REDACTED__"
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"attributes": {
|
||||
"durations": {
|
||||
"crateGraph": {
|
||||
"ms": "__REDACTED__",
|
||||
"pretty": "__REDACTED__"
|
||||
},
|
||||
"extract": {
|
||||
"ms": "__REDACTED__",
|
||||
"pretty": "__REDACTED__"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import rust
|
||||
|
||||
from Function f
|
||||
where exists(f.getLocation().getFile().getRelativePath())
|
||||
where f.fromSource()
|
||||
select f
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
| exe/src/main.rs:0:0:0:0 | Extract(exe/src/main.rs) |
|
||||
| exe/src/main.rs:0:0:0:0 | LoadSource(exe/src/main.rs) |
|
||||
| exe/src/main.rs:0:0:0:0 | Parse(exe/src/main.rs) |
|
||||
| file://:0:0:0:0 | CrateGraph |
|
||||
| file://:0:0:0:0 | FindManifests |
|
||||
| lib/src/a_module/mod.rs:0:0:0:0 | Extract(lib/src/a_module/mod.rs) |
|
||||
| lib/src/a_module/mod.rs:0:0:0:0 | LoadSource(lib/src/a_module/mod.rs) |
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
| exe/src/main.rs:0:0:0:0 | Extract(exe/src/main.rs) |
|
||||
| exe/src/main.rs:0:0:0:0 | LoadSource(exe/src/main.rs) |
|
||||
| exe/src/main.rs:0:0:0:0 | Parse(exe/src/main.rs) |
|
||||
| file://:0:0:0:0 | CrateGraph |
|
||||
| file://:0:0:0:0 | FindManifests |
|
||||
| lib/src/a_module/mod.rs:0:0:0:0 | Extract(lib/src/a_module/mod.rs) |
|
||||
| lib/src/a_module/mod.rs:0:0:0:0 | LoadSource(lib/src/a_module/mod.rs) |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| Elements extracted | 86 |
|
||||
| Elements extracted | 87 |
|
||||
| Elements unextracted | 0 |
|
||||
| Extraction errors | 0 |
|
||||
| Extraction warnings | 0 |
|
||||
@@ -8,6 +8,7 @@
|
||||
| Files extracted - without errors % | 100 |
|
||||
| Inconsistencies - AST | 0 |
|
||||
| Inconsistencies - CFG | 0 |
|
||||
| Inconsistencies - Path resolution | 0 |
|
||||
| Inconsistencies - data flow | 0 |
|
||||
| Lines of code extracted | 9 |
|
||||
| Lines of user code extracted | 9 |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| Elements extracted | 86 |
|
||||
| Elements extracted | 87 |
|
||||
| Elements unextracted | 0 |
|
||||
| Extraction errors | 0 |
|
||||
| Extraction warnings | 0 |
|
||||
@@ -8,6 +8,7 @@
|
||||
| Files extracted - without errors % | 100 |
|
||||
| Inconsistencies - AST | 0 |
|
||||
| Inconsistencies - CFG | 0 |
|
||||
| Inconsistencies - Path resolution | 0 |
|
||||
| Inconsistencies - data flow | 0 |
|
||||
| Lines of code extracted | 9 |
|
||||
| Lines of user code extracted | 9 |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import rust
|
||||
|
||||
from Function f
|
||||
where f.fromSource()
|
||||
select f
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import rust
|
||||
|
||||
from Function f
|
||||
where f.fromSource()
|
||||
select f
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import rust
|
||||
|
||||
from Function f
|
||||
where f.fromSource()
|
||||
select f
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import rust
|
||||
|
||||
from Function f
|
||||
where exists(f.getLocation().getFile().getRelativePath())
|
||||
where f.fromSource()
|
||||
select f
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import rust
|
||||
|
||||
from Function f
|
||||
where exists(f.getLocation().getFile().getRelativePath())
|
||||
where f.fromSource()
|
||||
select f
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import rust
|
||||
|
||||
from Function f
|
||||
where exists(f.getLocation().getFile().getRelativePath())
|
||||
where f.fromSource()
|
||||
select f
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import rust
|
||||
|
||||
from Function f
|
||||
where exists(f.getLocation().getFile().getRelativePath())
|
||||
where f.fromSource()
|
||||
select f
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
| Cargo.toml:0:0:0:0 | LoadManifest(Cargo.toml) |
|
||||
| exe/src/main.rs:0:0:0:0 | Extract(exe/src/main.rs) |
|
||||
| exe/src/main.rs:0:0:0:0 | Parse(exe/src/main.rs) |
|
||||
| file://:0:0:0:0 | CrateGraph |
|
||||
| file://:0:0:0:0 | FindManifests |
|
||||
| lib/src/lib.rs:0:0:0:0 | Extract(lib/src/lib.rs) |
|
||||
| lib/src/lib.rs:0:0:0:0 | Parse(lib/src/lib.rs) |
|
||||
|
||||
@@ -55,7 +55,8 @@ class File extends Container, Impl::File {
|
||||
|
|
||||
node.getFile() = this and
|
||||
line = [/*loc.getStartLine(), */ loc.getEndLine()] and // ignore start locations for now as we're getting them wrong for things with a comment attached
|
||||
not loc instanceof EmptyLocation
|
||||
not loc instanceof EmptyLocation and
|
||||
line > 0
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -152,6 +152,29 @@ class ModeledRemoteSource extends RemoteSource::Range {
|
||||
ModeledRemoteSource() { sourceNode(this, "remote") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow sink that is used in a query.
|
||||
*
|
||||
* Extend this class to refine existing API models. If you want to model new APIs,
|
||||
* extend `QuerySink::Range` instead.
|
||||
*/
|
||||
final class QuerySink = QuerySink::Range;
|
||||
|
||||
/**
|
||||
* Provides a class for modeling new query sinks.
|
||||
*/
|
||||
module QuerySink {
|
||||
/**
|
||||
* A data flow sink that is used in a query.
|
||||
*/
|
||||
abstract class Range extends DataFlow::Node {
|
||||
/**
|
||||
* Gets a string that describes the type of this sink (usually the query it applies to).
|
||||
*/
|
||||
abstract string getSinkType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node that constructs a SQL statement (for later execution).
|
||||
*
|
||||
|
||||
@@ -239,9 +239,8 @@ final class RecordExprCfgNode extends Nodes::RecordExprCfgNode {
|
||||
pragma[nomagic]
|
||||
ExprCfgNode getFieldExpr(string field) {
|
||||
exists(RecordExprField ref |
|
||||
ref = node.getRecordExprFieldList().getAField() and
|
||||
any(ChildMapping mapping).hasCfgChild(node, ref.getExpr(), this, result) and
|
||||
field = ref.getFieldName()
|
||||
ref = node.getFieldExpr(field) and
|
||||
any(ChildMapping mapping).hasCfgChild(node, ref.getExpr(), this, result)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
/** Provides classes and predicates for defining flow sinks. */
|
||||
/**
|
||||
* Provides classes and predicates for defining flow sinks.
|
||||
*
|
||||
* Flow sinks defined here feed into data flow configurations as follows:
|
||||
*
|
||||
* ```text
|
||||
* data from *.model.yml | QL extensions of FlowSink::Range
|
||||
* v v
|
||||
* FlowSink (associated with a models-as-data kind string)
|
||||
* v
|
||||
* sinkNode predicate | other QL defined sinks, for example using concepts
|
||||
* v v
|
||||
* various Sink classes for specific data flow configurations <- extending QuerySink
|
||||
* ```
|
||||
*
|
||||
* New sinks should be defined using models-as-data, QL extensions of
|
||||
* `FlowSink::Range`, or concepts. Data flow configurations should use the
|
||||
* `sinkNode` predicate and/or concepts to define their sinks.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import internal.FlowSummaryImpl as Impl
|
||||
@@ -12,7 +30,7 @@ private module Sinks {
|
||||
|
||||
/** Provides the `Range` class used to define the extent of `FlowSink`. */
|
||||
module FlowSink {
|
||||
/** A flow source. */
|
||||
/** A flow sink. */
|
||||
abstract class Range extends Impl::Public::SinkElement {
|
||||
bindingset[this]
|
||||
Range() { any() }
|
||||
|
||||
@@ -1,4 +1,28 @@
|
||||
/** Provides classes and predicates for defining flow sources. */
|
||||
/**
|
||||
* Provides classes and predicates for defining flow sources.
|
||||
*
|
||||
* Flow sources defined here feed into the `ActiveThreatModelSource` class and
|
||||
* ultimately reach data flow configurations as follows:
|
||||
*
|
||||
* ```text
|
||||
* data from *.model.yml | QL extensions of FlowSource::Range
|
||||
* v v
|
||||
* FlowSource (associated with a models-as-data kind string)
|
||||
* v
|
||||
* sourceNode predicate | (theoretically other QL defined sources)
|
||||
* v v
|
||||
* ThreatModelSource (associated with a threat model source type)
|
||||
* v
|
||||
* ActiveThreatModelSource (just the enabled sources)
|
||||
* v
|
||||
* various Source classes for specific data flow configurations
|
||||
* ```
|
||||
*
|
||||
* New sources should be defined using models-as-data or QL extensions of
|
||||
* `FlowSource::Range`. Data flow configurations on the other hand should use
|
||||
* `ActiveThreatModelSource` to match sources enabled in the user
|
||||
* configuration.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import internal.FlowSummaryImpl as Impl
|
||||
|
||||
@@ -10,7 +10,7 @@ private import codeql.dataflow.internal.DataFlowImpl
|
||||
private import rust
|
||||
private import SsaImpl as SsaImpl
|
||||
private import codeql.rust.controlflow.internal.Scope as Scope
|
||||
private import codeql.rust.elements.internal.PathResolution
|
||||
private import codeql.rust.internal.PathResolution
|
||||
private import codeql.rust.controlflow.ControlFlowGraph
|
||||
private import codeql.rust.controlflow.CfgNodes
|
||||
private import codeql.rust.dataflow.Ssa
|
||||
@@ -847,7 +847,7 @@ class TupleFieldContent extends FieldContent, TTupleFieldContent {
|
||||
|
||||
predicate isStructField(Struct s, int pos) { field.isStructField(s, pos) }
|
||||
|
||||
override FieldExprCfgNode getAnAccess() { none() } // TODO
|
||||
override FieldExprCfgNode getAnAccess() { field = result.getFieldExpr().getTupleField() }
|
||||
|
||||
final override string toString() {
|
||||
exists(Variant v, int pos, string vname |
|
||||
@@ -878,7 +878,7 @@ class RecordFieldContent extends FieldContent, TRecordFieldContent {
|
||||
|
||||
predicate isStructField(Struct s, string name) { field.isStructField(s, name) }
|
||||
|
||||
override FieldExprCfgNode getAnAccess() { none() } // TODO
|
||||
override FieldExprCfgNode getAnAccess() { field = result.getFieldExpr().getRecordField() }
|
||||
|
||||
final override string toString() {
|
||||
exists(Variant v, string name, string vname |
|
||||
|
||||
1
rust/ql/lib/codeql/rust/elements.qll
generated
1
rust/ql/lib/codeql/rust/elements.qll
generated
@@ -48,6 +48,7 @@ import codeql.rust.elements.ConstArg
|
||||
import codeql.rust.elements.ConstBlockPat
|
||||
import codeql.rust.elements.ConstParam
|
||||
import codeql.rust.elements.ContinueExpr
|
||||
import codeql.rust.elements.Crate
|
||||
import codeql.rust.elements.DynTraitTypeRepr
|
||||
import codeql.rust.elements.Element
|
||||
import codeql.rust.elements.Enum
|
||||
|
||||
10
rust/ql/lib/codeql/rust/elements/Crate.qll
generated
Normal file
10
rust/ql/lib/codeql/rust/elements/Crate.qll
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
// generated by codegen, do not edit
|
||||
/**
|
||||
* This module provides the public class `Crate`.
|
||||
*/
|
||||
|
||||
private import internal.CrateImpl
|
||||
import codeql.rust.elements.Element
|
||||
import codeql.rust.elements.Module
|
||||
|
||||
final class Crate = Impl::Crate;
|
||||
@@ -12,11 +12,7 @@ private import codeql.rust.elements.Resolvable
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
private import codeql.rust.elements.internal.CallableImpl::Impl
|
||||
private import codeql.rust.elements.internal.MethodCallExprImpl::Impl
|
||||
private import codeql.rust.elements.internal.CallExprImpl::Impl
|
||||
private import codeql.rust.elements.internal.PathExprImpl::Impl
|
||||
private import codeql.rust.elements.internal.PathResolution
|
||||
private import rust
|
||||
|
||||
pragma[nomagic]
|
||||
Resolvable getCallResolvable(CallExprBase call) {
|
||||
@@ -30,14 +26,7 @@ module Impl {
|
||||
* A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details.
|
||||
*/
|
||||
class CallExprBase extends Generated::CallExprBase {
|
||||
/**
|
||||
* Gets the target callable of this call, if a unique such target can
|
||||
* be statically resolved.
|
||||
*/
|
||||
Callable getStaticTarget() {
|
||||
getCallResolvable(this).resolvesAsItem(result)
|
||||
or
|
||||
result = resolvePath(this.(CallExpr).getFunction().(PathExpr).getPath())
|
||||
}
|
||||
/** Gets the static target of this call, if any. */
|
||||
Callable getStaticTarget() { none() } // overridden by subclasses, but cannot be made abstract
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,15 @@ private import codeql.rust.elements.PathExpr
|
||||
*/
|
||||
module Impl {
|
||||
private import rust
|
||||
private import PathResolution as PathResolution
|
||||
private import codeql.rust.internal.PathResolution as PathResolution
|
||||
|
||||
pragma[nomagic]
|
||||
Path getFunctionPath(CallExpr ce) { result = ce.getFunction().(PathExpr).getPath() }
|
||||
|
||||
pragma[nomagic]
|
||||
PathResolution::ItemNode getResolvedFunction(CallExpr ce) {
|
||||
result = PathResolution::resolvePath(getFunctionPath(ce))
|
||||
}
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
@@ -28,9 +36,17 @@ module Impl {
|
||||
class CallExpr extends Generated::CallExpr {
|
||||
override string toString() { result = this.getFunction().toAbbreviatedString() + "(...)" }
|
||||
|
||||
override Callable getStaticTarget() { result = getResolvedFunction(this) }
|
||||
|
||||
/** Gets the struct that this call resolves to, if any. */
|
||||
Struct getStruct() { result = getResolvedFunction(this) }
|
||||
|
||||
/** Gets the variant that this call resolves to, if any. */
|
||||
Variant getVariant() { result = getResolvedFunction(this) }
|
||||
|
||||
pragma[nomagic]
|
||||
private PathResolution::ItemNode getResolvedFunction(int pos) {
|
||||
result = PathResolution::resolvePath(this.getFunction().(PathExpr).getPath()) and
|
||||
private PathResolution::ItemNode getResolvedFunctionAndPos(int pos) {
|
||||
result = getResolvedFunction(this) and
|
||||
exists(this.getArgList().getArg(pos))
|
||||
}
|
||||
|
||||
@@ -42,7 +58,7 @@ module Impl {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
TupleField getTupleField(int pos) {
|
||||
exists(PathResolution::ItemNode i | i = this.getResolvedFunction(pos) |
|
||||
exists(PathResolution::ItemNode i | i = this.getResolvedFunctionAndPos(pos) |
|
||||
result.isStructField(i, pos) or
|
||||
result.isVariantField(i, pos)
|
||||
)
|
||||
|
||||
14
rust/ql/lib/codeql/rust/elements/internal/CrateConstructor.qll
generated
Normal file
14
rust/ql/lib/codeql/rust/elements/internal/CrateConstructor.qll
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
// generated by codegen, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module defines the hook used internally to tweak the characteristic predicate of
|
||||
* `Crate` synthesized instances.
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
|
||||
private import codeql.rust.elements.internal.generated.Raw
|
||||
|
||||
/**
|
||||
* The characteristic predicate of `Crate` synthesized instances.
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
predicate constructCrate(Raw::Crate id) { any() }
|
||||
29
rust/ql/lib/codeql/rust/elements/internal/CrateImpl.qll
Normal file
29
rust/ql/lib/codeql/rust/elements/internal/CrateImpl.qll
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `Crate`.
|
||||
*
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
|
||||
private import codeql.rust.elements.internal.generated.Crate
|
||||
|
||||
/**
|
||||
* INTERNAL: This module contains the customizable definition of `Crate` and should not
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
class Crate extends Generated::Crate {
|
||||
override string toString() { result = strictconcat(int i | | this.toStringPart(i) order by i) }
|
||||
|
||||
private string toStringPart(int i) {
|
||||
i = 0 and result = "Crate("
|
||||
or
|
||||
i = 1 and result = this.getName()
|
||||
or
|
||||
i = 2 and result = "@"
|
||||
or
|
||||
i = 3 and result = this.getVersion()
|
||||
or
|
||||
i = 4 and result = ")"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,9 @@ private import codeql.rust.elements.internal.generated.FieldExpr
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
private import rust
|
||||
private import codeql.rust.internal.TypeInference as TypeInference
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* A field access expression. For example:
|
||||
@@ -19,6 +22,12 @@ module Impl {
|
||||
* ```
|
||||
*/
|
||||
class FieldExpr extends Generated::FieldExpr {
|
||||
/** Gets the record field that this access references, if any. */
|
||||
RecordField getRecordField() { result = TypeInference::resolveRecordFieldExpr(this) }
|
||||
|
||||
/** Gets the tuple field that this access references, if any. */
|
||||
TupleField getTupleField() { result = TypeInference::resolveTupleFieldExpr(this) }
|
||||
|
||||
override string toString() {
|
||||
exists(string abbr, string name |
|
||||
abbr = this.getExpr().toAbbreviatedString() and
|
||||
|
||||
@@ -11,6 +11,8 @@ private import codeql.rust.elements.internal.generated.GenericArgList
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
private import rust
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* The base class for generic arguments.
|
||||
@@ -22,5 +24,18 @@ module Impl {
|
||||
override string toString() { result = this.toAbbreviatedString() }
|
||||
|
||||
override string toAbbreviatedString() { result = "<...>" }
|
||||
|
||||
/** Gets the `i`th type argument of this list. */
|
||||
TypeRepr getTypeArg(int i) {
|
||||
result =
|
||||
rank[i + 1](TypeRepr res, int j |
|
||||
res = this.getGenericArg(j).(TypeArg).getTypeRepr()
|
||||
|
|
||||
res order by j
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a type argument of this list. */
|
||||
TypeRepr getATypeArg() { result = this.getTypeArg(_) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// generated by codegen, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `GenericParamList`.
|
||||
*
|
||||
@@ -12,11 +11,26 @@ private import codeql.rust.elements.internal.generated.GenericParamList
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
private import rust
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* A GenericParamList. For example:
|
||||
* ```rust
|
||||
* todo!()
|
||||
* ```
|
||||
*/
|
||||
class GenericParamList extends Generated::GenericParamList { }
|
||||
class GenericParamList extends Generated::GenericParamList {
|
||||
override string toString() { result = this.toAbbreviatedString() }
|
||||
|
||||
override string toAbbreviatedString() { result = "<...>" }
|
||||
|
||||
/** Gets the `i`th type parameter of this list. */
|
||||
TypeParam getTypeParam(int i) {
|
||||
result = rank[i + 1](TypeParam res, int j | res = this.getGenericParam(j) | res order by j)
|
||||
}
|
||||
|
||||
/** Gets a type parameter of this list. */
|
||||
TypeParam getATypeParam() { result = this.getTypeParam(_) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,9 @@ module Impl {
|
||||
* Gets the primary file where this element occurs.
|
||||
*/
|
||||
File getFile() { result = this.getLocation().getFile() }
|
||||
|
||||
/** Holds if this element is from source code. */
|
||||
predicate fromSource() { exists(this.getFile().getRelativePath()) }
|
||||
}
|
||||
|
||||
/** Gets the non-synthesized location of `l`, if any. */
|
||||
|
||||
@@ -4,13 +4,18 @@
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import codeql.rust.elements.internal.generated.MethodCallExpr
|
||||
private import codeql.rust.internal.PathResolution
|
||||
private import codeql.rust.internal.TypeInference
|
||||
|
||||
/**
|
||||
* INTERNAL: This module contains the customizable definition of `MethodCallExpr` and should not
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Impl {
|
||||
private predicate isImplFunction(Function f) { f = any(ImplItemNode impl).getAnAssocItem() }
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* A method call expression. For example:
|
||||
@@ -20,6 +25,23 @@ module Impl {
|
||||
* ```
|
||||
*/
|
||||
class MethodCallExpr extends Generated::MethodCallExpr {
|
||||
override Function getStaticTarget() {
|
||||
result = resolveMethodCallExpr(this) and
|
||||
(
|
||||
// prioritize `impl` methods first
|
||||
isImplFunction(result)
|
||||
or
|
||||
not isImplFunction(resolveMethodCallExpr(this)) and
|
||||
(
|
||||
// then trait methods with default implementations
|
||||
result.hasBody()
|
||||
or
|
||||
// and finally trait methods without default implementations
|
||||
not resolveMethodCallExpr(this).hasBody()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
exists(string base, string separator |
|
||||
base = this.getReceiver().toAbbreviatedString() and
|
||||
|
||||
@@ -12,7 +12,7 @@ private import codeql.rust.elements.internal.generated.RecordExpr
|
||||
*/
|
||||
module Impl {
|
||||
private import rust
|
||||
private import PathResolution as PathResolution
|
||||
private import codeql.rust.internal.PathResolution as PathResolution
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
@@ -27,13 +27,23 @@ module Impl {
|
||||
class RecordExpr extends Generated::RecordExpr {
|
||||
override string toString() { result = this.getPath().toString() + " {...}" }
|
||||
|
||||
/** Gets the record expression for the field `name`. */
|
||||
pragma[nomagic]
|
||||
RecordExprField getFieldExpr(string name) {
|
||||
result = this.getRecordExprFieldList().getAField() and
|
||||
name = result.getFieldName()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PathResolution::ItemNode getResolvedPath(string name) {
|
||||
result = PathResolution::resolvePath(this.getPath()) and
|
||||
exists(this.getFieldExpr(name))
|
||||
}
|
||||
|
||||
/** Gets the record field that matches the `name` field of this record expression. */
|
||||
pragma[nomagic]
|
||||
RecordField getRecordField(string name) {
|
||||
exists(PathResolution::ItemNode i |
|
||||
i = PathResolution::resolvePath(this.getPath()) and
|
||||
name = this.getRecordExprFieldList().getAField().getFieldName()
|
||||
|
|
||||
exists(PathResolution::ItemNode i | i = this.getResolvedPath(name) |
|
||||
result.isStructField(i, name) or
|
||||
result.isVariantField(i, name)
|
||||
)
|
||||
|
||||
@@ -12,7 +12,7 @@ private import codeql.rust.elements.internal.generated.RecordPat
|
||||
*/
|
||||
module Impl {
|
||||
private import rust
|
||||
private import PathResolution as PathResolution
|
||||
private import codeql.rust.internal.PathResolution as PathResolution
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
@@ -27,13 +27,16 @@ module Impl {
|
||||
class RecordPat extends Generated::RecordPat {
|
||||
override string toString() { result = this.getPath().toAbbreviatedString() + " {...}" }
|
||||
|
||||
pragma[nomagic]
|
||||
private PathResolution::ItemNode getResolvedPath(string name) {
|
||||
result = PathResolution::resolvePath(this.getPath()) and
|
||||
name = this.getRecordPatFieldList().getAField().getFieldName()
|
||||
}
|
||||
|
||||
/** Gets the record field that matches the `name` pattern of this pattern. */
|
||||
pragma[nomagic]
|
||||
RecordField getRecordField(string name) {
|
||||
exists(PathResolution::ItemNode i |
|
||||
i = PathResolution::resolvePath(this.getPath()) and
|
||||
name = this.getRecordPatFieldList().getAField().getFieldName()
|
||||
|
|
||||
exists(PathResolution::ItemNode i | i = this.getResolvedPath(name) |
|
||||
result.isStructField(i, name) or
|
||||
result.isVariantField(i, name)
|
||||
)
|
||||
|
||||
@@ -32,5 +32,17 @@ module Impl {
|
||||
/** Gets the `i`th tuple field, if any. */
|
||||
pragma[nomagic]
|
||||
TupleField getTupleField(int i) { result = this.getFieldList().(TupleFieldList).getField(i) }
|
||||
|
||||
/** Holds if this struct uses tuple fields. */
|
||||
pragma[nomagic]
|
||||
predicate isTuple() { this.getFieldList() instanceof TupleFieldList }
|
||||
|
||||
/**
|
||||
* Holds if this struct uses record fields.
|
||||
*
|
||||
* Empty structs are considered to use record fields.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate isRecord() { not this.isTuple() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ private import codeql.rust.elements.internal.generated.TupleStructPat
|
||||
*/
|
||||
module Impl {
|
||||
private import rust
|
||||
private import PathResolution as PathResolution
|
||||
private import codeql.rust.internal.PathResolution as PathResolution
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user