Merge branch 'main' into rust-cleartext-transmission

This commit is contained in:
Simon Friis Vindum
2025-03-13 15:01:11 +01:00
107 changed files with 2413 additions and 216 deletions

2
Cargo.lock generated
View File

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

View File

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

View File

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

View File

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

View File

@@ -119,9 +119,14 @@ class ConstantMatchingCondition extends ConstantCondition {
}
override predicate isWhiteListed() {
exists(SwitchExpr se, int i |
se.getCase(i).getPattern() = this.(DiscardExpr) and
exists(Switch se, Case c, int i |
c = se.getCase(i) and
c.getPattern() = this.(DiscardExpr)
|
i > 0
or
i = 0 and
exists(Expr cond | c.getCondition() = cond and not isConstantCondition(cond, true))
)
or
this = any(PositionalPatternExpr ppe).getPattern(_)

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Increase query precision for `cs/constant-condition` and allow the use of discards in switch/case statements and also take the condition (if any) into account.

View File

@@ -9,3 +9,4 @@
- cs/inefficient-containskey
- cs/call-to-object-tostring
- cs/local-not-disposed
- cs/constant-condition

View File

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

View File

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

View File

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

View File

@@ -1 +1,2 @@
API Abuse/NoDisposeCallOnLocalIDisposable.ql
query: API Abuse/NoDisposeCallOnLocalIDisposable.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

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

View File

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

View File

@@ -35,18 +35,18 @@ class ConstantNullness
{
void M1(int i)
{
var j = ((string)null)?.Length; // BAD
var s = ((int?)i)?.ToString(); // BAD
var j = ((string)null)?.Length; // $ Alert
var s = ((int?)i)?.ToString(); // $ Alert
var k = s?.Length; // GOOD
k = s?.ToLower()?.Length; // GOOD
}
void M2(int i)
{
var j = (int?)null ?? 0; // BAD
var s = "" ?? "a"; // BAD
j = (int?)i ?? 1; // BAD
s = ""?.CommaJoinWith(s); // BAD
var j = (int?)null ?? 0; // $ Alert
var s = "" ?? "a"; // $ Alert
j = (int?)i ?? 1; // $ Alert
s = ""?.CommaJoinWith(s); // $ Alert
s = s ?? ""; // GOOD
s = (i == 0 ? s : null) ?? s; // GOOD
var k = (i == 0 ? s : null)?.Length; // GOOD
@@ -59,9 +59,9 @@ class ConstantMatching
{
switch (1 + 2)
{
case 2: // BAD
case 2: // $ Alert
break;
case 3: // BAD
case 3: // $ Alert
break;
case int _: // GOOD
break;
@@ -72,7 +72,7 @@ class ConstantMatching
{
switch ((object)s)
{
case int _: // BAD
case int _: // $ Alert
break;
case "": // GOOD
break;
@@ -92,7 +92,7 @@ class ConstantMatching
{
return o switch
{
_ => o.ToString() // BAD
_ => o.ToString() // $ Alert
};
}
@@ -111,7 +111,7 @@ class ConstantMatching
return;
if (!b2)
return;
if (b1 && b2) // BAD
if (b1 && b2) // $ Alert
return;
}
@@ -124,6 +124,35 @@ class ConstantMatching
_ => "" // GOOD
};
}
string M8(int i)
{
return i switch
{
_ when i % 2 == 0 => "even", // GOOD
_ => "odd" // GOOD
};
}
string M9(int i)
{
switch (i)
{
case var _: // $ Alert
return "even";
}
}
string M10(int i)
{
switch (i)
{
case var _ when i % 2 == 0: // GOOD
return "even";
case var _: // GOOD
return "odd";
}
}
}
class Assertions

View File

@@ -10,7 +10,7 @@
| ConstantCondition.cs:95:13:95:13 | _ | Pattern always matches. |
| ConstantCondition.cs:114:13:114:14 | access to parameter b1 | Condition always evaluates to 'true'. |
| ConstantCondition.cs:114:19:114:20 | access to parameter b2 | Condition always evaluates to 'true'. |
| ConstantConditionBad.cs:5:16:5:20 | ... > ... | Condition always evaluates to 'false'. |
| ConstantCondition.cs:141:22:141:22 | _ | Pattern always matches. |
| ConstantConditionalExpressionCondition.cs:11:22:11:34 | ... == ... | Condition always evaluates to 'true'. |
| ConstantConditionalExpressionCondition.cs:12:21:12:25 | false | Condition always evaluates to 'false'. |
| ConstantConditionalExpressionCondition.cs:13:21:13:30 | ... == ... | Condition always evaluates to 'true'. |
@@ -19,6 +19,7 @@
| ConstantIfCondition.cs:11:17:11:29 | ... == ... | Condition always evaluates to 'true'. |
| ConstantIfCondition.cs:14:17:14:21 | false | Condition always evaluates to 'false'. |
| ConstantIfCondition.cs:17:17:17:26 | ... == ... | Condition always evaluates to 'true'. |
| ConstantIfCondition.cs:30:20:30:24 | ... > ... | Condition always evaluates to 'false'. |
| ConstantIsNullOrEmpty.cs:10:21:10:54 | call to method IsNullOrEmpty | Condition always evaluates to 'false'. |
| ConstantIsNullOrEmpty.cs:46:21:46:46 | call to method IsNullOrEmpty | Condition always evaluates to 'true'. |
| ConstantIsNullOrEmpty.cs:50:21:50:44 | call to method IsNullOrEmpty | Condition always evaluates to 'true'. |

View File

@@ -1 +1,2 @@
Bad Practices/Control-Flow/ConstantCondition.ql
query: Bad Practices/Control-Flow/ConstantCondition.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,7 +0,0 @@
class Bad
{
public int Max(int a, int b)
{
return a > a ? a : b;
}
}

View File

@@ -8,10 +8,10 @@ namespace ConstantConditionalExpression
public void Foo()
{
int i = (ZERO == 1 - 1) ? 0 : 1; // BAD
int j = false ? 0 : 1; // BAD
int k = " " == " " ? 0 : 1; // BAD
int l = (" "[0] == ' ') ? 0 : 1; // BAD: but not flagged
int i = (ZERO == 1 - 1) ? 0 : 1; // $ Alert
int j = false ? 0 : 1; // $ Alert
int k = " " == " " ? 0 : 1; // $ Alert
int l = (" "[0] == ' ') ? 0 : 1; // Missing Alert
int m = Bar() == 0 ? 0 : 1; // GOOD
}
@@ -21,5 +21,4 @@ namespace ConstantConditionalExpression
}
}
}

View File

@@ -6,9 +6,9 @@ namespace ConstantForCondition
{
public void M()
{
for (int i = 0; false; i++) // GOOD
for (int i = 0; false; i++) // $ Alert
;
for (int i = 0; 0 == 1; i++) // BAD
for (int i = 0; 0 == 1; i++) // $ Alert
;
for (; ; ) // GOOD
;

View File

@@ -8,23 +8,28 @@ namespace ConstantIfCondition
public void Foo()
{
if (ZERO == 1 - 1)
{ // BAD
if (ZERO == 1 - 1) // $ Alert
{
}
if (false)
{ // BAD
if (false) // $ Alert
{
}
if (" " == " ")
{ // BAD
if (" " == " ") // $ Alert
{
}
if (" "[0] == ' ')
{ // BAD: but not flagged
if (" "[0] == ' ') // Missing Alert
{
}
if (Bar() == 0)
{ // GOOD
if (Bar() == 0) // GOOD
{
}
}
public int Max(int a, int b)
{
return a > a ? a : b; // $ Alert
}
public int Bar()
{
return ZERO;

View File

@@ -7,17 +7,17 @@ namespace ConstantIsNullOrEmpty
static void Main(string[] args)
{
{
if (string.IsNullOrEmpty(nameof(args))) // bad: always false
if (string.IsNullOrEmpty(nameof(args))) // $ Alert
{
}
string? x = null;
if (string.IsNullOrEmpty(x)) // would be nice... bad: always true
if (string.IsNullOrEmpty(x)) // Missing Alert (always true)
{
}
string y = "";
if (string.IsNullOrEmpty(y)) // would be nice... bad: always true
if (string.IsNullOrEmpty(y)) // Missing Alert (always true)
{
}
@@ -28,12 +28,12 @@ namespace ConstantIsNullOrEmpty
}
string z = " ";
if (string.IsNullOrEmpty(z)) // would be nice... bad: always false
if (string.IsNullOrEmpty(z)) // Missing Alert (always false)
{
}
string a = "a";
if (string.IsNullOrEmpty(a)) // would be nice... bad: always false
if (string.IsNullOrEmpty(a)) // Missing Alert (always false)
{
}
@@ -43,18 +43,18 @@ namespace ConstantIsNullOrEmpty
{
}
if (string.IsNullOrEmpty(null)) // bad: always true
if (string.IsNullOrEmpty(null)) // $ Alert
{
}
if (string.IsNullOrEmpty("")) // bad: always true
if (string.IsNullOrEmpty("")) // $ Alert
{
}
if (string.IsNullOrEmpty(" ")) // bad: always false
if (string.IsNullOrEmpty(" ")) // $ Alert
{
}
}
}
}
}
}

View File

@@ -8,8 +8,8 @@ namespace ConstantNullCoalescingLeftHandOperand
public void Foo()
{
object i = NULL_OBJECT ?? ""; // BAD
object j = null ?? ""; // BAD
object i = NULL_OBJECT ?? ""; // $ Alert
object j = null ?? ""; // $ Alert
object k = Bar() ?? ""; // GOOD
}

View File

@@ -9,28 +9,28 @@ namespace ConstantWhileCondition
public void Foo()
{
while (ZERO == 1 - 1)
{ // BAD
while (ZERO == 1 - 1) // $ Alert
{
break;
}
while (false)
{ // GOOD
while (false) // $ Alert
{
break;
}
while (true)
{ // GOOD
while (true) // GOOD
{
break;
}
while (" " == " ")
{ // BAD
while (" " == " ") // $ Alert
{
break;
}
while (" "[0] == ' ')
{ // BAD: but not flagged
while (" "[0] == ' ') // Missing Alert
{
break;
}
while (Bar() == 0)
{ // GOOD
while (Bar() == 0) // GOOD
{
break;
}
}

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* Added support for the `@tanstack/angular-query-experimental` package.
* Improved support for the `@angular/common/http` package, detecting outgoing HTTP requests in more cases.

View File

@@ -0,0 +1,7 @@
extensions:
- addsTo:
pack: codeql/javascript-all
extensible: summaryModel
data:
- ["@tanstack/angular-query-experimental", "Member[injectQuery]", "Argument[0].ReturnValue.Member[queryFn].ReturnValue", "ReturnValue.Member[data].Awaited", "taint"]
- ["@tanstack/angular-query", "Member[injectQuery]", "Argument[0].ReturnValue.Member[queryFn].ReturnValue", "ReturnValue.Member[data].Awaited", "taint"]

View File

@@ -190,13 +190,16 @@ module Angular2 {
result.hasUnderlyingType("@angular/common/http", "HttpClient")
}
/** Gets a reference to an `HttpClient` object using the API graph. */
API::Node httpClientApiNode() { result = API::Node::ofType("@angular/common/http", "HttpClient") }
private class AngularClientRequest extends ClientRequest::Range, DataFlow::MethodCallNode {
int argumentOffset;
AngularClientRequest() {
this = httpClient().getAMethodCall("request") and argumentOffset = 1
this = httpClientApiNode().getMember("request").getACall() and argumentOffset = 1
or
this = httpClient().getAMethodCall() and
this = httpClientApiNode().getAMember().getACall() and
not this.getMethodName() = "request" and
argumentOffset = 0
}

View File

@@ -1,5 +1,7 @@
#select
| test.jsx:27:29:27:32 | data | test.jsx:5:28:5:63 | fetch(" ... ntent") | test.jsx:27:29:27:32 | data | Cross-site scripting vulnerability due to $@. | test.jsx:5:28:5:63 | fetch(" ... ntent") | user-provided value |
| test.ts:21:57:21:76 | response.description | test.ts:8:9:8:79 | this.#h ... query') | test.ts:21:57:21:76 | response.description | Cross-site scripting vulnerability due to $@. | test.ts:8:9:8:79 | this.#h ... query') | user-provided value |
| test.ts:24:36:24:90 | `<h2>${ ... o}</p>` | test.ts:8:9:8:79 | this.#h ... query') | test.ts:24:36:24:90 | `<h2>${ ... o}</p>` | Cross-site scripting vulnerability due to $@. | test.ts:8:9:8:79 | this.#h ... query') | user-provided value |
| testReactRelay.tsx:7:43:7:58 | commentData.text | testReactRelay.tsx:5:23:5:52 | useFrag ... entRef) | testReactRelay.tsx:7:43:7:58 | commentData.text | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:5:23:5:52 | useFrag ... entRef) | user-provided value |
| testReactRelay.tsx:18:48:18:68 | data.co ... 0].text | testReactRelay.tsx:17:16:17:42 | useLazy ... ry, {}) | testReactRelay.tsx:18:48:18:68 | data.co ... 0].text | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:17:16:17:42 | useLazy ... ry, {}) | user-provided value |
| testReactRelay.tsx:28:17:28:67 | usePrel ... r?.name | testReactRelay.tsx:28:17:28:56 | usePrel ... erence) | testReactRelay.tsx:28:17:28:67 | usePrel ... r?.name | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:28:17:28:56 | usePrel ... erence) | user-provided value |
@@ -20,6 +22,15 @@ edges
| test.jsx:6:24:6:38 | response.json() | test.jsx:6:18:6:38 | await r ... .json() | provenance | |
| test.jsx:7:12:7:15 | data | test.jsx:15:11:17:5 | data | provenance | |
| test.jsx:15:11:17:5 | data | test.jsx:27:29:27:32 | data | provenance | |
| test.ts:8:9:8:79 | this.#h ... query') | test.ts:20:28:20:35 | response | provenance | |
| test.ts:20:28:20:35 | response | test.ts:21:57:21:64 | response | provenance | |
| test.ts:20:28:20:35 | response | test.ts:24:43:24:50 | response | provenance | |
| test.ts:20:28:20:35 | response | test.ts:24:67:24:74 | response | provenance | |
| test.ts:21:57:21:64 | response | test.ts:21:57:21:76 | response.description | provenance | |
| test.ts:24:43:24:50 | response | test.ts:24:43:24:55 | response.name | provenance | |
| test.ts:24:43:24:55 | response.name | test.ts:24:36:24:90 | `<h2>${ ... o}</p>` | provenance | |
| test.ts:24:67:24:74 | response | test.ts:24:67:24:84 | response.owner.bio | provenance | |
| test.ts:24:67:24:84 | response.owner.bio | test.ts:24:36:24:90 | `<h2>${ ... o}</p>` | provenance | |
| testReactRelay.tsx:5:9:5:52 | commentData | testReactRelay.tsx:7:43:7:53 | commentData | provenance | |
| testReactRelay.tsx:5:23:5:52 | useFrag ... entRef) | testReactRelay.tsx:5:9:5:52 | commentData | provenance | |
| testReactRelay.tsx:7:43:7:53 | commentData | testReactRelay.tsx:7:43:7:58 | commentData.text | provenance | |
@@ -56,6 +67,15 @@ nodes
| test.jsx:7:12:7:15 | data | semmle.label | data |
| test.jsx:15:11:17:5 | data | semmle.label | data |
| test.jsx:27:29:27:32 | data | semmle.label | data |
| test.ts:8:9:8:79 | this.#h ... query') | semmle.label | this.#h ... query') |
| test.ts:20:28:20:35 | response | semmle.label | response |
| test.ts:21:57:21:64 | response | semmle.label | response |
| test.ts:21:57:21:76 | response.description | semmle.label | response.description |
| test.ts:24:36:24:90 | `<h2>${ ... o}</p>` | semmle.label | `<h2>${ ... o}</p>` |
| test.ts:24:43:24:50 | response | semmle.label | response |
| test.ts:24:43:24:55 | response.name | semmle.label | response.name |
| test.ts:24:67:24:74 | response | semmle.label | response |
| test.ts:24:67:24:84 | response.owner.bio | semmle.label | response.owner.bio |
| testReactRelay.tsx:5:9:5:52 | commentData | semmle.label | commentData |
| testReactRelay.tsx:5:23:5:52 | useFrag ... entRef) | semmle.label | useFrag ... entRef) |
| testReactRelay.tsx:7:43:7:53 | commentData | semmle.label | commentData |

View File

@@ -0,0 +1,37 @@
import { QueryClient, injectQuery } from '@tanstack/angular-query-experimental'
import { HttpClient } from '@angular/common/http'
class ServiceOrComponent {
query = injectQuery(() => ({
queryKey: ['repoData'],
queryFn: () =>
this.#http.get<Response>('https://api.github.com/repos/tanstack/query'), // $ Source
}))
#http: {
get: <T>(url: string) => Promise<T>
};
constructor(http: HttpClient) {
this.#http = http;
}
displayRepoDetails() {
this.query.data.then(response => {
document.getElementById('repoInfo').innerHTML = response.description; // $ Alert
const detailsElement = document.createElement('div');
detailsElement.innerHTML = `<h2>${response.name}</h2><p>${response.owner.bio}</p>`; // $ Alert
document.body.appendChild(detailsElement);
});
}
}
interface Response {
name: string;
description: string;
stargazers_count: number;
owner: {
bio: string;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,8 +5,11 @@
<recommendation>
<p>To guard against SSRF attacks you should avoid putting user-provided input directly
into a request URL. Instead, either maintain a list of authorized URLs on the server and choose
from that list based on the input provided, or perform proper validation of the input.
into a request URL. On the application level, maintain a list of authorized URLs on the server and choose
from that list based on the input provided. If that is not possible, one should verify the IP address for all user-controlled
requests to ensure they are not private. This requires saving the verified IP address of each domain,
then utilizing a custom HTTP adapter to ensure that future requests to that domain use the verified IP address.
On the network level, you can segment the vulnerable application into its own LAN or block access to specific devices.
</p>
</recommendation>

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,2 +1,2 @@
mod.rs 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7
top.rs da0f43b99d3a173520048275597e2b052a7351f6fcb2ad5fc912257976742bb7 da0f43b99d3a173520048275597e2b052a7351f6fcb2ad5fc912257976742bb7
top.rs 4b7dee6ebdbb2f8bd2f387cbb71e0481475de0a94c0baaac4699f19551256d65 4b7dee6ebdbb2f8bd2f387cbb71e0481475de0a94c0baaac4699f19551256d65

View File

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

View File

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

View File

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

View File

@@ -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
@@ -501,6 +503,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 +577,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 +592,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 +618,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 +655,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 +753,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

4
rust/ql/.gitattributes generated vendored
View File

@@ -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
@@ -503,6 +505,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 +755,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

View File

@@ -1,6 +1,10 @@
{
"attributes": {
"durations": {
"crateGraph": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"extract": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"

View File

@@ -1,5 +1,5 @@
import rust
from Function f
where exists(f.getLocation().getFile().getRelativePath())
where f.fromSource()
select f

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
| Elements extracted | 66 |
| Elements extracted | 67 |
| Elements unextracted | 0 |
| Extraction errors | 0 |
| Extraction warnings | 1 |

View File

@@ -1,6 +1,10 @@
{
"attributes": {
"durations": {
"crateGraph": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"extract": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"

View File

@@ -1,6 +1,10 @@
{
"attributes": {
"durations": {
"crateGraph": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"
},
"extract": {
"ms": "__REDACTED__",
"pretty": "__REDACTED__"

View File

@@ -1,5 +1,5 @@
import rust
from Function f
where exists(f.getLocation().getFile().getRelativePath())
where f.fromSource()
select f

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
| Elements extracted | 86 |
| Elements extracted | 87 |
| Elements unextracted | 0 |
| Extraction errors | 0 |
| Extraction warnings | 0 |

View File

@@ -1,4 +1,4 @@
| Elements extracted | 86 |
| Elements extracted | 87 |
| Elements unextracted | 0 |
| Extraction errors | 0 |
| Extraction warnings | 0 |

View File

@@ -1,4 +1,5 @@
import rust
from Function f
where f.fromSource()
select f

View File

@@ -1,4 +1,5 @@
import rust
from Function f
where f.fromSource()
select f

View File

@@ -1,4 +1,5 @@
import rust
from Function f
where f.fromSource()
select f

View File

@@ -1,5 +1,5 @@
import rust
from Function f
where exists(f.getLocation().getFile().getRelativePath())
where f.fromSource()
select f

View File

@@ -1,5 +1,5 @@
import rust
from Function f
where exists(f.getLocation().getFile().getRelativePath())
where f.fromSource()
select f

View File

@@ -1,5 +1,5 @@
import rust
from Function f
where exists(f.getLocation().getFile().getRelativePath())
where f.fromSource()
select f

View File

@@ -1,5 +1,5 @@
import rust
from Function f
where exists(f.getLocation().getFile().getRelativePath())
where f.fromSource()
select f

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

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

View File

@@ -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. */

View File

@@ -236,13 +236,11 @@ module Impl {
this instanceof VariableScope or
this instanceof VariableAccessCand or
this instanceof LetStmt or
getImmediateChildAndAccessor(this, _, _) instanceof RelevantElement
getImmediateChild(this, _) instanceof RelevantElement
}
pragma[nomagic]
private RelevantElement getChild(int index) {
result = getImmediateChildAndAccessor(this, index, _)
}
private RelevantElement getChild(int index) { result = getImmediateChild(this, index) }
pragma[nomagic]
private RelevantElement getImmediateChildMin(int index) {

View File

@@ -0,0 +1,94 @@
// generated by codegen, do not edit
/**
* This module provides the generated definition of `Crate`.
* INTERNAL: Do not import directly.
*/
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.elements.internal.generated.Raw
import codeql.rust.elements.Crate
import codeql.rust.elements.internal.ElementImpl::Impl as ElementImpl
import codeql.rust.elements.Module
private class CrateAlias = Crate;
/**
* INTERNAL: This module contains the fully generated definition of `Crate` and should not
* be referenced directly.
*/
module Generated {
/**
* INTERNAL: Do not reference the `Generated::Crate` class directly.
* Use the subclass `Crate`, where the following predicates are available.
*/
class Crate extends Synth::TCrate, ElementImpl::Element {
override string getAPrimaryQlClass() { result = "Crate" }
/**
* Gets the name of this crate, if it exists.
*/
string getName() { result = Synth::convertCrateToRaw(this).(Raw::Crate).getName() }
/**
* Holds if `getName()` exists.
*/
final predicate hasName() { exists(this.getName()) }
/**
* Gets the version of this crate, if it exists.
*/
string getVersion() { result = Synth::convertCrateToRaw(this).(Raw::Crate).getVersion() }
/**
* Holds if `getVersion()` exists.
*/
final predicate hasVersion() { exists(this.getVersion()) }
/**
* Gets the module of this crate, if it exists.
*/
Module getModule() {
result = Synth::convertModuleFromRaw(Synth::convertCrateToRaw(this).(Raw::Crate).getModule())
}
/**
* Holds if `getModule()` exists.
*/
final predicate hasModule() { exists(this.getModule()) }
/**
* Gets the `index`th cfg option of this crate (0-based).
*/
string getCfgOption(int index) {
result = Synth::convertCrateToRaw(this).(Raw::Crate).getCfgOption(index)
}
/**
* Gets any of the cfg options of this crate.
*/
final string getACfgOption() { result = this.getCfgOption(_) }
/**
* Gets the number of cfg options of this crate.
*/
final int getNumberOfCfgOptions() { result = count(int i | exists(this.getCfgOption(i))) }
/**
* Gets the `index`th dependency of this crate (0-based).
*/
CrateAlias getDependency(int index) {
result =
Synth::convertCrateFromRaw(Synth::convertCrateToRaw(this).(Raw::Crate).getDependency(index))
}
/**
* Gets any of the dependencies of this crate.
*/
final CrateAlias getADependency() { result = this.getDependency(_) }
/**
* Gets the number of dependencies of this crate.
*/
final int getNumberOfDependencies() { result = count(int i | exists(this.getDependency(i))) }
}
}

View File

@@ -12,6 +12,19 @@ private module Impl {
none()
}
private Element getImmediateChildOfCrate(Crate e, int index, string partialPredicateCall) {
exists(int b, int bElement, int n |
b = 0 and
bElement = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfElement(e, i, _)) | i) and
n = bElement and
(
none()
or
result = getImmediateChildOfElement(e, index - b, partialPredicateCall)
)
)
}
private Element getImmediateChildOfExtractorStep(
ExtractorStep e, int index, string partialPredicateCall
) {
@@ -4050,6 +4063,8 @@ private module Impl {
// * none() simplifies generation, as we can append `or ...` without a special case for the first item
none()
or
result = getImmediateChildOfCrate(e, index, partialAccessor)
or
result = getImmediateChildOfExtractorStep(e, index, partialAccessor)
or
result = getImmediateChildOfFormat(e, index, partialAccessor)
@@ -4388,6 +4403,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.
*/
@@ -4407,3 +4427,8 @@ Element getChildAndAccessor(Element e, int index, string accessor) {
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() }

View File

@@ -12,6 +12,38 @@ module Raw {
string toString() { none() }
}
/**
* INTERNAL: Do not use.
*/
class Crate extends @crate, Element {
override string toString() { result = "Crate" }
/**
* Gets the name of this crate, if it exists.
*/
string getName() { crate_names(this, result) }
/**
* Gets the version of this crate, if it exists.
*/
string getVersion() { crate_versions(this, result) }
/**
* Gets the module of this crate, if it exists.
*/
Module getModule() { crate_modules(this, result) }
/**
* Gets the `index`th cfg option of this crate (0-based).
*/
string getCfgOption(int index) { crate_cfg_options(this, index, result) }
/**
* Gets the `index`th dependency of this crate (0-based).
*/
Crate getDependency(int index) { crate_dependencies(this, index, result) }
}
/**
* INTERNAL: Do not use.
*/

View File

@@ -162,6 +162,10 @@ module Synth {
* INTERNAL: Do not use.
*/
TContinueExpr(Raw::ContinueExpr id) { constructContinueExpr(id) } or
/**
* INTERNAL: Do not use.
*/
TCrate(Raw::Crate id) { constructCrate(id) } or
/**
* INTERNAL: Do not use.
*/
@@ -1061,6 +1065,12 @@ module Synth {
*/
TContinueExpr convertContinueExprFromRaw(Raw::Element e) { result = TContinueExpr(e) }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TCrate`, if possible.
*/
TCrate convertCrateFromRaw(Raw::Element e) { result = TCrate(e) }
/**
* INTERNAL: Do not use.
* Converts a raw element to a synthesized `TDynTraitTypeRepr`, if possible.
@@ -2050,6 +2060,8 @@ module Synth {
* Converts a raw DB element to a synthesized `TElement`, if possible.
*/
TElement convertElementFromRaw(Raw::Element e) {
result = convertCrateFromRaw(e)
or
result = convertExtractorStepFromRaw(e)
or
result = convertLocatableFromRaw(e)
@@ -2633,6 +2645,12 @@ module Synth {
*/
Raw::Element convertContinueExprToRaw(TContinueExpr e) { e = TContinueExpr(result) }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TCrate` to a raw DB element, if possible.
*/
Raw::Element convertCrateToRaw(TCrate e) { e = TCrate(result) }
/**
* INTERNAL: Do not use.
* Converts a synthesized `TDynTraitTypeRepr` to a raw DB element, if possible.
@@ -3620,6 +3638,8 @@ module Synth {
* Converts a synthesized `TElement` to a raw DB element, if possible.
*/
Raw::Element convertElementToRaw(TElement e) {
result = convertCrateToRaw(e)
or
result = convertExtractorStepToRaw(e)
or
result = convertLocatableToRaw(e)

View File

@@ -40,6 +40,7 @@ import codeql.rust.elements.internal.ConstArgConstructor
import codeql.rust.elements.internal.ConstBlockPatConstructor
import codeql.rust.elements.internal.ConstParamConstructor
import codeql.rust.elements.internal.ContinueExprConstructor
import codeql.rust.elements.internal.CrateConstructor
import codeql.rust.elements.internal.DynTraitTypeReprConstructor
import codeql.rust.elements.internal.EnumConstructor
import codeql.rust.elements.internal.ExprStmtConstructor

View File

@@ -24,7 +24,9 @@ query predicate multipleLocations(Locatable e) { strictcount(e.getLocation()) >
/**
* Holds if `e` does not have a `Location`.
*/
query predicate noLocation(Locatable e) { not exists(e.getLocation()) }
query predicate noLocation(Locatable e) {
not exists(e.getLocation()) and not e.(AstNode).getParentNode*() = any(Crate c).getModule()
}
private predicate multiplePrimaryQlClasses(Element e) {
strictcount(string cls | cls = e.getAPrimaryQlClass() and cls != "VariableAccess") > 1
@@ -38,7 +40,7 @@ query predicate multiplePrimaryQlClasses(Element e, string s) {
s = strictconcat(e.getPrimaryQlClasses(), ", ")
}
private Element getParent(Element child) { child = getChildAndAccessor(result, _, _) }
private Element getParent(Element child) { child = getChild(result, _) }
private predicate multipleParents(Element child) { strictcount(getParent(child)) > 1 }
@@ -54,8 +56,8 @@ query predicate multipleParents(Element child, string childClass, Element parent
/** Holds if `parent` has multiple children at the same index. */
query predicate multipleChildren(Element parent, int index, Element child1, Element child2) {
child1 = getChildAndAccessor(parent, index, _) and
child2 = getChildAndAccessor(parent, index, _) and
child1 = getChild(parent, index) and
child2 = getChild(parent, index) and
child1 != child2
}

View File

@@ -7,6 +7,7 @@ import rust
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.internal.DataFlowImpl
private import codeql.rust.security.SensitiveData
private import codeql.rust.Concepts
/**
* Provides default sources, sinks and barriers for detecting cleartext logging
@@ -21,7 +22,9 @@ module CleartextLogging {
/**
* A data flow sink for cleartext logging vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
abstract class Sink extends QuerySink::Range {
override string getSinkType() { result = "CleartextLogging" }
}
/**
* A barrier for cleartext logging vulnerabilities.

View File

@@ -23,7 +23,9 @@ module SqlInjection {
/**
* A data flow sink for SQL injection vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
abstract class Sink extends QuerySink::Range {
override string getSinkType() { result = "SqlInjection" }
}
/**
* A barrier for SQL injection vulnerabilities.

View File

@@ -43,7 +43,7 @@ module NormalHashFunction {
* data" vulnerabilities that applies to data that does not require computationally expensive
* hashing. That is, a broken or weak hashing algorithm.
*/
abstract class Sink extends DataFlow::Node {
abstract class Sink extends QuerySink::Range {
/**
* Gets the name of the weak hashing algorithm.
*/
@@ -76,6 +76,8 @@ module NormalHashFunction {
class WeakHashingOperationInputAsSink extends Sink {
Cryptography::HashingAlgorithm algorithm;
override string getSinkType() { result = "WeakSensitiveDataHashing" }
WeakHashingOperationInputAsSink() {
exists(Cryptography::CryptographicOperation operation |
algorithm.isWeak() and
@@ -114,7 +116,9 @@ module ComputationallyExpensiveHashFunction {
* hashing. That is, a broken or weak hashing algorithm or one that is not computationally
* expensive enough for password hashing.
*/
abstract class Sink extends DataFlow::Node {
abstract class Sink extends QuerySink::Range {
override string getSinkType() { result = "WeakSensitiveDataHashing" }
/**
* Gets the name of the weak hashing algorithm.
*/

View File

@@ -8,11 +8,14 @@ private import rust
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.controlflow.CfgNodes
private import codeql.rust.dataflow.FlowSink
private import codeql.rust.Concepts
/**
* A data flow sink for regular expression injection vulnerabilities.
*/
abstract class RegexInjectionSink extends DataFlow::Node { }
abstract class RegexInjectionSink extends QuerySink::Range {
override string getSinkType() { result = "RegexInjection" }
}
/**
* A barrier for regular expression injection vulnerabilities.

View File

@@ -120,11 +120,48 @@ locatable_locations(
// from schema
@element =
@extractor_step
@crate
| @extractor_step
| @locatable
| @unextracted
;
crates(
unique int id: @crate
);
#keyset[id]
crate_names(
int id: @crate ref,
string name: string ref
);
#keyset[id]
crate_versions(
int id: @crate ref,
string version: string ref
);
#keyset[id]
crate_modules(
int id: @crate ref,
int module: @module ref
);
#keyset[id, index]
crate_cfg_options(
int id: @crate ref,
int index: int ref,
string cfg_option: string ref
);
#keyset[id, index]
crate_dependencies(
int id: @crate ref,
int index: int ref,
int dependency: @crate ref
);
extractor_steps(
unique int id: @extractor_step,
string action: string ref,

View File

@@ -10,8 +10,9 @@
import rust
import codeql.rust.dataflow.DataFlow
import codeql.rust.Concepts
import Stats
from string kind, int num
where num = strictcount(DataFlow::Node n | getAQuerySinkKind(n) = kind)
where num = strictcount(QuerySink s | s.getSinkType() = kind)
select kind, num

View File

@@ -11,7 +11,8 @@
import rust
import codeql.rust.dataflow.DataFlow
import codeql.rust.Concepts
import Stats
from DataFlow::Node n
select n, "Sink for " + strictconcat(getAQuerySinkKind(n), ", ") + "."
from QuerySink s
select s, "Sink for " + concat(s.getSinkType(), ", ") + "."

View File

@@ -9,8 +9,12 @@ private import codeql.rust.dataflow.internal.TaintTrackingImpl
private import codeql.rust.internal.AstConsistency as AstConsistency
private import codeql.rust.controlflow.internal.CfgConsistency as CfgConsistency
private import codeql.rust.dataflow.internal.DataFlowConsistency as DataFlowConsistency
private import codeql.rust.security.SqlInjectionExtensions
private import codeql.rust.Concepts
// import all query extensions files, so that all extensions of `QuerySink` are found
private import codeql.rust.security.CleartextLoggingExtensions
private import codeql.rust.security.SqlInjectionExtensions
private import codeql.rust.security.WeakSensitiveDataHashingExtensions
private import codeql.rust.security.regex.RegexInjectionExtensions
/**
* Gets a count of the total number of lines of code in the database.
@@ -55,16 +59,7 @@ int getTaintEdgesCount() {
)
}
/**
* Gets a kind of query for which `n` is a sink (if any).
*/
string getAQuerySinkKind(DataFlow::Node n) {
n instanceof SqlInjection::Sink and result = "SqlInjection"
or
n instanceof CleartextLogging::Sink and result = "CleartextLogging"
}
/**
* Gets a count of the total number of query sinks in the database.
*/
int getQuerySinksCount() { result = count(DataFlow::Node n | exists(getAQuerySinkKind(n))) }
int getQuerySinksCount() { result = count(QuerySink s) }

View File

@@ -14,9 +14,17 @@ import codeql.rust.Diagnostics
import Stats
import TaintReach
class CrateElement extends Element {
CrateElement() {
this instanceof Crate or
this.(AstNode).getParentNode*() = any(Crate c).getModule()
}
}
from string key, int value
where
key = "Elements extracted" and value = count(Element e | not e instanceof Unextracted)
key = "Elements extracted" and
value = count(Element e | not e instanceof Unextracted and not e instanceof CrateElement)
or
key = "Elements unextracted" and value = count(Unextracted e)
or

View File

@@ -1,3 +1,10 @@
private import rust
predicate toBeTested(Element e) { any() }
predicate toBeTested(Element e) { not e instanceof CrateElement }
class CrateElement extends Element {
CrateElement() {
this instanceof Crate or
any(Crate c).getModule() = this.(AstNode).getParentNode*()
}
}

View File

@@ -0,0 +1,117 @@
#-----| Crate(allocator_api2@0.2.21)
#-----| Crate(core@0.0.0)
#-----| -> Crate(rand@0.8.5)
#-----| -> Crate(rand_xorshift@0.3.0)
#-----| Crate(compiler_builtins@0.1.140)
#-----| -> Crate(core@0.0.0)
#-----| Crate(cfg_if@1.0.0)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(compiler_builtins@0.1.140)
#-----| Crate(std@0.0.0)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(compiler_builtins@0.1.140)
#-----| -> Crate(cfg_if@1.0.0)
#-----| -> Crate(alloc@0.0.0)
#-----| -> Crate(hashbrown@0.15.2)
#-----| -> Crate(libc@0.2.169)
#-----| -> Crate(rand@0.8.5)
#-----| -> Crate(rand_xorshift@0.3.0)
#-----| -> Crate(rustc_demangle@0.1.24)
#-----| -> Crate(panic_abort@0.0.0)
#-----| -> Crate(unwind@0.0.0)
#-----| -> Crate(panic_unwind@0.0.0)
#-----| -> Crate(std_detect@0.1.5)
#-----| Crate(unicode_width@0.1.14)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(compiler_builtins@0.1.140)
#-----| -> Crate(std@0.0.0)
#-----| Crate(getopts@0.2.21)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(std@0.0.0)
#-----| -> Crate(unicode_width@0.1.14)
#-----| Crate(alloc@0.0.0)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(compiler_builtins@0.1.140)
#-----| -> Crate(rand@0.8.5)
#-----| -> Crate(rand_xorshift@0.3.0)
#-----| Crate(hashbrown@0.15.2)
#-----| -> Crate(allocator_api2@0.2.21)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(compiler_builtins@0.1.140)
#-----| -> Crate(alloc@0.0.0)
#-----| Crate(libc@0.2.169)
#-----| -> Crate(core@0.0.0)
#-----| Crate(rand_core@0.6.4)
#-----| Crate(rand@0.8.5)
#-----| -> Crate(rand_core@0.6.4)
#-----| Crate(rand_xorshift@0.3.0)
#-----| -> Crate(rand_core@0.6.4)
#-----| Crate(rustc_demangle@0.1.24)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(compiler_builtins@0.1.140)
#-----| Crate(panic_abort@0.0.0)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(compiler_builtins@0.1.140)
#-----| -> Crate(cfg_if@1.0.0)
#-----| -> Crate(alloc@0.0.0)
#-----| -> Crate(libc@0.2.169)
#-----| Crate(unwind@0.0.0)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(compiler_builtins@0.1.140)
#-----| -> Crate(cfg_if@1.0.0)
#-----| -> Crate(libc@0.2.169)
#-----| Crate(panic_unwind@0.0.0)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(compiler_builtins@0.1.140)
#-----| -> Crate(cfg_if@1.0.0)
#-----| -> Crate(alloc@0.0.0)
#-----| -> Crate(libc@0.2.169)
#-----| -> Crate(unwind@0.0.0)
#-----| Crate(proc_macro@0.0.0)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(std@0.0.0)
#-----| Crate(std_detect@0.1.5)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(compiler_builtins@0.1.140)
#-----| -> Crate(cfg_if@1.0.0)
#-----| -> Crate(alloc@0.0.0)
#-----| -> Crate(libc@0.2.169)
#-----| Crate(test@0.0.0)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(std@0.0.0)
#-----| -> Crate(getopts@0.2.21)
#-----| -> Crate(libc@0.2.169)
#-----| Crate(test@0.0.1)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(std@0.0.0)
#-----| -> Crate(alloc@0.0.0)
#-----| -> Crate(proc_macro@0.0.0)
#-----| -> Crate(test@0.0.0)
#-----| Crate(main@0.0.1)
#-----| -> Crate(core@0.0.0)
#-----| -> Crate(std@0.0.0)
#-----| -> Crate(alloc@0.0.0)
#-----| -> Crate(proc_macro@0.0.0)
#-----| -> Crate(test@0.0.0)
#-----| -> Crate(test@0.0.1)

View File

@@ -0,0 +1,11 @@
/**
* @id crate-graph
* @name Crate Graph
* @kind graph
*/
import rust
query predicate nodes(Crate c) { any() }
query predicate edges(Crate c1, Crate c2) { c1.getADependency() = c2 }

View File

@@ -0,0 +1,3 @@
fn main() {
println! {"Hello world"}
}

View File

@@ -0,0 +1,42 @@
use std::fmt;
pub enum X {
A,
B,
}
pub struct X_List {
x: X,
tail: Option<Box<X_List>>,
}
pub fn length(list: X_List) -> usize {
match list {
X_List { x: _, tail: None } => 1,
X_List {
x: _,
tail: Some(tail),
} => 1 + length(*tail),
}
}
pub trait AsString {
fn as_string(&self) -> &str;
}
impl AsString for X {
fn as_string(&self) -> &str {
match self {
X::A => "a",
X::B => "b",
}
}
}
impl fmt::Display for X {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_string())
}
}
pub const X_A: X = X::A;
pub static X_B: X = X::B;

View File

@@ -0,0 +1,38 @@
#-----| Const
#-----| Static
#-----| enum X
#-----| fn as_string
#-----| fn as_string
#-----| fn fmt
#-----| fn length
#-----| impl ...::Display for ...::X { ... }
#-----| -> fn fmt
#-----| impl AsString for ...::X { ... }
#-----| -> fn as_string
lib.rs:
# 0| mod crate
#-----| -> mod module
#-----| mod module
#-----| -> Const
#-----| -> Static
#-----| -> enum X
#-----| -> fn length
#-----| -> impl ...::Display for ...::X { ... }
#-----| -> impl AsString for ...::X { ... }
#-----| -> struct X_List
#-----| -> trait AsString
#-----| struct X_List
#-----| trait AsString
#-----| -> fn as_string

View File

@@ -0,0 +1,45 @@
/**
* @id module-graph
* @name Module and Item Graph
* @kind graph
*/
import rust
predicate nodes(Item i) { i instanceof RelevantNode }
class RelevantNode extends Item {
RelevantNode() {
this.getParentNode*() =
any(Crate m | m.getName() = "test" and m.getVersion() = "0.0.1").getModule()
}
}
predicate edges(RelevantNode container, RelevantNode element) {
element = container.(Module).getItemList().getAnItem() or
element = container.(Impl).getAssocItemList().getAnAssocItem() or
element = container.(Trait).getAssocItemList().getAnAssocItem()
}
query predicate nodes(RelevantNode node, string attr, string val) {
nodes(node) and
(
attr = "semmle.label" and
val = node.toString()
or
attr = "semmle.order" and
val =
any(int i | node = rank[i](RelevantNode n | nodes(n) | n order by n.toString())).toString()
)
}
query predicate edges(RelevantNode pred, RelevantNode succ, string attr, string val) {
edges(pred, succ) and
(
attr = "semmle.label" and
val = ""
or
attr = "semmle.order" and
val = any(int i | succ = rank[i](Item s | edges(pred, s) | s order by s.toString())).toString()
)
}

Some files were not shown because too many files have changed in this diff Show More