Merge branch 'main' into openssl_keyagreement_instances_and_consumers

This commit is contained in:
Nicolas Will
2025-06-02 16:54:22 +02:00
committed by GitHub
270 changed files with 32529 additions and 7518 deletions

View File

@@ -66,6 +66,6 @@ jobs:
# Update existing stubs in the repo with the freshly generated ones
mv "$STUBS_PATH/output/stubs/_frameworks" ql/test/resources/stubs/
git status
codeql test run --threads=0 --search-path "${{ github.workspace }}" --check-databases --check-undefined-labels --check-repeated-labels --check-redefined-labels --consistency-queries ql/consistency-queries -- ql/test/library-tests/dataflow/flowsources/aspremote
codeql test run --threads=0 --search-path "${{ github.workspace }}" --check-databases --check-diff-informed --check-undefined-labels --check-repeated-labels --check-redefined-labels --consistency-queries ql/consistency-queries -- ql/test/library-tests/dataflow/flowsources/aspremote
env:
GITHUB_TOKEN: ${{ github.token }}

View File

@@ -35,6 +35,6 @@ jobs:
key: ruby-qltest
- name: Run QL tests
run: |
codeql test run --dynamic-join-order-mode=all --threads=0 --ram 50000 --search-path "${{ github.workspace }}" --check-databases --check-undefined-labels --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
codeql test run --dynamic-join-order-mode=all --threads=0 --ram 50000 --search-path "${{ github.workspace }}" --check-databases --check-diff-informed --check-undefined-labels --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
env:
GITHUB_TOKEN: ${{ github.token }}

View File

@@ -68,6 +68,6 @@ jobs:
key: ruby-qltest
- name: Run QL tests
run: |
codeql test run --threads=0 --ram 50000 --search-path "${{ github.workspace }}" --check-databases --check-undefined-labels --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
codeql test run --threads=0 --ram 50000 --search-path "${{ github.workspace }}" --check-databases --check-diff-informed --check-undefined-labels --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
env:
GITHUB_TOKEN: ${{ github.token }}

View File

@@ -32,7 +32,7 @@ jobs:
if: github.repository_owner == 'github'
strategy:
matrix:
runner: [ubuntu-latest, macos-13-xlarge]
runner: [ubuntu-latest, macos-15-xlarge]
fail-fast: false
runs-on: ${{ matrix.runner }}
steps:

46
Cargo.lock generated
View File

@@ -242,6 +242,8 @@ version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7"
dependencies = [
"jobserver",
"libc",
"shlex",
]
@@ -390,6 +392,7 @@ dependencies = [
"tree-sitter",
"tree-sitter-json",
"tree-sitter-ql",
"zstd",
]
[[package]]
@@ -983,6 +986,15 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jobserver"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
dependencies = [
"libc",
]
[[package]]
name = "jod-thread"
version = "0.1.2"
@@ -1334,6 +1346,12 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "pkg-config"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "portable-atomic"
version = "1.11.0"
@@ -3027,3 +3045,31 @@ dependencies = [
"quote",
"syn",
]
[[package]]
name = "zstd"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "7.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "2.0.15+zstd.1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
dependencies = [
"cc",
"pkg-config",
]

View File

@@ -124,6 +124,7 @@ use_repo(
"vendor_ts__tree-sitter-ruby-0.23.1",
"vendor_ts__triomphe-0.1.14",
"vendor_ts__ungrammar-1.16.1",
"vendor_ts__zstd-0.13.3",
)
http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

View File

@@ -22,16 +22,21 @@ extensions:
- ["actions/stale", "pull-requests: write"]
- ["actions/attest-build-provenance", "id-token: write"]
- ["actions/attest-build-provenance", "attestations: write"]
- ["actions/deploy-pages", "pages: write"]
- ["actions/deploy-pages", "id-token: write"]
- ["actions/delete-package-versions", "packages: write"]
- ["actions/jekyll-build-pages", "contents: read"]
- ["actions/jekyll-build-pages", "pages: write"]
- ["actions/jekyll-build-pages", "id-token: write"]
- ["actions/publish-action", "contents: write"]
- ["actions/versions-package-tools", "contents: read"]
- ["actions/versions-package-tools", "contents: read"]
- ["actions/versions-package-tools", "actions: read"]
- ["actions/reusable-workflows", "contents: read"]
- ["actions/reusable-workflows", "contents: read"]
- ["actions/reusable-workflows", "actions: read"]
- ["actions/ai-inference", "contents: read"]
- ["actions/ai-inference", "models: read"]
# TODO: Add permissions for actions/download-artifact
# TODO: Add permissions for actions/upload-artifact
# No permissions needed for actions/upload-pages-artifact
# TODO: Add permissions for actions/cache
# No permissions needed for actions/configure-pages

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The query `actions/missing-workflow-permissions` is now aware of the minimal permissions needed for the actions `deploy-pages`, `delete-package-versions`, `ai-inference`. This should lead to better alert messages and better fix suggestions.

View File

@@ -0,0 +1,10 @@
on:
workflow_call:
workflow_dispatch:
jobs:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
- uses: actions/ai-inference

View File

@@ -0,0 +1,10 @@
on:
workflow_call:
workflow_dispatch:
jobs:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
- uses: actions/deploy-pages

View File

@@ -0,0 +1,10 @@
on:
workflow_call:
workflow_dispatch:
jobs:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
- uses: actions/delete-package-versions

View File

@@ -3,3 +3,6 @@
| .github/workflows/perms5.yml:7:5:10:32 | Job: build | Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read} |
| .github/workflows/perms6.yml:7:5:11:39 | Job: build | Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read, id-token: write, pages: write} |
| .github/workflows/perms7.yml:7:5:10:38 | Job: build | Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {} |
| .github/workflows/perms8.yml:7:5:10:33 | Job: build | Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {id-token: write, pages: write} |
| .github/workflows/perms9.yml:7:5:10:44 | Job: build | Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {packages: write} |
| .github/workflows/perms10.yml:7:5:10:33 | Job: build | Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read, models: read} |

View File

@@ -0,0 +1,9 @@
{
"strategy": "dca",
"language": "cpp",
"targets": [
{ "name": "openssl", "with-sources": false, "with-sinks": false },
{ "name": "sqlite", "with-sources": false, "with-sinks": false }
],
"destination": "cpp/ql/lib/ext/generated"
}

View File

@@ -0,0 +1,6 @@
---
category: feature
---
* Added the `pCmdLine` arguments of `WinMain` and `wWinMain` as local flow sources.
* Added source models for `GetCommandLineA`, `GetCommandLineW`, `GetEnvironmentStringsA`, `GetEnvironmentStringsW`, `GetEnvironmentVariableA`, and `GetEnvironmentVariableW`.
* Added summary models for `CommandLineToArgvA` and `CommandLineToArgvW`.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added local flow source models for `ReadFile`, `ReadFileEx`, `MapViewOfFile`, `MapViewOfFile2`, `MapViewOfFile3`, `MapViewOfFile3FromApp`, `MapViewOfFileEx`, `MapViewOfFileFromApp`, `MapViewOfFileNuma2`, and `NtReadFile`.

View File

@@ -1,4 +1,4 @@
# partial model of the Boost::Asio network library
# partial model of the Boost::Asio network library
extensions:
- addsTo:
pack: codeql/cpp-all

View File

@@ -0,0 +1,35 @@
# partial model of windows system calls
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: sourceModel
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
# processenv.h
- ["", "", False, "GetCommandLineA", "", "", "ReturnValue[*]", "local", "manual"]
- ["", "", False, "GetCommandLineW", "", "", "ReturnValue[*]", "local", "manual"]
- ["", "", False, "GetEnvironmentStringsA", "", "", "ReturnValue[*]", "local", "manual"]
- ["", "", False, "GetEnvironmentStringsW", "", "", "ReturnValue[*]", "local", "manual"]
- ["", "", False, "GetEnvironmentVariableA", "", "", "Argument[*1]", "local", "manual"]
- ["", "", False, "GetEnvironmentVariableW", "", "", "Argument[*1]", "local", "manual"]
# fileapi.h
- ["", "", False, "ReadFile", "", "", "Argument[*1]", "local", "manual"]
- ["", "", False, "ReadFileEx", "", "", "Argument[*1]", "local", "manual"]
# memoryapi.h
- ["", "", False, "MapViewOfFile", "", "", "ReturnValue[*]", "local", "manual"]
- ["", "", False, "MapViewOfFile2", "", "", "ReturnValue[*]", "local", "manual"]
- ["", "", False, "MapViewOfFile3", "", "", "ReturnValue[*]", "local", "manual"]
- ["", "", False, "MapViewOfFile3FromApp", "", "", "ReturnValue[*]", "local", "manual"]
- ["", "", False, "MapViewOfFileEx", "", "", "ReturnValue[*]", "local", "manual"]
- ["", "", False, "MapViewOfFileFromApp", "", "", "ReturnValue[*]", "local", "manual"]
- ["", "", False, "MapViewOfFileNuma2", "", "", "ReturnValue[*]", "local", "manual"]
# ntifs.h
- ["", "", False, "NtReadFile", "", "", "Argument[*5]", "local", "manual"]
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
# shellapi.h
- ["", "", False, "CommandLineToArgvA", "", "", "Argument[*0]", "ReturnValue[**]", "taint", "manual"]
- ["", "", False, "CommandLineToArgvW", "", "", "Argument[*0]", "ReturnValue[**]", "taint", "manual"]
# fileapi.h
- ["", "", False, "ReadFileEx", "", "", "Argument[*3].Field[@hEvent]", "Argument[4].Parameter[*2].Field[@hEvent]", "value", "manual"]

View File

@@ -17,7 +17,7 @@ dependencies:
codeql/xml: ${workspace}
dataExtensions:
- ext/*.model.yml
- ext/generated/*.model.yml
- ext/generated/**/*.model.yml
- ext/deallocation/*.model.yml
- ext/allocation/*.model.yml
warnOnImplicitThis: true

View File

@@ -22,7 +22,11 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
ArgumentPosition callbackSelfParameterPosition() { result = TDirectPosition(-1) }
ReturnKind getStandardReturnValueKind() { result.(NormalReturnKind).getIndirectionIndex() = 0 }
ReturnKind getStandardReturnValueKind() { result = getReturnValueKind("") }
ReturnKind getReturnValueKind(string arg) {
arg = repeatStars(result.(NormalReturnKind).getIndirectionIndex())
}
string encodeParameterPosition(ParameterPosition pos) { result = pos.toString() }

View File

@@ -1903,6 +1903,10 @@ module IteratorFlow {
predicate allowFlowIntoUncertainDef(IteratorSsa::UncertainWriteDefinition def) { any() }
class Guard extends Void {
predicate hasBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
none()
}
predicate controlsBranchEdge(
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch
) {

View File

@@ -991,13 +991,17 @@ private module DataFlowIntegrationInput implements SsaImpl::DataFlowIntegrationI
class Guard instanceof IRGuards::IRGuardCondition {
string toString() { result = super.toString() }
predicate controlsBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
predicate hasBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
exists(EdgeKind kind |
super.getBlock() = bb1 and
kind = getConditionalEdge(branch) and
bb1.getSuccessor(kind) = bb2
)
}
predicate controlsBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
this.hasBranchEdge(bb1, bb2, branch)
}
}
predicate guardDirectlyControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) {

View File

@@ -264,10 +264,6 @@ module SemanticExprConfig {
Guard comparisonGuard(Expr e) { getSemanticExpr(result) = e }
predicate implies_v2(Guard g1, boolean b1, Guard g2, boolean b2) {
none() // TODO
}
/** Gets the expression associated with `instr`. */
SemExpr getSemanticExpr(IR::Instruction instr) { result = instr }
}

View File

@@ -18,11 +18,11 @@ class SemGuard instanceof Specific::Guard {
Specific::equalityGuard(this, e1, e2, polarity)
}
final predicate directlyControls(SemBasicBlock controlled, boolean branch) {
final predicate controls(SemBasicBlock controlled, boolean branch) {
Specific::guardDirectlyControlsBlock(this, controlled, branch)
}
final predicate hasBranchEdge(SemBasicBlock bb1, SemBasicBlock bb2, boolean branch) {
final predicate controlsBranchEdge(SemBasicBlock bb1, SemBasicBlock bb2, boolean branch) {
Specific::guardHasBranchEdge(this, bb1, bb2, branch)
}
@@ -31,8 +31,4 @@ class SemGuard instanceof Specific::Guard {
final SemExpr asExpr() { result = Specific::getGuardAsExpr(this) }
}
predicate semImplies_v2(SemGuard g1, boolean b1, SemGuard g2, boolean b2) {
Specific::implies_v2(g1, b1, g2, b2)
}
SemGuard semGetComparisonGuard(SemRelationalExpr e) { result = Specific::comparisonGuard(e) }

View File

@@ -77,8 +77,6 @@ module Sem implements Semantic<SemLocation> {
class Guard = SemGuard;
predicate implies_v2 = semImplies_v2/4;
class Type = SemType;
class IntegerType = SemIntegerType;

View File

@@ -55,7 +55,7 @@ private class LocalModelSource extends LocalFlowSource {
}
/**
* A local data flow source that the `argv` parameter to `main` or `wmain`.
* A local data flow source that is the `argv` parameter to `main` or `wmain`.
*/
private class ArgvSource extends LocalFlowSource {
ArgvSource() {
@@ -69,6 +69,21 @@ private class ArgvSource extends LocalFlowSource {
override string getSourceType() { result = "a command-line argument" }
}
/**
* A local data flow source that is the `pCmdLine` parameter to `WinMain` or `wWinMain`.
*/
private class CmdLineSource extends LocalFlowSource {
CmdLineSource() {
exists(Function main, Parameter pCmdLine |
main.hasGlobalName(["WinMain", "wWinMain"]) and
main.getParameter(2) = pCmdLine and
this.asParameter(1) = pCmdLine
)
}
override string getSourceType() { result = "a command-line" }
}
/**
* A remote data flow source that is defined through 'models as data'.
*/

View File

@@ -1 +1 @@
semmle-extractor-options: -I ../../../../stubs/crypto
semmle-extractor-options: -I ../../../stubs

View File

@@ -0,0 +1,4 @@
The stubs in this directory are derived from various open-source projects, and
used to test that the relevant APIs are correctly modelled. Where a disclaimer
or third-party-notice is required, this is included in the top-level directory
for each particular library.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,177 @@
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@@ -0,0 +1,3 @@
int RAND_bytes(unsigned char *buf, int num);
int RAND_pseudo_bytes(unsigned char *buf, int num);

View File

@@ -124,7 +124,11 @@ module IRTest {
/** Common data flow configuration to be used by tests. */
module IRTestAllocationConfig implements DataFlow::ConfigSig {
private import semmle.code.cpp.security.FlowSources
predicate isSource(DataFlow::Node source) {
source instanceof FlowSource
or
source.asExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asIndirectExpr(1).(FunctionCall).getTarget().getName() = "indirect_source"

View File

@@ -337,3 +337,4 @@ irFlow
| true_upon_entry.cpp:70:11:70:16 | call to source | true_upon_entry.cpp:78:8:78:8 | x |
| true_upon_entry.cpp:83:11:83:16 | call to source | true_upon_entry.cpp:86:8:86:8 | x |
| true_upon_entry.cpp:98:11:98:16 | call to source | true_upon_entry.cpp:105:8:105:8 | x |
| winmain.cpp:4:57:4:64 | *pCmdLine | winmain.cpp:6:8:6:16 | * ... |

View File

@@ -0,0 +1,9 @@
void sink(char);
void sink(char*);
int WinMain(void *hInstance, void *hPrevInstance, char *pCmdLine, int nCmdShow) { // $ ast-def=hInstance ast-def=hPrevInstance ast-def=pCmdLine ir-def=*hInstance ir-def=*hPrevInstance ir-def=*pCmdLine
sink(pCmdLine);
sink(*pCmdLine); // $ ir
return 0;
}

View File

@@ -10,33 +10,95 @@ edges
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:6 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:10 |
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:23489 |
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:23490 |
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:23491 |
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:23508 |
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:23509 |
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:23510 |
| test.cpp:7:47:7:52 | value2 | test.cpp:7:64:7:69 | value2 | provenance | |
| test.cpp:7:64:7:69 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | provenance | |
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:23487 |
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:14:10:14:10 | x | provenance | Sink:MaD:23488 |
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:23506 |
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:14:10:14:10 | x | provenance | Sink:MaD:23507 |
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:17:24:17:24 | x | provenance | |
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:21:27:21:27 | x | provenance | |
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:25:35:25:35 | x | provenance | |
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:32:41:32:41 | x | provenance | |
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | |
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:18:10:18:10 | y | provenance | Sink:MaD:23488 |
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:18:10:18:10 | y | provenance | Sink:MaD:23507 |
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | provenance | |
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:23489 |
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:23508 |
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | |
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:22:10:22:10 | z | provenance | Sink:MaD:23488 |
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:22:10:22:10 | z | provenance | Sink:MaD:23507 |
| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | provenance | |
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:23490 |
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:23509 |
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | |
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:26:10:26:11 | y2 | provenance | Sink:MaD:23488 |
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:26:10:26:11 | y2 | provenance | Sink:MaD:23507 |
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | provenance | |
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:23491 |
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:23510 |
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | |
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:33:10:33:11 | z2 | provenance | Sink:MaD:23488 |
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:33:10:33:11 | z2 | provenance | Sink:MaD:23507 |
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | provenance | |
| test.cpp:32:41:32:41 | x | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | |
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | provenance | MaD:341 |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:325 |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:27:36:27:38 | *cmd | provenance | |
| windows.cpp:27:17:27:34 | **call to CommandLineToArgvA | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA | provenance | |
| windows.cpp:27:17:27:34 | **call to CommandLineToArgvA | windows.cpp:30:8:30:15 | * ... | provenance | |
| windows.cpp:27:36:27:38 | *cmd | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | provenance | |
| windows.cpp:27:36:27:38 | *cmd | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA | provenance | MaD:341 |
| windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | provenance | Src:MaD:327 |
| windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | windows.cpp:36:10:36:13 | * ... | provenance | |
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | windows.cpp:41:10:41:13 | * ... | provenance | Src:MaD:329 |
| windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [*hEvent] | windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | provenance | |
| windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [hEvent] | windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | provenance | |
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | provenance | MaD:343 |
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[hEvent] in ReadFileEx | provenance | MaD:343 |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [*hEvent] | windows.cpp:147:16:147:27 | *lpOverlapped [*hEvent] | provenance | |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [hEvent] | windows.cpp:157:16:157:27 | *lpOverlapped [hEvent] | provenance | |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [*hEvent] | provenance | |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [hEvent] | provenance | |
| windows.cpp:147:16:147:27 | *lpOverlapped [*hEvent] | windows.cpp:149:42:149:53 | *lpOverlapped [*hEvent] | provenance | |
| windows.cpp:149:18:149:62 | *hEvent | windows.cpp:149:18:149:62 | *hEvent | provenance | |
| windows.cpp:149:18:149:62 | *hEvent | windows.cpp:151:8:151:14 | * ... | provenance | |
| windows.cpp:149:42:149:53 | *lpOverlapped [*hEvent] | windows.cpp:149:18:149:62 | *hEvent | provenance | |
| windows.cpp:149:42:149:53 | *lpOverlapped [*hEvent] | windows.cpp:149:56:149:61 | *hEvent | provenance | |
| windows.cpp:149:56:149:61 | *hEvent | windows.cpp:149:18:149:62 | *hEvent | provenance | |
| windows.cpp:157:16:157:27 | *lpOverlapped [hEvent] | windows.cpp:159:35:159:46 | *lpOverlapped [hEvent] | provenance | |
| windows.cpp:159:12:159:55 | hEvent | windows.cpp:159:12:159:55 | hEvent | provenance | |
| windows.cpp:159:12:159:55 | hEvent | windows.cpp:160:8:160:8 | c | provenance | |
| windows.cpp:159:35:159:46 | *lpOverlapped [hEvent] | windows.cpp:159:12:159:55 | hEvent | provenance | |
| windows.cpp:159:35:159:46 | *lpOverlapped [hEvent] | windows.cpp:159:12:159:55 | hEvent | provenance | |
| windows.cpp:168:35:168:40 | ReadFile output argument | windows.cpp:170:10:170:16 | * ... | provenance | Src:MaD:331 |
| windows.cpp:177:23:177:28 | ReadFileEx output argument | windows.cpp:179:10:179:16 | * ... | provenance | Src:MaD:332 |
| windows.cpp:189:21:189:26 | ReadFile output argument | windows.cpp:190:5:190:56 | *... = ... | provenance | Src:MaD:331 |
| windows.cpp:190:5:190:14 | *overlapped [post update] [*hEvent] | windows.cpp:192:53:192:63 | *& ... [*hEvent] | provenance | |
| windows.cpp:190:5:190:56 | *... = ... | windows.cpp:190:5:190:14 | *overlapped [post update] [*hEvent] | provenance | |
| windows.cpp:192:53:192:63 | *& ... [*hEvent] | windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [*hEvent] | provenance | |
| windows.cpp:198:21:198:26 | ReadFile output argument | windows.cpp:199:5:199:57 | ... = ... | provenance | Src:MaD:331 |
| windows.cpp:199:5:199:14 | *overlapped [post update] [hEvent] | windows.cpp:201:53:201:63 | *& ... [hEvent] | provenance | |
| windows.cpp:199:5:199:57 | ... = ... | windows.cpp:199:5:199:14 | *overlapped [post update] [hEvent] | provenance | |
| windows.cpp:201:53:201:63 | *& ... [hEvent] | windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [hEvent] | provenance | |
| windows.cpp:209:84:209:89 | NtReadFile output argument | windows.cpp:211:10:211:16 | * ... | provenance | Src:MaD:340 |
| windows.cpp:286:23:286:35 | *call to MapViewOfFile | windows.cpp:286:23:286:35 | *call to MapViewOfFile | provenance | Src:MaD:333 |
| windows.cpp:286:23:286:35 | *call to MapViewOfFile | windows.cpp:287:20:287:52 | *pMapView | provenance | |
| windows.cpp:287:20:287:52 | *pMapView | windows.cpp:289:10:289:16 | * ... | provenance | |
| windows.cpp:293:23:293:36 | *call to MapViewOfFile2 | windows.cpp:293:23:293:36 | *call to MapViewOfFile2 | provenance | Src:MaD:334 |
| windows.cpp:293:23:293:36 | *call to MapViewOfFile2 | windows.cpp:294:20:294:52 | *pMapView | provenance | |
| windows.cpp:294:20:294:52 | *pMapView | windows.cpp:296:10:296:16 | * ... | provenance | |
| windows.cpp:302:23:302:36 | *call to MapViewOfFile3 | windows.cpp:302:23:302:36 | *call to MapViewOfFile3 | provenance | Src:MaD:335 |
| windows.cpp:302:23:302:36 | *call to MapViewOfFile3 | windows.cpp:303:20:303:52 | *pMapView | provenance | |
| windows.cpp:303:20:303:52 | *pMapView | windows.cpp:305:10:305:16 | * ... | provenance | |
| windows.cpp:311:23:311:43 | *call to MapViewOfFile3FromApp | windows.cpp:311:23:311:43 | *call to MapViewOfFile3FromApp | provenance | Src:MaD:336 |
| windows.cpp:311:23:311:43 | *call to MapViewOfFile3FromApp | windows.cpp:312:20:312:52 | *pMapView | provenance | |
| windows.cpp:312:20:312:52 | *pMapView | windows.cpp:314:10:314:16 | * ... | provenance | |
| windows.cpp:318:23:318:37 | *call to MapViewOfFileEx | windows.cpp:318:23:318:37 | *call to MapViewOfFileEx | provenance | Src:MaD:337 |
| windows.cpp:318:23:318:37 | *call to MapViewOfFileEx | windows.cpp:319:20:319:52 | *pMapView | provenance | |
| windows.cpp:319:20:319:52 | *pMapView | windows.cpp:321:10:321:16 | * ... | provenance | |
| windows.cpp:325:23:325:42 | *call to MapViewOfFileFromApp | windows.cpp:325:23:325:42 | *call to MapViewOfFileFromApp | provenance | Src:MaD:338 |
| windows.cpp:325:23:325:42 | *call to MapViewOfFileFromApp | windows.cpp:326:20:326:52 | *pMapView | provenance | |
| windows.cpp:326:20:326:52 | *pMapView | windows.cpp:328:10:328:16 | * ... | provenance | |
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | provenance | Src:MaD:339 |
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | windows.cpp:333:20:333:52 | *pMapView | provenance | |
| windows.cpp:333:20:333:52 | *pMapView | windows.cpp:335:10:335:16 | * ... | provenance | |
nodes
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | semmle.label | [summary param] *0 in buffer |
| asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | semmle.label | [summary] to write: ReturnValue in buffer |
@@ -78,9 +140,85 @@ nodes
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | semmle.label | call to ymlStepGenerated_with_body |
| test.cpp:32:41:32:41 | x | semmle.label | x |
| test.cpp:33:10:33:11 | z2 | semmle.label | z2 |
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | semmle.label | [summary param] *0 in CommandLineToArgvA |
| windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | semmle.label | [summary] to write: ReturnValue[**] in CommandLineToArgvA |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA |
| windows.cpp:24:8:24:11 | * ... | semmle.label | * ... |
| windows.cpp:27:17:27:34 | **call to CommandLineToArgvA | semmle.label | **call to CommandLineToArgvA |
| windows.cpp:27:17:27:34 | **call to CommandLineToArgvA | semmle.label | **call to CommandLineToArgvA |
| windows.cpp:27:36:27:38 | *cmd | semmle.label | *cmd |
| windows.cpp:30:8:30:15 | * ... | semmle.label | * ... |
| windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | semmle.label | *call to GetEnvironmentStringsA |
| windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | semmle.label | *call to GetEnvironmentStringsA |
| windows.cpp:36:10:36:13 | * ... | semmle.label | * ... |
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | semmle.label | GetEnvironmentVariableA output argument |
| windows.cpp:41:10:41:13 | * ... | semmle.label | * ... |
| windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [*hEvent] | semmle.label | [summary param] *3 in ReadFileEx [*hEvent] |
| windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [hEvent] | semmle.label | [summary param] *3 in ReadFileEx [hEvent] |
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | semmle.label | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx |
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | semmle.label | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [*hEvent] | semmle.label | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [*hEvent] |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [hEvent] | semmle.label | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [hEvent] |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | semmle.label | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[hEvent] in ReadFileEx | semmle.label | [summary] to write: Argument[4].Parameter[*2].Field[hEvent] in ReadFileEx |
| windows.cpp:147:16:147:27 | *lpOverlapped [*hEvent] | semmle.label | *lpOverlapped [*hEvent] |
| windows.cpp:149:18:149:62 | *hEvent | semmle.label | *hEvent |
| windows.cpp:149:18:149:62 | *hEvent | semmle.label | *hEvent |
| windows.cpp:149:42:149:53 | *lpOverlapped [*hEvent] | semmle.label | *lpOverlapped [*hEvent] |
| windows.cpp:149:56:149:61 | *hEvent | semmle.label | *hEvent |
| windows.cpp:151:8:151:14 | * ... | semmle.label | * ... |
| windows.cpp:157:16:157:27 | *lpOverlapped [hEvent] | semmle.label | *lpOverlapped [hEvent] |
| windows.cpp:159:12:159:55 | hEvent | semmle.label | hEvent |
| windows.cpp:159:12:159:55 | hEvent | semmle.label | hEvent |
| windows.cpp:159:35:159:46 | *lpOverlapped [hEvent] | semmle.label | *lpOverlapped [hEvent] |
| windows.cpp:160:8:160:8 | c | semmle.label | c |
| windows.cpp:168:35:168:40 | ReadFile output argument | semmle.label | ReadFile output argument |
| windows.cpp:170:10:170:16 | * ... | semmle.label | * ... |
| windows.cpp:177:23:177:28 | ReadFileEx output argument | semmle.label | ReadFileEx output argument |
| windows.cpp:179:10:179:16 | * ... | semmle.label | * ... |
| windows.cpp:189:21:189:26 | ReadFile output argument | semmle.label | ReadFile output argument |
| windows.cpp:190:5:190:14 | *overlapped [post update] [*hEvent] | semmle.label | *overlapped [post update] [*hEvent] |
| windows.cpp:190:5:190:56 | *... = ... | semmle.label | *... = ... |
| windows.cpp:192:53:192:63 | *& ... [*hEvent] | semmle.label | *& ... [*hEvent] |
| windows.cpp:198:21:198:26 | ReadFile output argument | semmle.label | ReadFile output argument |
| windows.cpp:199:5:199:14 | *overlapped [post update] [hEvent] | semmle.label | *overlapped [post update] [hEvent] |
| windows.cpp:199:5:199:57 | ... = ... | semmle.label | ... = ... |
| windows.cpp:201:53:201:63 | *& ... [hEvent] | semmle.label | *& ... [hEvent] |
| windows.cpp:209:84:209:89 | NtReadFile output argument | semmle.label | NtReadFile output argument |
| windows.cpp:211:10:211:16 | * ... | semmle.label | * ... |
| windows.cpp:286:23:286:35 | *call to MapViewOfFile | semmle.label | *call to MapViewOfFile |
| windows.cpp:286:23:286:35 | *call to MapViewOfFile | semmle.label | *call to MapViewOfFile |
| windows.cpp:287:20:287:52 | *pMapView | semmle.label | *pMapView |
| windows.cpp:289:10:289:16 | * ... | semmle.label | * ... |
| windows.cpp:293:23:293:36 | *call to MapViewOfFile2 | semmle.label | *call to MapViewOfFile2 |
| windows.cpp:293:23:293:36 | *call to MapViewOfFile2 | semmle.label | *call to MapViewOfFile2 |
| windows.cpp:294:20:294:52 | *pMapView | semmle.label | *pMapView |
| windows.cpp:296:10:296:16 | * ... | semmle.label | * ... |
| windows.cpp:302:23:302:36 | *call to MapViewOfFile3 | semmle.label | *call to MapViewOfFile3 |
| windows.cpp:302:23:302:36 | *call to MapViewOfFile3 | semmle.label | *call to MapViewOfFile3 |
| windows.cpp:303:20:303:52 | *pMapView | semmle.label | *pMapView |
| windows.cpp:305:10:305:16 | * ... | semmle.label | * ... |
| windows.cpp:311:23:311:43 | *call to MapViewOfFile3FromApp | semmle.label | *call to MapViewOfFile3FromApp |
| windows.cpp:311:23:311:43 | *call to MapViewOfFile3FromApp | semmle.label | *call to MapViewOfFile3FromApp |
| windows.cpp:312:20:312:52 | *pMapView | semmle.label | *pMapView |
| windows.cpp:314:10:314:16 | * ... | semmle.label | * ... |
| windows.cpp:318:23:318:37 | *call to MapViewOfFileEx | semmle.label | *call to MapViewOfFileEx |
| windows.cpp:318:23:318:37 | *call to MapViewOfFileEx | semmle.label | *call to MapViewOfFileEx |
| windows.cpp:319:20:319:52 | *pMapView | semmle.label | *pMapView |
| windows.cpp:321:10:321:16 | * ... | semmle.label | * ... |
| windows.cpp:325:23:325:42 | *call to MapViewOfFileFromApp | semmle.label | *call to MapViewOfFileFromApp |
| windows.cpp:325:23:325:42 | *call to MapViewOfFileFromApp | semmle.label | *call to MapViewOfFileFromApp |
| windows.cpp:326:20:326:52 | *pMapView | semmle.label | *pMapView |
| windows.cpp:328:10:328:16 | * ... | semmle.label | * ... |
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | semmle.label | *call to MapViewOfFileNuma2 |
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | semmle.label | *call to MapViewOfFileNuma2 |
| windows.cpp:333:20:333:52 | *pMapView | semmle.label | *pMapView |
| windows.cpp:335:10:335:16 | * ... | semmle.label | * ... |
subpaths
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | asio_streams.cpp:100:44:100:62 | call to buffer |
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual |
| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated |
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body |
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body |
| windows.cpp:27:36:27:38 | *cmd | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA |

View File

@@ -1,2 +1,19 @@
| asio_streams.cpp:87:34:87:44 | read_until output argument | remote |
| test.cpp:10:10:10:18 | call to ymlSource | local |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | local |
| windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local |
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local |
| windows.cpp:168:35:168:40 | ReadFile output argument | local |
| windows.cpp:177:23:177:28 | ReadFileEx output argument | local |
| windows.cpp:189:21:189:26 | ReadFile output argument | local |
| windows.cpp:192:23:192:29 | ReadFileEx output argument | local |
| windows.cpp:198:21:198:26 | ReadFile output argument | local |
| windows.cpp:201:23:201:29 | ReadFileEx output argument | local |
| windows.cpp:209:84:209:89 | NtReadFile output argument | local |
| windows.cpp:286:23:286:35 | *call to MapViewOfFile | local |
| windows.cpp:293:23:293:36 | *call to MapViewOfFile2 | local |
| windows.cpp:302:23:302:36 | *call to MapViewOfFile3 | local |
| windows.cpp:311:23:311:43 | *call to MapViewOfFile3FromApp | local |
| windows.cpp:318:23:318:37 | *call to MapViewOfFileEx | local |
| windows.cpp:325:23:325:42 | *call to MapViewOfFileFromApp | local |
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | local |

View File

@@ -5,3 +5,4 @@
| test.cpp:28:35:28:35 | 0 | test.cpp:28:11:28:33 | call to ymlStepManual_with_body |
| test.cpp:32:38:32:38 | 0 | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body |
| test.cpp:35:38:35:38 | x | test.cpp:35:11:35:36 | call to ymlStepGenerated_with_body |
| windows.cpp:27:36:27:38 | *cmd | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA |

View File

@@ -3771,3 +3771,7 @@
| Dubious signature "(wchar_t *)" in summary model. |
| Dubious signature "(wchar_t, const CStringT &)" in summary model. |
| Dubious signature "(wchar_t,const CStringT &)" in summary model. |
| Unrecognized input specification "Field[****hEvent]" in summary model. |
| Unrecognized input specification "Field[***hEvent]" in summary model. |
| Unrecognized output specification "Field[****hEvent]" in summary model. |
| Unrecognized output specification "Field[***hEvent]" in summary model. |

View File

@@ -0,0 +1,337 @@
void sink(char);
void sink(char*);
void sink(char**);
using HANDLE = void*;
using DWORD = unsigned long;
using LPCH = char*;
using LPSTR = char*;
using LPCSTR = const char*;
using LPVOID = void*;
using LPDWORD = unsigned long*;
using PVOID = void*;
using ULONG_PTR = unsigned long*;
using SIZE_T = decltype(sizeof(0));
LPSTR GetCommandLineA();
LPSTR* CommandLineToArgvA(LPSTR, int*);
LPCH GetEnvironmentStringsA();
DWORD GetEnvironmentVariableA(LPCSTR, LPSTR, DWORD);
void getCommandLine() {
char* cmd = GetCommandLineA();
sink(cmd);
sink(*cmd); // $ ir
int argc;
char** argv = CommandLineToArgvA(cmd, &argc);
sink(argv);
sink(argv[1]);
sink(*argv[1]); // $ ir
}
void getEnvironment() {
char* env = GetEnvironmentStringsA();
sink(env);
sink(*env); // $ ir
char buf[1024];
GetEnvironmentVariableA("FOO", buf, sizeof(buf));
sink(buf);
sink(*buf); // $ ir
}
typedef struct _OVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
} DUMMYSTRUCTNAME;
PVOID Pointer;
} DUMMYUNIONNAME;
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
using BOOL = int;
#define FILE_MAP_READ 0x0004
using ULONG64 = unsigned long long;
using ULONG = unsigned long;
using DWORD64 = unsigned long long;
#define MEM_EXTENDED_PARAMETER_TYPE_BITS 8
typedef struct MEM_EXTENDED_PARAMETER {
struct {
DWORD64 Type : MEM_EXTENDED_PARAMETER_TYPE_BITS;
DWORD64 Reserved : 64 - MEM_EXTENDED_PARAMETER_TYPE_BITS;
} DUMMYSTRUCTNAME;
union {
DWORD64 ULong64;
PVOID Pointer;
SIZE_T Size;
HANDLE Handle;
DWORD ULong;
} DUMMYUNIONNAME;
} MEM_EXTENDED_PARAMETER, *PMEM_EXTENDED_PARAMETER;
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);
using LPOVERLAPPED_COMPLETION_ROUTINE = void (*)(DWORD, DWORD, LPOVERLAPPED);
BOOL ReadFileEx(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPOVERLAPPED lpOverlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
using NTSTATUS = long;
using PIO_APC_ROUTINE = void (*)(struct _DEVICE_OBJECT*, struct _IRP*, PVOID);
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
} DUMMYUNIONNAME;
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
using LONGLONG = long long;
using LONG = long;
typedef struct _LARGE_INTEGER {
union {
struct {
ULONG LowPart;
LONG HighPart;
} DUMMYSTRUCTNAME;
LONGLONG QuadPart;
} DUMMYUNIONNAME;
} LARGE_INTEGER, *PLARGE_INTEGER;
using PULONG = unsigned long*;
NTSTATUS NtReadFile(
HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID Buffer,
ULONG Length,
PLARGE_INTEGER ByteOffset,
PULONG Key
);
void FileIOCompletionRoutine(
DWORD dwErrorCode,
DWORD dwNumberOfBytesTransfered,
LPOVERLAPPED lpOverlapped
) {
char* buffer = reinterpret_cast<char*>(lpOverlapped->hEvent);
sink(buffer);
sink(*buffer); // $ MISSING: ir
}
void FileIOCompletionRoutine2(
DWORD dwErrorCode,
DWORD dwNumberOfBytesTransfered,
LPOVERLAPPED lpOverlapped
) {
char* buffer = reinterpret_cast<char*>(lpOverlapped->hEvent);
sink(buffer);
sink(*buffer); // $ ir
}
void FileIOCompletionRoutine3(
DWORD dwErrorCode,
DWORD dwNumberOfBytesTransfered,
LPOVERLAPPED lpOverlapped
) {
char c = reinterpret_cast<char>(lpOverlapped->hEvent);
sink(c); // $ ir
}
void readFile(HANDLE hFile) {
{
char buffer[1024];
DWORD bytesRead;
OVERLAPPED overlapped;
BOOL result = ReadFile(hFile, buffer, sizeof(buffer), &bytesRead, &overlapped);
sink(buffer);
sink(*buffer); // $ ir
}
{
char buffer[1024];
OVERLAPPED overlapped;
overlapped.hEvent = reinterpret_cast<HANDLE>(buffer);
ReadFileEx(hFile, buffer, sizeof(buffer) - 1, &overlapped, FileIOCompletionRoutine);
sink(buffer);
sink(*buffer); // $ ir
char* p = reinterpret_cast<char*>(overlapped.hEvent);
sink(p);
sink(*p); // $ MISSING: ir
}
{
char buffer[1024];
OVERLAPPED overlapped;
ReadFile(hFile, buffer, sizeof(buffer), nullptr, nullptr);
overlapped.hEvent = reinterpret_cast<HANDLE>(buffer);
char buffer2[1024];
ReadFileEx(hFile, buffer2, sizeof(buffer2) - 1, &overlapped, FileIOCompletionRoutine2);
}
{
char buffer[1024];
OVERLAPPED overlapped;
ReadFile(hFile, buffer, sizeof(buffer), nullptr, nullptr);
overlapped.hEvent = reinterpret_cast<HANDLE>(*buffer);
char buffer2[1024];
ReadFileEx(hFile, buffer2, sizeof(buffer2) - 1, &overlapped, FileIOCompletionRoutine3);
}
{
char buffer[1024];
IO_STATUS_BLOCK ioStatusBlock;
LARGE_INTEGER byteOffset;
ULONG key;
NTSTATUS status = NtReadFile(hFile, nullptr, nullptr, nullptr, &ioStatusBlock, buffer, sizeof(buffer), &byteOffset, &key);
sink(buffer);
sink(*buffer); // $ ir
}
}
LPVOID MapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap
);
PVOID MapViewOfFile2(
HANDLE FileMappingHandle,
HANDLE ProcessHandle,
ULONG64 Offset,
PVOID BaseAddress,
SIZE_T ViewSize,
ULONG AllocationType,
ULONG PageProtection
);
PVOID MapViewOfFile3(
HANDLE FileMapping,
HANDLE Process,
PVOID BaseAddress,
ULONG64 Offset,
SIZE_T ViewSize,
ULONG AllocationType,
ULONG PageProtection,
MEM_EXTENDED_PARAMETER *ExtendedParameters,
ULONG ParameterCount
);
PVOID MapViewOfFile3FromApp(
HANDLE FileMapping,
HANDLE Process,
PVOID BaseAddress,
ULONG64 Offset,
SIZE_T ViewSize,
ULONG AllocationType,
ULONG PageProtection,
MEM_EXTENDED_PARAMETER *ExtendedParameters,
ULONG ParameterCount
);
LPVOID MapViewOfFileEx(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap,
LPVOID lpBaseAddress
);
PVOID MapViewOfFileFromApp(
HANDLE hFileMappingObject,
ULONG DesiredAccess,
ULONG64 FileOffset,
SIZE_T NumberOfBytesToMap
);
PVOID MapViewOfFileNuma2(
HANDLE FileMappingHandle,
HANDLE ProcessHandle,
ULONG64 Offset,
PVOID BaseAddress,
SIZE_T ViewSize,
ULONG AllocationType,
ULONG PageProtection,
ULONG PreferredNode
);
void mapViewOfFile(HANDLE hMapFile) {
{
LPVOID pMapView = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
char* buffer = reinterpret_cast<char*>(pMapView);
sink(buffer);
sink(*buffer); // $ ir
}
{
LPVOID pMapView = MapViewOfFile2(hMapFile, nullptr, 0, nullptr, 0, 0, 0);
char* buffer = reinterpret_cast<char*>(pMapView);
sink(buffer);
sink(*buffer); // $ ir
}
{
MEM_EXTENDED_PARAMETER extendedParams;
LPVOID pMapView = MapViewOfFile3(hMapFile, nullptr, 0, 0, 0, 0, 0, &extendedParams, 1);
char* buffer = reinterpret_cast<char*>(pMapView);
sink(buffer);
sink(*buffer); // $ ir
}
{
MEM_EXTENDED_PARAMETER extendedParams;
LPVOID pMapView = MapViewOfFile3FromApp(hMapFile, nullptr, 0, 0, 0, 0, 0, &extendedParams, 1);
char* buffer = reinterpret_cast<char*>(pMapView);
sink(buffer);
sink(*buffer); // $ ir
}
{
LPVOID pMapView = MapViewOfFileEx(hMapFile, FILE_MAP_READ, 0, 0, 0, nullptr);
char* buffer = reinterpret_cast<char*>(pMapView);
sink(buffer);
sink(*buffer); // $ ir
}
{
LPVOID pMapView = MapViewOfFileFromApp(hMapFile, FILE_MAP_READ, 0, 0);
char* buffer = reinterpret_cast<char*>(pMapView);
sink(buffer);
sink(*buffer); // $ ir
}
{
LPVOID pMapView = MapViewOfFileNuma2(hMapFile, nullptr, 0, nullptr, 0, 0, 0, 0);
char* buffer = reinterpret_cast<char*>(pMapView);
sink(buffer);
sink(*buffer); // $ ir
}
}

View File

@@ -56,9 +56,9 @@ void test_sources() {
sink(v_direct); // $ ir
sink(remoteMadSourceIndirect());
sink(*remoteMadSourceIndirect()); // $ MISSING: ir
sink(*remoteMadSourceIndirect()); // $ ir
sink(*remoteMadSourceDoubleIndirect());
sink(**remoteMadSourceDoubleIndirect()); // $ MISSING: ir
sink(**remoteMadSourceDoubleIndirect()); // $ ir
int a, b, c, d;
@@ -124,7 +124,7 @@ void test_sinks() {
// test sources + sinks together
madSinkArg0(localMadSource()); // $ ir
madSinkIndirectArg0(remoteMadSourceIndirect()); // $ MISSING: ir
madSinkIndirectArg0(remoteMadSourceIndirect()); // $ ir
madSinkVar = remoteMadSourceVar; // $ ir
*madSinkVarIndirect = remoteMadSourceVar; // $ MISSING: ir
}

View File

@@ -1,6 +1,6 @@
| test.cpp:3:13:3:13 | i |
| test.cpp:3:13:3:18 | ... <? ... |
| test.cpp:3:18:3:18 | j |
| test.cpp:4:13:4:13 | i |
| test.cpp:4:13:4:18 | ... >? ... |
| test.cpp:4:13:4:18 | ... <? ... |
| test.cpp:4:18:4:18 | j |
| test.cpp:5:13:5:13 | i |
| test.cpp:5:13:5:18 | ... >? ... |
| test.cpp:5:18:5:18 | j |

View File

@@ -1,3 +1,4 @@
// semmle-extractor-options: --gnu_version 40200
void f(int i, int j) {
int k = i <? j;

View File

@@ -113,7 +113,7 @@ namespace Semmle.Autobuild.CSharp
"buildless/mode-active",
"C# was extracted with build-mode set to 'none'",
visibility: new DiagnosticMessage.TspVisibility(statusPage: true, cliSummaryTable: true, telemetry: true),
markdownMessage: "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
markdownMessage: "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
severity: DiagnosticMessage.TspSeverity.Note
));

View File

@@ -4,11 +4,11 @@ Amazon.Lambda.Core,10,,,,,,,,,,,10,,,,,,,,,,,
Dapper,55,42,1,,,,,,,,,,55,,42,,,,,,,,1
ILCompiler,,,121,,,,,,,,,,,,,,,,,,,77,44
ILLink.RoslynAnalyzer,,,107,,,,,,,,,,,,,,,,,,,31,76
ILLink.Shared,,,37,,,,,,,,,,,,,,,,,,,11,26
ILLink.Shared,,,37,,,,,,,,,,,,,,,,,,,9,28
ILLink.Tasks,,,5,,,,,,,,,,,,,,,,,,,4,1
Internal.IL,,,54,,,,,,,,,,,,,,,,,,,28,26
Internal.Pgo,,,9,,,,,,,,,,,,,,,,,,,2,7
Internal.TypeSystem,,,342,,,,,,,,,,,,,,,,,,,205,137
Internal.TypeSystem,,,343,,,,,,,,,,,,,,,,,,,197,146
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,,,28,,,,,,,,,,
Microsoft.AspNetCore.Components,2,4,2,,,,,,,2,,,,,,,,,4,,,1,1
Microsoft.AspNetCore.Http,,,1,,,,,,,,,,,,,,,,,,,1,
@@ -21,7 +21,7 @@ Microsoft.DotNet.PlatformAbstractions,,,1,,,,,,,,,,,,,,,,,,,1,
Microsoft.EntityFrameworkCore,6,,12,,,,,,,,,,6,,,,,,,,,,12
Microsoft.Extensions.Caching.Distributed,,,3,,,,,,,,,,,,,,,,,,,,3
Microsoft.Extensions.Caching.Memory,,,37,,,,,,,,,,,,,,,,,,,5,32
Microsoft.Extensions.Configuration,,3,118,,,,,,,,,,,,,3,,,,,,41,77
Microsoft.Extensions.Configuration,,3,118,,,,,,,,,,,,,3,,,,,,39,79
Microsoft.Extensions.DependencyInjection,,,209,,,,,,,,,,,,,,,,,,,15,194
Microsoft.Extensions.DependencyModel,,1,57,,,,,,,,,,,,,1,,,,,,13,44
Microsoft.Extensions.Diagnostics.Metrics,,,14,,,,,,,,,,,,,,,,,,,1,13
@@ -37,10 +37,10 @@ Microsoft.JSInterop,2,,,,,,,,,,2,,,,,,,,,,,,
Microsoft.NET.Build.Tasks,,,5,,,,,,,,,,,,,,,,,,,3,2
Microsoft.VisualBasic,,,6,,,,,,,,,,,,,,,,,,,1,5
Microsoft.Win32,,4,2,,,,,,,,,,,,,,,,,,4,,2
Mono.Linker,,,278,,,,,,,,,,,,,,,,,,,130,148
Mono.Linker,,,278,,,,,,,,,,,,,,,,,,,127,151
MySql.Data.MySqlClient,48,,,,,,,,,,,,48,,,,,,,,,,
Newtonsoft.Json,,,91,,,,,,,,,,,,,,,,,,,73,18
ServiceStack,194,,7,27,,,,,75,,,,92,,,,,,,,,7,
SourceGenerators,,,5,,,,,,,,,,,,,,,,,,,,5
System,54,47,12111,,6,5,5,,,4,1,,33,2,,6,15,17,4,3,,5993,6118
System,54,47,12139,,6,5,5,,,4,1,,33,2,,6,15,17,4,3,,5903,6236
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,,,,,,
1 package sink source summary sink:code-injection sink:encryption-decryptor sink:encryption-encryptor sink:encryption-keyprop sink:encryption-symmetrickey sink:file-content-store sink:html-injection sink:js-injection sink:log-injection sink:sql-injection source:commandargs source:database source:environment source:file source:file-write source:remote source:stdin source:windows-registry summary:taint summary:value
4 Dapper 55 42 1 55 42 1
5 ILCompiler 121 77 44
6 ILLink.RoslynAnalyzer 107 31 76
7 ILLink.Shared 37 11 9 26 28
8 ILLink.Tasks 5 4 1
9 Internal.IL 54 28 26
10 Internal.Pgo 9 2 7
11 Internal.TypeSystem 342 343 205 197 137 146
12 Microsoft.ApplicationBlocks.Data 28 28
13 Microsoft.AspNetCore.Components 2 4 2 2 4 1 1
14 Microsoft.AspNetCore.Http 1 1
21 Microsoft.EntityFrameworkCore 6 12 6 12
22 Microsoft.Extensions.Caching.Distributed 3 3
23 Microsoft.Extensions.Caching.Memory 37 5 32
24 Microsoft.Extensions.Configuration 3 118 3 41 39 77 79
25 Microsoft.Extensions.DependencyInjection 209 15 194
26 Microsoft.Extensions.DependencyModel 1 57 1 13 44
27 Microsoft.Extensions.Diagnostics.Metrics 14 1 13
37 Microsoft.NET.Build.Tasks 5 3 2
38 Microsoft.VisualBasic 6 1 5
39 Microsoft.Win32 4 2 4 2
40 Mono.Linker 278 130 127 148 151
41 MySql.Data.MySqlClient 48 48
42 Newtonsoft.Json 91 73 18
43 ServiceStack 194 7 27 75 92 7
44 SourceGenerators 5 5
45 System 54 47 12111 12139 6 5 5 4 1 33 2 6 15 17 4 3 5993 5903 6118 6236
46 Windows.Security.Cryptography.Core 1 1

View File

@@ -8,7 +8,7 @@ C# framework & library support
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
System,"``System.*``, ``System``",47,12111,54,5
Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.AspNetCore.Components``, ``Microsoft.AspNetCore.Http``, ``Microsoft.AspNetCore.Mvc``, ``Microsoft.AspNetCore.WebUtilities``, ``Microsoft.CSharp``, ``Microsoft.Diagnostics.Tools.Pgo``, ``Microsoft.DotNet.Build.Tasks``, ``Microsoft.DotNet.PlatformAbstractions``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.Diagnostics.Metrics``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.JSInterop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",60,2252,152,4
Totals,,107,14370,400,9
System,"``System.*``, ``System``",47,12139,54,5
Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.AspNetCore.Components``, ``Microsoft.AspNetCore.Http``, ``Microsoft.AspNetCore.Mvc``, ``Microsoft.AspNetCore.WebUtilities``, ``Microsoft.CSharp``, ``Microsoft.Diagnostics.Tools.Pgo``, ``Microsoft.DotNet.Build.Tasks``, ``Microsoft.DotNet.PlatformAbstractions``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.Diagnostics.Metrics``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.JSInterop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",60,2253,152,4
Totals,,107,14399,400,9

View File

@@ -127,13 +127,13 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
public IList<string> GetNugetFeeds(string nugetConfig)
{
logger.LogInfo($"Getting Nuget feeds from '{nugetConfig}'...");
logger.LogInfo($"Getting NuGet feeds from '{nugetConfig}'...");
return GetResultList($"{nugetListSourceCommand} --configfile \"{nugetConfig}\"");
}
public IList<string> GetNugetFeedsFromFolder(string folderPath)
{
logger.LogInfo($"Getting Nuget feeds in folder '{folderPath}'...");
logger.LogInfo($"Getting NuGet feeds in folder '{folderPath}'...");
return GetResultList(nugetListSourceCommand, folderPath);
}

View File

@@ -55,7 +55,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
internal const string NugetFeedResponsivenessRequestCountForFallback = "CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK_FALLBACK_LIMIT";
/// <summary>
/// Specifies the NuGet feeds to use for fallback Nuget dependency fetching. The value is a space-separated list of feed URLs.
/// Specifies the NuGet feeds to use for fallback NuGet dependency fetching. The value is a space-separated list of feed URLs.
/// The default value is `https://api.nuget.org/v3/index.json`.
/// </summary>
public const string FallbackNugetFeeds = "CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_FALLBACK";

View File

@@ -135,16 +135,16 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
if (nugetPackageDllPaths.Count > 0)
{
logger.LogInfo($"Restored {nugetPackageDllPaths.Count} Nuget DLLs.");
logger.LogInfo($"Restored {nugetPackageDllPaths.Count} NuGet DLLs.");
}
if (excludedPaths.Count > 0)
{
logger.LogInfo($"Excluding {excludedPaths.Count} Nuget DLLs.");
logger.LogInfo($"Excluding {excludedPaths.Count} NuGet DLLs.");
}
foreach (var excludedPath in excludedPaths)
{
logger.LogInfo($"Excluded Nuget DLL: {excludedPath}");
logger.LogInfo($"Excluded NuGet DLL: {excludedPath}");
}
nugetPackageDllPaths.ExceptWith(excludedPaths);
@@ -152,7 +152,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
}
catch (Exception exc)
{
logger.LogError($"Failed to restore Nuget packages with nuget.exe: {exc.Message}");
logger.LogError($"Failed to restore NuGet packages with nuget.exe: {exc.Message}");
}
var restoredProjects = RestoreSolutions(out var container);
@@ -186,7 +186,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
if (fallbackFeeds.Count == 0)
{
fallbackFeeds.Add(PublicNugetOrgFeed);
logger.LogInfo($"No fallback Nuget feeds specified. Adding default feed: {PublicNugetOrgFeed}");
logger.LogInfo($"No fallback NuGet feeds specified. Adding default feed: {PublicNugetOrgFeed}");
var shouldAddNugetConfigFeeds = EnvironmentVariables.GetBooleanOptOut(EnvironmentVariableNames.AddNugetConfigFeedsToFallback);
logger.LogInfo($"Adding feeds from nuget.config to fallback restore: {shouldAddNugetConfigFeeds}");
@@ -196,23 +196,23 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
// There are some feeds in `feedsFromNugetConfigs` that have already been checked for reachability, we could skip those.
// But we might use different responsiveness testing settings when we try them in the fallback logic, so checking them again is safer.
fallbackFeeds.UnionWith(feedsFromNugetConfigs);
logger.LogInfo($"Using Nuget feeds from nuget.config files as fallback feeds: {string.Join(", ", feedsFromNugetConfigs.OrderBy(f => f))}");
logger.LogInfo($"Using NuGet feeds from nuget.config files as fallback feeds: {string.Join(", ", feedsFromNugetConfigs.OrderBy(f => f))}");
}
}
logger.LogInfo($"Checking fallback Nuget feed reachability on feeds: {string.Join(", ", fallbackFeeds.OrderBy(f => f))}");
logger.LogInfo($"Checking fallback NuGet feed reachability on feeds: {string.Join(", ", fallbackFeeds.OrderBy(f => f))}");
var (initialTimeout, tryCount) = GetFeedRequestSettings(isFallback: true);
var reachableFallbackFeeds = fallbackFeeds.Where(feed => IsFeedReachable(feed, initialTimeout, tryCount, allowExceptions: false)).ToList();
if (reachableFallbackFeeds.Count == 0)
{
logger.LogWarning("No fallback Nuget feeds are reachable.");
logger.LogWarning("No fallback NuGet feeds are reachable.");
}
else
{
logger.LogInfo($"Reachable fallback Nuget feeds: {string.Join(", ", reachableFallbackFeeds.OrderBy(f => f))}");
logger.LogInfo($"Reachable fallback NuGet feeds: {string.Join(", ", reachableFallbackFeeds.OrderBy(f => f))}");
}
compilationInfoContainer.CompilationInfos.Add(("Reachable fallback Nuget feed count", reachableFallbackFeeds.Count.ToString()));
compilationInfoContainer.CompilationInfos.Add(("Reachable fallback NuGet feed count", reachableFallbackFeeds.Count.ToString()));
return reachableFallbackFeeds;
}
@@ -331,7 +331,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
return DownloadMissingPackages(usedPackageNames, fallbackNugetFeeds: reachableFallbackFeeds);
}
logger.LogWarning("Skipping download of missing packages from specific feeds as no fallback Nuget feeds are reachable.");
logger.LogWarning("Skipping download of missing packages from specific feeds as no fallback NuGet feeds are reachable.");
return null;
}
@@ -624,7 +624,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private bool IsFeedReachable(string feed, int timeoutMilliSeconds, int tryCount, bool allowExceptions = true)
{
logger.LogInfo($"Checking if Nuget feed '{feed}' is reachable...");
logger.LogInfo($"Checking if NuGet feed '{feed}' is reachable...");
// Configure the HttpClient to be aware of the Dependabot Proxy, if used.
HttpClientHandler httpClientHandler = new();
@@ -662,7 +662,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
try
{
ExecuteGetRequest(feed, client, cts.Token).GetAwaiter().GetResult();
logger.LogInfo($"Querying Nuget feed '{feed}' succeeded.");
logger.LogInfo($"Querying NuGet feed '{feed}' succeeded.");
return true;
}
catch (Exception exc)
@@ -671,19 +671,19 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
tce.CancellationToken == cts.Token &&
cts.Token.IsCancellationRequested)
{
logger.LogInfo($"Didn't receive answer from Nuget feed '{feed}' in {timeoutMilliSeconds}ms.");
logger.LogInfo($"Didn't receive answer from NuGet feed '{feed}' in {timeoutMilliSeconds}ms.");
timeoutMilliSeconds *= 2;
continue;
}
// We're only interested in timeouts.
var start = allowExceptions ? "Considering" : "Not considering";
logger.LogInfo($"Querying Nuget feed '{feed}' failed in a timely manner. {start} the feed for use. The reason for the failure: {exc.Message}");
logger.LogInfo($"Querying NuGet feed '{feed}' failed in a timely manner. {start} the feed for use. The reason for the failure: {exc.Message}");
return allowExceptions;
}
}
logger.LogWarning($"Didn't receive answer from Nuget feed '{feed}'. Tried it {tryCount} times.");
logger.LogWarning($"Didn't receive answer from NuGet feed '{feed}'. Tried it {tryCount} times.");
return false;
}
@@ -694,20 +694,20 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
: int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessInitialTimeout), out timeoutMilliSeconds)
? timeoutMilliSeconds
: 1000;
logger.LogDebug($"Initial timeout for Nuget feed reachability check is {timeoutMilliSeconds}ms.");
logger.LogDebug($"Initial timeout for NuGet feed reachability check is {timeoutMilliSeconds}ms.");
int tryCount = isFallback && int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessRequestCountForFallback), out tryCount)
? tryCount
: int.TryParse(Environment.GetEnvironmentVariable(EnvironmentVariableNames.NugetFeedResponsivenessRequestCount), out tryCount)
? tryCount
: 4;
logger.LogDebug($"Number of tries for Nuget feed reachability check is {tryCount}.");
logger.LogDebug($"Number of tries for NuGet feed reachability check is {tryCount}.");
return (timeoutMilliSeconds, tryCount);
}
/// <summary>
/// Checks that we can connect to all Nuget feeds that are explicitly configured in configuration files
/// Checks that we can connect to all NuGet feeds that are explicitly configured in configuration files
/// as well as any private package registry feeds that are configured.
/// </summary>
/// <param name="explicitFeeds">Outputs the set of explicit feeds.</param>
@@ -727,28 +727,28 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var inheritedFeeds = allFeeds.Except(explicitFeeds).ToHashSet();
if (inheritedFeeds.Count > 0)
{
logger.LogInfo($"Inherited Nuget feeds (not checked for reachability): {string.Join(", ", inheritedFeeds.OrderBy(f => f))}");
compilationInfoContainer.CompilationInfos.Add(("Inherited Nuget feed count", inheritedFeeds.Count.ToString()));
logger.LogInfo($"Inherited NuGet feeds (not checked for reachability): {string.Join(", ", inheritedFeeds.OrderBy(f => f))}");
compilationInfoContainer.CompilationInfos.Add(("Inherited NuGet feed count", inheritedFeeds.Count.ToString()));
}
return allFeedsReachable;
}
/// <summary>
/// Checks that we can connect to the specified Nuget feeds.
/// Checks that we can connect to the specified NuGet feeds.
/// </summary>
/// <param name="feeds">The set of package feeds to check.</param>
/// <returns>True if all feeds are reachable or false otherwise.</returns>
private bool CheckSpecifiedFeeds(HashSet<string> feeds)
{
logger.LogInfo("Checking that Nuget feeds are reachable...");
logger.LogInfo("Checking that NuGet feeds are reachable...");
var excludedFeeds = EnvironmentVariables.GetURLs(EnvironmentVariableNames.ExcludedNugetFeedsFromResponsivenessCheck)
.ToHashSet();
if (excludedFeeds.Count > 0)
{
logger.LogInfo($"Excluded Nuget feeds from responsiveness check: {string.Join(", ", excludedFeeds.OrderBy(f => f))}");
logger.LogInfo($"Excluded NuGet feeds from responsiveness check: {string.Join(", ", excludedFeeds.OrderBy(f => f))}");
}
var (initialTimeout, tryCount) = GetFeedRequestSettings(isFallback: false);
@@ -756,17 +756,17 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
var allFeedsReachable = feeds.All(feed => excludedFeeds.Contains(feed) || IsFeedReachable(feed, initialTimeout, tryCount));
if (!allFeedsReachable)
{
logger.LogWarning("Found unreachable Nuget feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.");
logger.LogWarning("Found unreachable NuGet feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.");
diagnosticsWriter.AddEntry(new DiagnosticMessage(
Language.CSharp,
"buildless/unreachable-feed",
"Found unreachable Nuget feed in C# analysis with build-mode 'none'",
"Found unreachable NuGet feed in C# analysis with build-mode 'none'",
visibility: new DiagnosticMessage.TspVisibility(statusPage: true, cliSummaryTable: true, telemetry: true),
markdownMessage: "Found unreachable Nuget feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.",
markdownMessage: "Found unreachable NuGet feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.",
severity: DiagnosticMessage.TspSeverity.Note
));
}
compilationInfoContainer.CompilationInfos.Add(("All Nuget feeds reachable", allFeedsReachable ? "1" : "0"));
compilationInfoContainer.CompilationInfos.Add(("All NuGet feeds reachable", allFeedsReachable ? "1" : "0"));
return allFeedsReachable;
}
@@ -808,11 +808,11 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
if (explicitFeeds.Count > 0)
{
logger.LogInfo($"Found {explicitFeeds.Count} Nuget feeds in nuget.config files: {string.Join(", ", explicitFeeds.OrderBy(f => f))}");
logger.LogInfo($"Found {explicitFeeds.Count} NuGet feeds in nuget.config files: {string.Join(", ", explicitFeeds.OrderBy(f => f))}");
}
else
{
logger.LogDebug("No Nuget feeds found in nuget.config files.");
logger.LogDebug("No NuGet feeds found in nuget.config files.");
}
// todo: this could be improved.
@@ -844,7 +844,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
allFeeds = GetFeeds(() => dotnet.GetNugetFeedsFromFolder(this.fileProvider.SourceDir.FullName)).ToHashSet();
}
logger.LogInfo($"Found {allFeeds.Count} Nuget feeds (with inherited ones) in nuget.config files: {string.Join(", ", allFeeds.OrderBy(f => f))}");
logger.LogInfo($"Found {allFeeds.Count} NuGet feeds (with inherited ones) in nuget.config files: {string.Join(", ", allFeeds.OrderBy(f => f))}");
return (explicitFeeds, allFeeds);
}

View File

@@ -13,7 +13,7 @@
}
}
{
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
"severity": "note",
"source": {
"extractorName": "csharp",

View File

@@ -13,7 +13,7 @@
}
}
{
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
"severity": "note",
"source": {
"extractorName": "csharp",

View File

@@ -13,7 +13,7 @@
}
}
{
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
"severity": "note",
"source": {
"extractorName": "csharp",

View File

@@ -13,7 +13,7 @@
}
}
{
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
"severity": "note",
"source": {
"extractorName": "csharp",

View File

@@ -13,7 +13,7 @@
}
}
{
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
"severity": "note",
"source": {
"extractorName": "csharp",

View File

@@ -1,10 +1,10 @@
| All Nuget feeds reachable | 1.0 |
| All NuGet feeds reachable | 1.0 |
| Failed project restore with package source error | 0.0 |
| Failed solution restore with package source error | 0.0 |
| Inherited Nuget feed count | 1.0 |
| Inherited NuGet feed count | 1.0 |
| NuGet feed responsiveness checked | 1.0 |
| Project files on filesystem | 1.0 |
| Reachable fallback Nuget feed count | 1.0 |
| Reachable fallback NuGet feed count | 1.0 |
| Resource extraction enabled | 1.0 |
| Restored .NET framework variants | 1.0 |
| Restored projects through solution files | 0.0 |

View File

@@ -1,10 +1,10 @@
| All Nuget feeds reachable | 1.0 |
| All NuGet feeds reachable | 1.0 |
| Failed project restore with package source error | 0.0 |
| Failed solution restore with package source error | 0.0 |
| Inherited Nuget feed count | 1.0 |
| Inherited NuGet feed count | 1.0 |
| NuGet feed responsiveness checked | 1.0 |
| Project files on filesystem | 1.0 |
| Reachable fallback Nuget feed count | 1.0 |
| Reachable fallback NuGet feed count | 1.0 |
| Resource extraction enabled | 0.0 |
| Restored .NET framework variants | 1.0 |
| Restored projects through solution files | 0.0 |

View File

@@ -3,6 +3,7 @@ ql/csharp/ql/src/API Abuse/FormatInvalid.ql
ql/csharp/ql/src/API Abuse/NoDisposeCallOnLocalIDisposable.ql
ql/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql
ql/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql
ql/csharp/ql/src/Language Abuse/MissedReadonlyOpportunity.ql
ql/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql
ql/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql
ql/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql

View File

@@ -1,10 +1,10 @@
| All Nuget feeds reachable | 1.0 |
| All NuGet feeds reachable | 1.0 |
| Failed project restore with package source error | 1.0 |
| Failed solution restore with package source error | 0.0 |
| Fallback nuget restore | 1.0 |
| NuGet feed responsiveness checked | 1.0 |
| Project files on filesystem | 1.0 |
| Reachable fallback Nuget feed count | 1.0 |
| Reachable fallback NuGet feed count | 1.0 |
| Resolved assembly conflicts | 7.0 |
| Resource extraction enabled | 0.0 |
| Restored .NET framework variants | 0.0 |

View File

@@ -1,9 +1,9 @@
| All Nuget feeds reachable | 0.0 |
| All NuGet feeds reachable | 0.0 |
| Fallback nuget restore | 1.0 |
| Inherited Nuget feed count | 1.0 |
| Inherited NuGet feed count | 1.0 |
| NuGet feed responsiveness checked | 1.0 |
| Project files on filesystem | 1.0 |
| Reachable fallback Nuget feed count | 1.0 |
| Reachable fallback NuGet feed count | 1.0 |
| Resolved assembly conflicts | 7.0 |
| Resource extraction enabled | 0.0 |
| Restored .NET framework variants | 0.0 |

View File

@@ -13,7 +13,7 @@
}
}
{
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
"severity": "note",
"source": {
"extractorName": "csharp",
@@ -27,12 +27,12 @@
}
}
{
"markdownMessage": "Found unreachable Nuget feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.",
"markdownMessage": "Found unreachable NuGet feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.",
"severity": "note",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/buildless/unreachable-feed",
"name": "Found unreachable Nuget feed in C# analysis with build-mode 'none'"
"name": "Found unreachable NuGet feed in C# analysis with build-mode 'none'"
},
"visibility": {
"cliSummaryTable": true,

View File

@@ -4,7 +4,7 @@ import runs_on
@runs_on.posix
def test(codeql, csharp):
# os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK"] = "true" # Nuget feed check is enabled by default
# os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK"] = "true" # NuGet feed check is enabled by default
os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK_TIMEOUT"] = (
"1" # 1ms, the GET request should fail with such short timeout
)

View File

@@ -1,8 +1,8 @@
| All Nuget feeds reachable | 0.0 |
| All NuGet feeds reachable | 0.0 |
| Fallback nuget restore | 1.0 |
| NuGet feed responsiveness checked | 1.0 |
| Project files on filesystem | 1.0 |
| Reachable fallback Nuget feed count | 2.0 |
| Reachable fallback NuGet feed count | 2.0 |
| Resolved assembly conflicts | 7.0 |
| Resource extraction enabled | 0.0 |
| Restored .NET framework variants | 0.0 |

View File

@@ -13,7 +13,7 @@
}
}
{
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as Nuget and Dotnet CLIs, only contributing information about external dependencies.",
"markdownMessage": "C# was extracted with build-mode set to 'none'. This means that all C# source in the working directory will be scanned, with build tools, such as NuGet and dotnet CLIs, only contributing information about external dependencies.",
"severity": "note",
"source": {
"extractorName": "csharp",
@@ -27,12 +27,12 @@
}
}
{
"markdownMessage": "Found unreachable Nuget feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.",
"markdownMessage": "Found unreachable NuGet feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.",
"severity": "note",
"source": {
"extractorName": "csharp",
"id": "csharp/autobuilder/buildless/unreachable-feed",
"name": "Found unreachable Nuget feed in C# analysis with build-mode 'none'"
"name": "Found unreachable NuGet feed in C# analysis with build-mode 'none'"
},
"visibility": {
"cliSummaryTable": true,

View File

@@ -5,7 +5,7 @@ import runs_on
@runs_on.posix
def test(codeql, csharp):
# os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK"] = "true" # Nuget feed check is enabled by default
# os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK"] = "true" # NuGet feed check is enabled by default
os.environ["CODEQL_EXTRACTOR_CSHARP_BUILDLESS_NUGET_FEEDS_CHECK_TIMEOUT"] = (
"1" # 1ms, the GET request should fail with such short timeout
)

View File

@@ -17,7 +17,7 @@ private predicate valueFlowStepSsa(SsaVariable v, SsaReadPosition pos, Expr e, i
exists(Guard guard, boolean testIsTrue |
pos.hasReadOfVar(v) and
guard = eqFlowCond(v, e, delta, true, testIsTrue) and
guardDirectlyControlsSsaRead(guard, pos, testIsTrue)
guardControlsSsaRead(guard, pos, testIsTrue)
)
}

View File

@@ -1044,17 +1044,25 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
class Guard extends Guards::Guard {
/**
* Holds if the control flow branching from `bb1` is dependent on this guard,
* and that the edge from `bb1` to `bb2` corresponds to the evaluation of this
* guard to `branch`.
* Holds if the evaluation of this guard to `branch` corresponds to the edge
* from `bb1` to `bb2`.
*/
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
predicate hasBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
exists(ControlFlow::SuccessorTypes::ConditionalSuccessor s |
this.getAControlFlowNode() = bb1.getLastNode() and
bb2 = bb1.getASuccessorByType(s) and
s.getValue() = branch
)
}
/**
* Holds if this guard evaluating to `branch` controls the control-flow
* branch edge from `bb1` to `bb2`. That is, following the edge from
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
*/
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
this.hasBranchEdge(bb1, bb2, branch)
}
}
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */

View File

@@ -32,8 +32,6 @@ module Private {
class LeftShiftExpr = RU::ExprNode::LeftShiftExpr;
predicate guardDirectlyControlsSsaRead = RU::guardControlsSsaRead/3;
predicate guardControlsSsaRead = RU::guardControlsSsaRead/3;
predicate valueFlowStep = RU::valueFlowStep/3;

View File

@@ -8,6 +8,7 @@
* @id cs/missed-readonly-modifier
* @tags maintainability
* language-features
* quality
*/
import csharp
@@ -19,13 +20,17 @@ predicate defTargetsField(AssignableDefinition def, Field f) {
predicate isReadonlyCompatibleDefinition(AssignableDefinition def, Field f) {
defTargetsField(def, f) and
(
def.getEnclosingCallable().(Constructor).getDeclaringType() = f.getDeclaringType()
def.getEnclosingCallable().(StaticConstructor).getDeclaringType() = f.getDeclaringType()
or
def.getEnclosingCallable().(InstanceConstructor).getDeclaringType() = f.getDeclaringType() and
def.getTargetAccess().(QualifiableExpr).getQualifier() instanceof ThisAccess
or
def instanceof AssignableDefinitions::InitializerDefinition
)
}
predicate canBeReadonly(Field f) {
exists(Type t | t = f.getType() | not t instanceof Struct or t.(Struct).isReadonly()) and
forex(AssignableDefinition def | defTargetsField(def, f) | isReadonlyCompatibleDefinition(def, f))
}

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The precision of the query `cs/missed-readonly-modifier` has been improved. Some false positives related to static fields and struct type fields have been removed.

View File

@@ -1,23 +1,27 @@
class MissedReadonlyOpportunity<T>
{
public int Bad1;
public T Bad2;
public int Bad1; // $ Alert
public T Bad2; // $ Alert
public Immutable Bad3; // $ Alert
public readonly int Good1;
public readonly int Good2 = 0;
public const int Good3 = 0;
public int Good4;
public readonly T Good5;
public T Good6;
public Mutable Good7;
public MissedReadonlyOpportunity(int i, T t)
{
Bad1 = i;
Bad2 = t;
Bad3 = new Immutable();
Good1 = i;
Good2 = i;
Good4 = i;
Good5 = t;
Good6 = t;
Good7 = new Mutable();
}
public void M(int i)
@@ -27,3 +31,54 @@ class MissedReadonlyOpportunity<T>
x.Good6 = false;
}
}
struct Mutable
{
private int x;
public int Mutate()
{
x = x + 1;
return x;
}
}
readonly struct Immutable { }
class Tree
{
private Tree? Parent;
private Tree? Left; // $ Alert
private readonly Tree? Right;
public Tree(Tree left, Tree right)
{
this.Left = left;
this.Right = right;
left.Parent = this;
right.Parent = this;
}
public Tree()
{
Left = null;
Right = null;
}
}
class StaticFields
{
static int X; // $ Alert
static int Y;
// Static constructor
static StaticFields()
{
X = 0;
}
// Instance constructor
public StaticFields(int y)
{
Y = y;
}
}

View File

@@ -1,3 +1,6 @@
| MissedReadonlyOpportunity.cs:3:16:3:19 | Bad1 | Field 'Bad1' can be 'readonly'. |
| MissedReadonlyOpportunity.cs:4:14:4:17 | Bad2 | Field 'Bad2' can be 'readonly'. |
| MissedReadonlyOpportunity.cs:5:22:5:25 | Bad3 | Field 'Bad3' can be 'readonly'. |
| MissedReadonlyOpportunity.cs:50:19:50:22 | Left | Field 'Left' can be 'readonly'. |
| MissedReadonlyOpportunity.cs:70:16:70:16 | X | Field 'X' can be 'readonly'. |
| MissedReadonlyOpportunityBad.cs:3:9:3:13 | Field | Field 'Field' can be 'readonly'. |

View File

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

View File

@@ -1,6 +1,6 @@
class Bad
{
int Field;
int Field; // $ Alert
public Bad(int i)
{

View File

@@ -1,6 +1,6 @@
# Generate stubs for a single NuGet package
Stubs can be generated from Nuget packages with the `make_stubs_nuget.py` script.
Stubs can be generated from NuGet packages with the `make_stubs_nuget.py` script.
The following calls generate stubs for `Newtonsoft.Json`:
@@ -13,7 +13,7 @@ python3 make_stubs_nuget.py classlib Newtonsoft.Json 13.0.1 /Users/tmp/working-d
The output stubs are found in the `[DIR]/output/stubs` folder and can be copied over to `csharp/ql/test/resources/stubs`.
In some more involved cases the output files need to be edited. For example `ServiceStack` has Nuget dependencies, which
In some more involved cases the output files need to be edited. For example `ServiceStack` has NuGet dependencies, which
are included in the `Microsoft.NETCore.App` framework stub. These dependencies generate empty packages, which can be
removed. The `ProjectReference` entries referencing these removed empty packages also need to be deleted from the
`.csproj` files.

View File

@@ -54,9 +54,9 @@ ql/lib/go.dbscheme.stats: ql/lib/go.dbscheme build/stats/src.stamp extractor
codeql dataset measure -o $@ build/stats/database/db-go
test: all build/testdb/check-upgrade-path
codeql test run -j0 ql/test --search-path .. --consistency-queries ql/test/consistency --compilation-cache=$(cache) --dynamic-join-order-mode=$(rtjo)
codeql test run -j0 ql/test --search-path .. --check-diff-informed --consistency-queries ql/test/consistency --compilation-cache=$(cache) --dynamic-join-order-mode=$(rtjo) --check-databases --fail-on-trap-errors --check-undefined-labels --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition
# use GOOS=linux because GOOS=darwin GOARCH=386 is no longer supported
env GOOS=linux GOARCH=386 codeql$(EXE) test run -j0 ql/test/query-tests/Security/CWE-681 --search-path .. --consistency-queries ql/test/consistency --compilation-cache=$(cache) --dynamic-join-order-mode=$(rtjo)
env GOOS=linux GOARCH=386 codeql$(EXE) test run -j0 ql/test/query-tests/Security/CWE-681 --search-path .. --check-diff-informed --consistency-queries ql/test/consistency --compilation-cache=$(cache) --dynamic-join-order-mode=$(rtjo)
cd extractor; $(BAZEL) test ...
bash extractor-smoke-test/test.sh || (echo "Extractor smoke test FAILED"; exit 1)

View File

@@ -13,6 +13,7 @@ import (
"log"
"os"
"path/filepath"
"reflect"
"regexp"
"runtime"
"strconv"
@@ -773,18 +774,25 @@ func (extraction *Extraction) extractFileInfo(tw *trap.Writer, file string, isDu
var parentLbl trap.Label
for i, component := range components {
// displayPath is the same as rawPath except for root directories: if
// rawPath is "" then displayPath is "/"; if rawPath is "C:" then
// displayPath is "C:/".
var rawPath, displayPath string
if i == 0 {
if component == "" {
path = "/"
rawPath = component
if component == "" || regexp.MustCompile(`^[A-Za-z]:$`).MatchString(component) {
// Handle linux root and Windows drive letters by appending "/"
displayPath = rawPath + "/"
} else {
path = component
displayPath = rawPath
}
} else {
path = parentPath + "/" + component
rawPath = parentPath + "/" + component
displayPath = rawPath
}
if i == len(components)-1 {
lbl := tw.Labeler.FileLabelFor(file)
dbscheme.FilesTable.Emit(tw, lbl, path)
dbscheme.FilesTable.Emit(tw, lbl, displayPath)
dbscheme.ContainerParentTable.Emit(tw, parentLbl, lbl)
dbscheme.HasLocationTable.Emit(tw, lbl, emitLocation(tw, lbl, 0, 0, 0, 0))
extraction.Lock.Lock()
@@ -795,14 +803,12 @@ func (extraction *Extraction) extractFileInfo(tw *trap.Writer, file string, isDu
extraction.Lock.Unlock()
break
}
lbl := tw.Labeler.GlobalID(util.EscapeTrapSpecialChars(path) + ";folder")
dbscheme.FoldersTable.Emit(tw, lbl, path)
lbl := tw.Labeler.GlobalID(util.EscapeTrapSpecialChars(displayPath) + ";folder")
dbscheme.FoldersTable.Emit(tw, lbl, displayPath)
if i > 0 {
dbscheme.ContainerParentTable.Emit(tw, parentLbl, lbl)
}
if path != "/" {
parentPath = path
}
parentPath = rawPath
parentLbl = lbl
}
}
@@ -936,7 +942,7 @@ func emitScopeNodeInfo(tw *trap.Writer, nd ast.Node, lbl trap.Label) {
// extractExpr extracts AST information for the given expression and all its subexpressions
func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int, skipExtractingValue bool) {
if expr == nil {
if expr == nil || reflect.ValueOf(expr).IsNil() {
return
}
@@ -948,9 +954,6 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int, ski
case *ast.BadExpr:
kind = dbscheme.BadExpr.Index()
case *ast.Ident:
if expr == nil {
return
}
kind = dbscheme.IdentExpr.Index()
dbscheme.LiteralsTable.Emit(tw, lbl, expr.Name, expr.Name)
def := tw.Package.TypesInfo.Defs[expr]
@@ -984,15 +987,9 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int, ski
}
}
case *ast.Ellipsis:
if expr == nil {
return
}
kind = dbscheme.EllipsisExpr.Index()
extractExpr(tw, expr.Elt, lbl, 0, false)
case *ast.BasicLit:
if expr == nil {
return
}
value := ""
switch expr.Kind {
case token.INT:
@@ -1016,36 +1013,21 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int, ski
}
dbscheme.LiteralsTable.Emit(tw, lbl, value, expr.Value)
case *ast.FuncLit:
if expr == nil {
return
}
kind = dbscheme.FuncLitExpr.Index()
extractExpr(tw, expr.Type, lbl, 0, false)
extractStmt(tw, expr.Body, lbl, 1)
case *ast.CompositeLit:
if expr == nil {
return
}
kind = dbscheme.CompositeLitExpr.Index()
extractExpr(tw, expr.Type, lbl, 0, false)
extractExprs(tw, expr.Elts, lbl, 1, 1)
case *ast.ParenExpr:
if expr == nil {
return
}
kind = dbscheme.ParenExpr.Index()
extractExpr(tw, expr.X, lbl, 0, false)
case *ast.SelectorExpr:
if expr == nil {
return
}
kind = dbscheme.SelectorExpr.Index()
extractExpr(tw, expr.X, lbl, 0, false)
extractExpr(tw, expr.Sel, lbl, 1, false)
case *ast.IndexExpr:
if expr == nil {
return
}
typeofx := typeOf(tw, expr.X)
if typeofx == nil {
// We are missing type information for `expr.X`, so we cannot
@@ -1065,9 +1047,6 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int, ski
extractExpr(tw, expr.X, lbl, 0, false)
extractExpr(tw, expr.Index, lbl, 1, false)
case *ast.IndexListExpr:
if expr == nil {
return
}
typeofx := typeOf(tw, expr.X)
if typeofx == nil {
// We are missing type information for `expr.X`, so we cannot
@@ -1084,18 +1063,12 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int, ski
extractExpr(tw, expr.X, lbl, 0, false)
extractExprs(tw, expr.Indices, lbl, 1, 1)
case *ast.SliceExpr:
if expr == nil {
return
}
kind = dbscheme.SliceExpr.Index()
extractExpr(tw, expr.X, lbl, 0, false)
extractExpr(tw, expr.Low, lbl, 1, false)
extractExpr(tw, expr.High, lbl, 2, false)
extractExpr(tw, expr.Max, lbl, 3, false)
case *ast.TypeAssertExpr:
if expr == nil {
return
}
kind = dbscheme.TypeAssertExpr.Index()
extractExpr(tw, expr.X, lbl, 0, false)
// expr.Type can be `nil` if this is the `x.(type)` in a type switch.
@@ -1103,9 +1076,6 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int, ski
extractExpr(tw, expr.Type, lbl, 1, false)
}
case *ast.CallExpr:
if expr == nil {
return
}
kind = dbscheme.CallOrConversionExpr.Index()
extractExpr(tw, expr.Fun, lbl, 0, false)
extractExprs(tw, expr.Args, lbl, 1, 1)
@@ -1113,22 +1083,13 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int, ski
dbscheme.HasEllipsisTable.Emit(tw, lbl)
}
case *ast.StarExpr:
if expr == nil {
return
}
kind = dbscheme.StarExpr.Index()
extractExpr(tw, expr.X, lbl, 0, false)
case *ast.KeyValueExpr:
if expr == nil {
return
}
kind = dbscheme.KeyValueExpr.Index()
extractExpr(tw, expr.Key, lbl, 0, false)
extractExpr(tw, expr.Value, lbl, 1, false)
case *ast.UnaryExpr:
if expr == nil {
return
}
if expr.Op == token.TILDE {
kind = dbscheme.TypeSetLiteralExpr.Index()
} else {
@@ -1140,9 +1101,6 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int, ski
}
extractExpr(tw, expr.X, lbl, 0, false)
case *ast.BinaryExpr:
if expr == nil {
return
}
_, isUnionType := typeOf(tw, expr).(*types.Union)
if expr.Op == token.OR && isUnionType {
kind = dbscheme.TypeSetLiteralExpr.Index()
@@ -1158,46 +1116,28 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int, ski
extractExpr(tw, expr.Y, lbl, 1, false)
}
case *ast.ArrayType:
if expr == nil {
return
}
kind = dbscheme.ArrayTypeExpr.Index()
extractExpr(tw, expr.Len, lbl, 0, false)
extractExpr(tw, expr.Elt, lbl, 1, false)
case *ast.StructType:
if expr == nil {
return
}
kind = dbscheme.StructTypeExpr.Index()
extractFields(tw, expr.Fields, lbl, 0, 1)
case *ast.FuncType:
if expr == nil {
return
}
kind = dbscheme.FuncTypeExpr.Index()
extractFields(tw, expr.Params, lbl, 0, 1)
extractFields(tw, expr.Results, lbl, -1, -1)
emitScopeNodeInfo(tw, expr, lbl)
case *ast.InterfaceType:
if expr == nil {
return
}
kind = dbscheme.InterfaceTypeExpr.Index()
// expr.Methods contains methods, embedded interfaces and type set
// literals.
makeTypeSetLiteralsUnionTyped(tw, expr.Methods)
extractFields(tw, expr.Methods, lbl, 0, 1)
case *ast.MapType:
if expr == nil {
return
}
kind = dbscheme.MapTypeExpr.Index()
extractExpr(tw, expr.Key, lbl, 0, false)
extractExpr(tw, expr.Value, lbl, 1, false)
case *ast.ChanType:
if expr == nil {
return
}
tp := dbscheme.ChanTypeExprs[expr.Dir]
if tp == nil {
log.Fatalf("unsupported channel direction %v", expr.Dir)
@@ -1299,7 +1239,7 @@ func extractFields(tw *trap.Writer, fields *ast.FieldList, parent trap.Label, id
// extractStmt extracts AST information for a given statement and all other statements or expressions
// nested inside it
func extractStmt(tw *trap.Writer, stmt ast.Stmt, parent trap.Label, idx int) {
if stmt == nil {
if stmt == nil || reflect.ValueOf(stmt).IsNil() {
return
}
@@ -1309,37 +1249,22 @@ func extractStmt(tw *trap.Writer, stmt ast.Stmt, parent trap.Label, idx int) {
case *ast.BadStmt:
kind = dbscheme.BadStmtType.Index()
case *ast.DeclStmt:
if stmt == nil {
return
}
kind = dbscheme.DeclStmtType.Index()
extractDecl(tw, stmt.Decl, lbl, 0)
case *ast.EmptyStmt:
kind = dbscheme.EmptyStmtType.Index()
case *ast.LabeledStmt:
if stmt == nil {
return
}
kind = dbscheme.LabeledStmtType.Index()
extractExpr(tw, stmt.Label, lbl, 0, false)
extractStmt(tw, stmt.Stmt, lbl, 1)
case *ast.ExprStmt:
if stmt == nil {
return
}
kind = dbscheme.ExprStmtType.Index()
extractExpr(tw, stmt.X, lbl, 0, false)
case *ast.SendStmt:
if stmt == nil {
return
}
kind = dbscheme.SendStmtType.Index()
extractExpr(tw, stmt.Chan, lbl, 0, false)
extractExpr(tw, stmt.Value, lbl, 1, false)
case *ast.IncDecStmt:
if stmt == nil {
return
}
if stmt.Tok == token.INC {
kind = dbscheme.IncStmtType.Index()
} else if stmt.Tok == token.DEC {
@@ -1349,9 +1274,6 @@ func extractStmt(tw *trap.Writer, stmt ast.Stmt, parent trap.Label, idx int) {
}
extractExpr(tw, stmt.X, lbl, 0, false)
case *ast.AssignStmt:
if stmt == nil {
return
}
tp := dbscheme.AssignStmtTypes[stmt.Tok]
if tp == nil {
log.Fatalf("unsupported assignment statement with operator %v", stmt.Tok)
@@ -1360,24 +1282,15 @@ func extractStmt(tw *trap.Writer, stmt ast.Stmt, parent trap.Label, idx int) {
extractExprs(tw, stmt.Lhs, lbl, -1, -1)
extractExprs(tw, stmt.Rhs, lbl, 1, 1)
case *ast.GoStmt:
if stmt == nil {
return
}
kind = dbscheme.GoStmtType.Index()
extractExpr(tw, stmt.Call, lbl, 0, false)
case *ast.DeferStmt:
if stmt == nil {
return
}
kind = dbscheme.DeferStmtType.Index()
extractExpr(tw, stmt.Call, lbl, 0, false)
case *ast.ReturnStmt:
kind = dbscheme.ReturnStmtType.Index()
extractExprs(tw, stmt.Results, lbl, 0, 1)
case *ast.BranchStmt:
if stmt == nil {
return
}
switch stmt.Tok {
case token.BREAK:
kind = dbscheme.BreakStmtType.Index()
@@ -1392,16 +1305,10 @@ func extractStmt(tw *trap.Writer, stmt ast.Stmt, parent trap.Label, idx int) {
}
extractExpr(tw, stmt.Label, lbl, 0, false)
case *ast.BlockStmt:
if stmt == nil {
return
}
kind = dbscheme.BlockStmtType.Index()
extractStmts(tw, stmt.List, lbl, 0, 1)
emitScopeNodeInfo(tw, stmt, lbl)
case *ast.IfStmt:
if stmt == nil {
return
}
kind = dbscheme.IfStmtType.Index()
extractStmt(tw, stmt.Init, lbl, 0)
extractExpr(tw, stmt.Cond, lbl, 1, false)
@@ -1409,35 +1316,23 @@ func extractStmt(tw *trap.Writer, stmt ast.Stmt, parent trap.Label, idx int) {
extractStmt(tw, stmt.Else, lbl, 3)
emitScopeNodeInfo(tw, stmt, lbl)
case *ast.CaseClause:
if stmt == nil {
return
}
kind = dbscheme.CaseClauseType.Index()
extractExprs(tw, stmt.List, lbl, -1, -1)
extractStmts(tw, stmt.Body, lbl, 0, 1)
emitScopeNodeInfo(tw, stmt, lbl)
case *ast.SwitchStmt:
if stmt == nil {
return
}
kind = dbscheme.ExprSwitchStmtType.Index()
extractStmt(tw, stmt.Init, lbl, 0)
extractExpr(tw, stmt.Tag, lbl, 1, false)
extractStmt(tw, stmt.Body, lbl, 2)
emitScopeNodeInfo(tw, stmt, lbl)
case *ast.TypeSwitchStmt:
if stmt == nil {
return
}
kind = dbscheme.TypeSwitchStmtType.Index()
extractStmt(tw, stmt.Init, lbl, 0)
extractStmt(tw, stmt.Assign, lbl, 1)
extractStmt(tw, stmt.Body, lbl, 2)
emitScopeNodeInfo(tw, stmt, lbl)
case *ast.CommClause:
if stmt == nil {
return
}
kind = dbscheme.CommClauseType.Index()
extractStmt(tw, stmt.Comm, lbl, 0)
extractStmts(tw, stmt.Body, lbl, 1, 1)
@@ -1446,9 +1341,6 @@ func extractStmt(tw *trap.Writer, stmt ast.Stmt, parent trap.Label, idx int) {
kind = dbscheme.SelectStmtType.Index()
extractStmt(tw, stmt.Body, lbl, 0)
case *ast.ForStmt:
if stmt == nil {
return
}
kind = dbscheme.ForStmtType.Index()
extractStmt(tw, stmt.Init, lbl, 0)
extractExpr(tw, stmt.Cond, lbl, 1, false)
@@ -1456,9 +1348,6 @@ func extractStmt(tw *trap.Writer, stmt ast.Stmt, parent trap.Label, idx int) {
extractStmt(tw, stmt.Body, lbl, 3)
emitScopeNodeInfo(tw, stmt, lbl)
case *ast.RangeStmt:
if stmt == nil {
return
}
kind = dbscheme.RangeStmtType.Index()
extractExpr(tw, stmt.Key, lbl, 0, false)
extractExpr(tw, stmt.Value, lbl, 1, false)
@@ -1486,15 +1375,15 @@ func extractStmts(tw *trap.Writer, stmts []ast.Stmt, parent trap.Label, idx int,
// extractDecl extracts AST information for the given declaration
func extractDecl(tw *trap.Writer, decl ast.Decl, parent trap.Label, idx int) {
if reflect.ValueOf(decl).IsNil() {
return
}
lbl := tw.Labeler.LocalID(decl)
var kind int
switch decl := decl.(type) {
case *ast.BadDecl:
kind = dbscheme.BadDeclType.Index()
case *ast.GenDecl:
if decl == nil {
return
}
switch decl.Tok {
case token.IMPORT:
kind = dbscheme.ImportDeclType.Index()
@@ -1512,9 +1401,6 @@ func extractDecl(tw *trap.Writer, decl ast.Decl, parent trap.Label, idx int) {
}
extractDoc(tw, decl.Doc, lbl)
case *ast.FuncDecl:
if decl == nil {
return
}
kind = dbscheme.FuncDeclType.Index()
extractFields(tw, decl.Recv, lbl, -1, -1)
extractExpr(tw, decl.Name, lbl, 0, false)

View File

@@ -50,8 +50,8 @@ func parseRegistryConfigs(str string) ([]RegistryConfig, error) {
func getEnvVars() []string {
var result []string
if proxy_host, proxy_host_set := os.LookupEnv(PROXY_HOST); proxy_host_set {
if proxy_port, proxy_port_set := os.LookupEnv(PROXY_PORT); proxy_port_set {
if proxy_host, proxy_host_set := os.LookupEnv(PROXY_HOST); proxy_host_set && proxy_host != "" {
if proxy_port, proxy_port_set := os.LookupEnv(PROXY_PORT); proxy_port_set && proxy_port != "" {
proxy_address = fmt.Sprintf("http://%s:%s", proxy_host, proxy_port)
result = append(result, fmt.Sprintf("HTTP_PROXY=%s", proxy_address), fmt.Sprintf("HTTPS_PROXY=%s", proxy_address))
@@ -59,7 +59,7 @@ func getEnvVars() []string {
}
}
if proxy_cert, proxy_cert_set := os.LookupEnv(PROXY_CA_CERTIFICATE); proxy_cert_set {
if proxy_cert, proxy_cert_set := os.LookupEnv(PROXY_CA_CERTIFICATE); proxy_cert_set && proxy_cert != "" {
// Write the certificate to a temporary file
slog.Info("Found certificate")
@@ -82,7 +82,7 @@ func getEnvVars() []string {
}
}
if proxy_urls, proxy_urls_set := os.LookupEnv(PROXY_URLS); proxy_urls_set {
if proxy_urls, proxy_urls_set := os.LookupEnv(PROXY_URLS); proxy_urls_set && proxy_urls != "" {
val, err := parseRegistryConfigs(proxy_urls)
if err != nil {
slog.Error("Unable to parse proxy configurations", slog.String("error", err.Error()))

View File

@@ -20,10 +20,6 @@ numberOfTypeParameters
| genericFunctions.go:152:6:152:36 | multipleAnonymousTypeParamsType | 3 |
| genericFunctions.go:154:51:154:51 | f | 3 |
#select
| cmp.Compare | 0 | T | Ordered |
| cmp.Less | 0 | T | Ordered |
| cmp.Or | 0 | T | comparable |
| cmp.isNaN | 0 | T | Ordered |
| codeql-go-tests/function.EdgeConstraint | 0 | Node | interface { } |
| codeql-go-tests/function.Element | 0 | S | interface { } |
| codeql-go-tests/function.GenericFunctionInAnotherFile | 0 | T | interface { } |
@@ -57,205 +53,3 @@ numberOfTypeParameters
| codeql-go-tests/function.multipleAnonymousTypeParamsType.f | 0 | _ | interface { } |
| codeql-go-tests/function.multipleAnonymousTypeParamsType.f | 1 | _ | interface { string } |
| codeql-go-tests/function.multipleAnonymousTypeParamsType.f | 2 | _ | interface { } |
| github.com/anotherpkg.GenericFunctionInAnotherPackage | 0 | T | interface { } |
| internal/abi.Escape | 0 | T | interface { } |
| internal/bytealg.HashStr | 0 | T | interface { string \| []uint8 } |
| internal/bytealg.HashStrRev | 0 | T | interface { string \| []uint8 } |
| internal/bytealg.IndexRabinKarp | 0 | T | interface { string \| []uint8 } |
| internal/bytealg.LastIndexRabinKarp | 0 | T | interface { string \| []uint8 } |
| internal/poll.ignoringEINTR2 | 0 | T | interface { } |
| internal/runtime/atomic.Pointer.CompareAndSwap | 0 | T | interface { } |
| internal/runtime/atomic.Pointer.CompareAndSwapNoWB | 0 | T | interface { } |
| internal/runtime/atomic.Pointer.Load | 0 | T | interface { } |
| internal/runtime/atomic.Pointer.Store | 0 | T | interface { } |
| internal/runtime/atomic.Pointer.StoreNoWB | 0 | T | interface { } |
| internal/sync.HashTrieMap.All | 0 | K | comparable |
| internal/sync.HashTrieMap.All | 1 | V | interface { } |
| internal/sync.HashTrieMap.CompareAndDelete | 0 | K | comparable |
| internal/sync.HashTrieMap.CompareAndDelete | 1 | V | interface { } |
| internal/sync.HashTrieMap.CompareAndSwap | 0 | K | comparable |
| internal/sync.HashTrieMap.CompareAndSwap | 1 | V | interface { } |
| internal/sync.HashTrieMap.Delete | 0 | K | comparable |
| internal/sync.HashTrieMap.Load | 0 | K | comparable |
| internal/sync.HashTrieMap.Load | 1 | V | interface { } |
| internal/sync.HashTrieMap.LoadAndDelete | 0 | K | comparable |
| internal/sync.HashTrieMap.LoadAndDelete | 1 | V | interface { } |
| internal/sync.HashTrieMap.LoadOrStore | 0 | K | comparable |
| internal/sync.HashTrieMap.LoadOrStore | 1 | V | interface { } |
| internal/sync.HashTrieMap.Range | 0 | K | comparable |
| internal/sync.HashTrieMap.Range | 1 | V | interface { } |
| internal/sync.HashTrieMap.Store | 0 | K | comparable |
| internal/sync.HashTrieMap.Store | 1 | V | interface { } |
| internal/sync.HashTrieMap.Swap | 0 | K | comparable |
| internal/sync.HashTrieMap.Swap | 1 | V | interface { } |
| internal/sync.HashTrieMap.find | 0 | K | comparable |
| internal/sync.HashTrieMap.find | 1 | V | interface { } |
| internal/sync.HashTrieMap.iter | 0 | K | comparable |
| internal/sync.HashTrieMap.iter | 1 | V | interface { } |
| internal/sync.entry | 0 | K | comparable |
| internal/sync.entry | 1 | V | interface { } |
| internal/sync.entry.compareAndDelete | 0 | K | comparable |
| internal/sync.entry.compareAndDelete | 1 | V | interface { } |
| internal/sync.entry.compareAndSwap | 0 | K | comparable |
| internal/sync.entry.compareAndSwap | 1 | V | interface { } |
| internal/sync.entry.loadAndDelete | 0 | K | comparable |
| internal/sync.entry.loadAndDelete | 1 | V | interface { } |
| internal/sync.entry.lookup | 0 | K | comparable |
| internal/sync.entry.lookup | 1 | V | interface { } |
| internal/sync.entry.lookupWithValue | 0 | K | comparable |
| internal/sync.entry.lookupWithValue | 1 | V | interface { } |
| internal/sync.entry.swap | 0 | K | comparable |
| internal/sync.entry.swap | 1 | V | interface { } |
| internal/sync.newEntryNode | 0 | K | comparable |
| internal/sync.newEntryNode | 1 | V | interface { } |
| iter.Pull | 0 | V | interface { } |
| iter.Pull2 | 0 | K | interface { } |
| iter.Pull2 | 1 | V | interface { } |
| iter.Seq | 0 | V | interface { } |
| iter.Seq2 | 0 | K | interface { } |
| iter.Seq2 | 1 | V | interface { } |
| os.doInRoot | 0 | T | interface { } |
| os.ignoringEINTR2 | 0 | T | interface { } |
| reflect.rangeNum | 1 | N | interface { int64 \| uint64 } |
| runtime.AddCleanup | 0 | T | interface { } |
| runtime.AddCleanup | 1 | S | interface { } |
| runtime.fandbits | 0 | F | floaty |
| runtime.fmax | 0 | F | floaty |
| runtime.fmin | 0 | F | floaty |
| runtime.forbits | 0 | F | floaty |
| runtime.noEscapePtr | 0 | T | interface { } |
| slices.All | 0 | Slice | interface { ~[]E } |
| slices.All | 1 | E | interface { } |
| slices.AppendSeq | 0 | Slice | interface { ~[]E } |
| slices.AppendSeq | 1 | E | interface { } |
| slices.Backward | 0 | Slice | interface { ~[]E } |
| slices.Backward | 1 | E | interface { } |
| slices.BinarySearch | 0 | S | interface { ~[]E } |
| slices.BinarySearch | 1 | E | Ordered |
| slices.BinarySearchFunc | 0 | S | interface { ~[]E } |
| slices.BinarySearchFunc | 1 | E | interface { } |
| slices.BinarySearchFunc | 2 | T | interface { } |
| slices.Chunk | 0 | Slice | interface { ~[]E } |
| slices.Chunk | 1 | E | interface { } |
| slices.Clip | 0 | S | interface { ~[]E } |
| slices.Clip | 1 | E | interface { } |
| slices.Clone | 0 | S | interface { ~[]E } |
| slices.Clone | 1 | E | interface { } |
| slices.Collect | 0 | E | interface { } |
| slices.Compact | 0 | S | interface { ~[]E } |
| slices.Compact | 1 | E | comparable |
| slices.CompactFunc | 0 | S | interface { ~[]E } |
| slices.CompactFunc | 1 | E | interface { } |
| slices.Compare | 0 | S | interface { ~[]E } |
| slices.Compare | 1 | E | Ordered |
| slices.CompareFunc | 0 | S1 | interface { ~[]E1 } |
| slices.CompareFunc | 1 | S2 | interface { ~[]E2 } |
| slices.CompareFunc | 2 | E1 | interface { } |
| slices.CompareFunc | 3 | E2 | interface { } |
| slices.Concat | 0 | S | interface { ~[]E } |
| slices.Concat | 1 | E | interface { } |
| slices.Contains | 0 | S | interface { ~[]E } |
| slices.Contains | 1 | E | comparable |
| slices.ContainsFunc | 0 | S | interface { ~[]E } |
| slices.ContainsFunc | 1 | E | interface { } |
| slices.Delete | 0 | S | interface { ~[]E } |
| slices.Delete | 1 | E | interface { } |
| slices.DeleteFunc | 0 | S | interface { ~[]E } |
| slices.DeleteFunc | 1 | E | interface { } |
| slices.Equal | 0 | S | interface { ~[]E } |
| slices.Equal | 1 | E | comparable |
| slices.EqualFunc | 0 | S1 | interface { ~[]E1 } |
| slices.EqualFunc | 1 | S2 | interface { ~[]E2 } |
| slices.EqualFunc | 2 | E1 | interface { } |
| slices.EqualFunc | 3 | E2 | interface { } |
| slices.Grow | 0 | S | interface { ~[]E } |
| slices.Grow | 1 | E | interface { } |
| slices.Index | 0 | S | interface { ~[]E } |
| slices.Index | 1 | E | comparable |
| slices.IndexFunc | 0 | S | interface { ~[]E } |
| slices.IndexFunc | 1 | E | interface { } |
| slices.Insert | 0 | S | interface { ~[]E } |
| slices.Insert | 1 | E | interface { } |
| slices.IsSorted | 0 | S | interface { ~[]E } |
| slices.IsSorted | 1 | E | Ordered |
| slices.IsSortedFunc | 0 | S | interface { ~[]E } |
| slices.IsSortedFunc | 1 | E | interface { } |
| slices.Max | 0 | S | interface { ~[]E } |
| slices.Max | 1 | E | Ordered |
| slices.MaxFunc | 0 | S | interface { ~[]E } |
| slices.MaxFunc | 1 | E | interface { } |
| slices.Min | 0 | S | interface { ~[]E } |
| slices.Min | 1 | E | Ordered |
| slices.MinFunc | 0 | S | interface { ~[]E } |
| slices.MinFunc | 1 | E | interface { } |
| slices.Repeat | 0 | S | interface { ~[]E } |
| slices.Repeat | 1 | E | interface { } |
| slices.Replace | 0 | S | interface { ~[]E } |
| slices.Replace | 1 | E | interface { } |
| slices.Reverse | 0 | S | interface { ~[]E } |
| slices.Reverse | 1 | E | interface { } |
| slices.Sort | 0 | S | interface { ~[]E } |
| slices.Sort | 1 | E | Ordered |
| slices.SortFunc | 0 | S | interface { ~[]E } |
| slices.SortFunc | 1 | E | interface { } |
| slices.SortStableFunc | 0 | S | interface { ~[]E } |
| slices.SortStableFunc | 1 | E | interface { } |
| slices.Sorted | 0 | E | Ordered |
| slices.SortedFunc | 0 | E | interface { } |
| slices.SortedStableFunc | 0 | E | interface { } |
| slices.Values | 0 | Slice | interface { ~[]E } |
| slices.Values | 1 | E | interface { } |
| slices.breakPatternsCmpFunc | 0 | E | interface { } |
| slices.breakPatternsOrdered | 0 | E | Ordered |
| slices.choosePivotCmpFunc | 0 | E | interface { } |
| slices.choosePivotOrdered | 0 | E | Ordered |
| slices.heapSortCmpFunc | 0 | E | interface { } |
| slices.heapSortOrdered | 0 | E | Ordered |
| slices.insertionSortCmpFunc | 0 | E | interface { } |
| slices.insertionSortOrdered | 0 | E | Ordered |
| slices.isNaN | 0 | T | Ordered |
| slices.medianAdjacentCmpFunc | 0 | E | interface { } |
| slices.medianAdjacentOrdered | 0 | E | Ordered |
| slices.medianCmpFunc | 0 | E | interface { } |
| slices.medianOrdered | 0 | E | Ordered |
| slices.order2CmpFunc | 0 | E | interface { } |
| slices.order2Ordered | 0 | E | Ordered |
| slices.overlaps | 0 | E | interface { } |
| slices.partialInsertionSortCmpFunc | 0 | E | interface { } |
| slices.partialInsertionSortOrdered | 0 | E | Ordered |
| slices.partitionCmpFunc | 0 | E | interface { } |
| slices.partitionEqualCmpFunc | 0 | E | interface { } |
| slices.partitionEqualOrdered | 0 | E | Ordered |
| slices.partitionOrdered | 0 | E | Ordered |
| slices.pdqsortCmpFunc | 0 | E | interface { } |
| slices.pdqsortOrdered | 0 | E | Ordered |
| slices.reverseRangeCmpFunc | 0 | E | interface { } |
| slices.reverseRangeOrdered | 0 | E | Ordered |
| slices.rotateCmpFunc | 0 | E | interface { } |
| slices.rotateLeft | 0 | E | interface { } |
| slices.rotateOrdered | 0 | E | Ordered |
| slices.rotateRight | 0 | E | interface { } |
| slices.siftDownCmpFunc | 0 | E | interface { } |
| slices.siftDownOrdered | 0 | E | Ordered |
| slices.stableCmpFunc | 0 | E | interface { } |
| slices.stableOrdered | 0 | E | Ordered |
| slices.startIdx | 0 | E | interface { } |
| slices.swapRangeCmpFunc | 0 | E | interface { } |
| slices.swapRangeOrdered | 0 | E | Ordered |
| slices.symMergeCmpFunc | 0 | E | interface { } |
| slices.symMergeOrdered | 0 | E | Ordered |
| strconv.bsearch | 0 | S | interface { ~[]E } |
| strconv.bsearch | 1 | E | interface { ~uint16 \| ~uint32 } |
| sync.OnceValue | 0 | T | interface { } |
| sync.OnceValues | 0 | T1 | interface { } |
| sync.OnceValues | 1 | T2 | interface { } |
| sync/atomic.Pointer | 0 | T | interface { } |
| sync/atomic.Pointer.CompareAndSwap | 0 | T | interface { } |
| sync/atomic.Pointer.Load | 0 | T | interface { } |
| sync/atomic.Pointer.Store | 0 | T | interface { } |
| sync/atomic.Pointer.Swap | 0 | T | interface { } |
| time.atoi | 0 | bytes | interface { []uint8 \| string } |
| time.isDigit | 0 | bytes | interface { []uint8 \| string } |
| time.leadingInt | 0 | bytes | interface { []uint8 \| string } |
| time.parseNanoseconds | 0 | bytes | interface { []uint8 \| string } |
| time.parseRFC3339 | 0 | bytes | interface { []uint8 \| string } |

View File

@@ -6,5 +6,9 @@ query predicate numberOfTypeParameters(TypeParamParentEntity parent, int n) {
}
from TypeParamType tpt, TypeParamParentEntity ty
where ty = tpt.getParent()
where
ty = tpt.getParent() and
// Note that we cannot use the location of `tpt` itself as we currently fail
// to extract an object for type parameters for methods on generic structs.
exists(ty.getLocation())
select ty.getQualifiedName(), tpt.getIndex(), tpt.getParamName(), tpt.getConstraint().pp()

View File

@@ -1,3 +1,4 @@
| greet.go:6:2:6:6 | myfmt | greet.go:3:8:3:12 | myfmt | V |
| main.go:6:26:6:28 | who | main.go:5:12:5:14 | who | V |
| main.go:11:2:11:6 | greet | main.go:5:6:5:10 | greet | V |
| main.go:11:8:11:12 | world | main.go:10:2:10:6 | world | V |

View File

@@ -1,7 +1,7 @@
package main
import "fmt"
import myfmt "fmt"
func greet2() {
fmt.Println("Hello world!")
myfmt.Println("Hello world!")
}

View File

@@ -145,7 +145,7 @@ private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pre
* Evaluating a switch case to true corresponds to taking that switch case, and
* evaluating it to false corresponds to taking some other branch.
*/
class Guard extends ExprParent {
final class Guard extends ExprParent {
Guard() {
this.(Expr).getType() instanceof BooleanType and not this instanceof BooleanLiteral
or
@@ -272,6 +272,15 @@ class Guard extends ExprParent {
preconditionControls(this, controlled, branch)
}
/**
* Holds if this guard evaluating to `branch` controls the control-flow
* branch edge from `bb1` to `bb2`. That is, following the edge from
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
*/
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
guardControlsBranchEdge_v3(this, bb1, bb2, branch)
}
/**
* Holds if this guard evaluating to `branch` directly or indirectly controls
* the block `controlled`. That is, the evaluation of `controlled` is
@@ -351,6 +360,51 @@ private predicate guardControls_v3(Guard guard, BasicBlock controlled, boolean b
)
}
pragma[nomagic]
private predicate guardControlsBranchEdge_v2(
Guard guard, BasicBlock bb1, BasicBlock bb2, boolean branch
) {
guard.hasBranchEdge(bb1, bb2, branch)
or
exists(Guard g, boolean b |
guardControlsBranchEdge_v2(g, bb1, bb2, b) and
implies_v2(g, b, guard, branch)
)
}
pragma[nomagic]
private predicate guardControlsBranchEdge_v3(
Guard guard, BasicBlock bb1, BasicBlock bb2, boolean branch
) {
guard.hasBranchEdge(bb1, bb2, branch)
or
exists(Guard g, boolean b |
guardControlsBranchEdge_v3(g, bb1, bb2, b) and
implies_v3(g, b, guard, branch)
)
}
/** INTERNAL: Use `Guard` instead. */
final class Guard_v2 extends Guard {
/**
* Holds if this guard evaluating to `branch` controls the control-flow
* branch edge from `bb1` to `bb2`. That is, following the edge from
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
*/
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
guardControlsBranchEdge_v2(this, bb1, bb2, branch)
}
/**
* Holds if this guard evaluating to `branch` directly or indirectly controls
* the block `controlled`. That is, the evaluation of `controlled` is
* dominated by this guard evaluating to `branch`.
*/
predicate controls(BasicBlock controlled, boolean branch) {
guardControls_v2(this, controlled, branch)
}
}
private predicate equalityGuard(Guard g, Expr e1, Expr e2, boolean polarity) {
exists(EqualityTest eqtest |
eqtest = g and

View File

@@ -17,7 +17,7 @@ private predicate valueFlowStepSsa(SsaVariable v, SsaReadPosition pos, Expr e, i
exists(Guard guard, boolean testIsTrue |
pos.hasReadOfVar(v) and
guard = eqFlowCond(v, e, delta, true, testIsTrue) and
guardDirectlyControlsSsaRead(guard, pos, testIsTrue)
guardControlsSsaRead(guard, pos, testIsTrue)
)
}

View File

@@ -219,16 +219,10 @@ module Sem implements Semantic<Location> {
int getBlockId1(BasicBlock bb) { idOf(bb, result) }
final private class FinalGuard = GL::Guard;
class Guard extends FinalGuard {
class Guard extends GL::Guard_v2 {
Expr asExpr() { result = this }
}
predicate implies_v2(Guard g1, boolean b1, Guard g2, boolean b2) {
GL::implies_v2(g1, b1, g2, b2)
}
class Type = J::Type;
class IntegerType extends J::IntegralType {

View File

@@ -19,8 +19,6 @@ predicate ssaUpdateStep = U::ssaUpdateStep/3;
predicate valueFlowStep = U::valueFlowStep/3;
predicate guardDirectlyControlsSsaRead = U::guardDirectlyControlsSsaRead/3;
predicate guardControlsSsaRead = U::guardControlsSsaRead/3;
predicate eqFlowCond = U::eqFlowCond/5;

View File

@@ -654,16 +654,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
def instanceof SsaUncertainImplicitUpdate
}
class Guard extends Guards::Guard {
/**
* Holds if the control flow branching from `bb1` is dependent on this guard,
* and that the edge from `bb1` to `bb2` corresponds to the evaluation of this
* guard to `branch`.
*/
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
super.hasBranchEdge(bb1, bb2, branch)
}
}
class Guard = Guards::Guard;
/** Holds if the guard `guard` directly controls block `bb` upon evaluating to `branch`. */
predicate guardDirectlyControlsBlock(Guard guard, BasicBlock bb, boolean branch) {

View File

@@ -4,7 +4,6 @@ module Private {
private import semmle.code.java.dataflow.RangeUtils as RU
private import semmle.code.java.controlflow.Guards as G
private import semmle.code.java.controlflow.BasicBlocks as BB
private import semmle.code.java.controlflow.internal.GuardsLogic as GL
private import SsaReadPositionCommon
class BasicBlock = BB::BasicBlock;
@@ -15,7 +14,7 @@ module Private {
class Expr = J::Expr;
class Guard = G::Guard;
class Guard = G::Guard_v2;
class ConstantIntegerExpr = RU::ConstantIntegerExpr;
@@ -101,29 +100,17 @@ module Private {
}
}
/**
* Holds if `guard` directly controls the position `controlled` with the
* value `testIsTrue`.
*/
pragma[nomagic]
predicate guardDirectlyControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
guard.directlyControls(controlled.(SsaReadPositionBlock).getBlock(), testIsTrue)
or
exists(SsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
guard.directlyControls(controlledEdge.getOrigBlock(), testIsTrue) or
guard.hasBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(), testIsTrue)
)
}
/**
* Holds if `guard` controls the position `controlled` with the value `testIsTrue`.
*/
predicate guardControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
guardDirectlyControlsSsaRead(guard, controlled, testIsTrue)
guard.controls(controlled.(SsaReadPositionBlock).getBlock(), testIsTrue)
or
exists(Guard guard0, boolean testIsTrue0 |
GL::implies_v2(guard0, testIsTrue0, guard, testIsTrue) and
guardControlsSsaRead(guard0, controlled, testIsTrue0)
exists(SsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
guard.controls(controlledEdge.getOrigBlock(), testIsTrue) or
guard
.controlsBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(),
testIsTrue)
)
}

View File

@@ -7,13 +7,12 @@ module Private {
private import semmle.code.java.dataflow.SSA as Ssa
private import semmle.code.java.controlflow.Guards as G
private import SsaReadPositionCommon
private import semmle.code.java.controlflow.internal.GuardsLogic as GL
private import Sign
import Impl
class ConstantIntegerExpr = RU::ConstantIntegerExpr;
class Guard = G::Guard;
class Guard = G::Guard_v2;
class SsaVariable = Ssa::SsaVariable;
@@ -170,31 +169,17 @@ module Private {
predicate ssaRead = RU::ssaRead/2;
/**
* Holds if `guard` directly controls the position `controlled` with the
* value `testIsTrue`.
*/
pragma[nomagic]
private predicate guardDirectlyControlsSsaRead(
Guard guard, SsaReadPosition controlled, boolean testIsTrue
) {
guard.directlyControls(controlled.(SsaReadPositionBlock).getBlock(), testIsTrue)
or
exists(SsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
guard.directlyControls(controlledEdge.getOrigBlock(), testIsTrue) or
guard.hasBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(), testIsTrue)
)
}
/**
* Holds if `guard` controls the position `controlled` with the value `testIsTrue`.
*/
predicate guardControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
guardDirectlyControlsSsaRead(guard, controlled, testIsTrue)
guard.controls(controlled.(SsaReadPositionBlock).getBlock(), testIsTrue)
or
exists(Guard guard0, boolean testIsTrue0 |
GL::implies_v2(guard0, testIsTrue0, guard, testIsTrue) and
guardControlsSsaRead(guard0, controlled, testIsTrue0)
exists(SsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
guard.controls(controlledEdge.getOrigBlock(), testIsTrue) or
guard
.controlsBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(),
testIsTrue)
)
}
}

View File

@@ -75,11 +75,10 @@ module SsaDataflowInput implements DataFlowIntegrationInputSig {
Guard() { this = any(js::ConditionGuardNode g).getTest() }
/**
* Holds if the control flow branching from `bb1` is dependent on this guard,
* and that the edge from `bb1` to `bb2` corresponds to the evaluation of this
* guard to `branch`.
* Holds if the evaluation of this guard to `branch` corresponds to the edge
* from `bb1` to `bb2`.
*/
predicate controlsBranchEdge(js::BasicBlock bb1, js::BasicBlock bb2, boolean branch) {
predicate hasBranchEdge(js::BasicBlock bb1, js::BasicBlock bb2, boolean branch) {
exists(js::ConditionGuardNode g |
g.getTest() = this and
bb1 = this.getBasicBlock() and
@@ -87,6 +86,15 @@ module SsaDataflowInput implements DataFlowIntegrationInputSig {
branch = g.getOutcome()
)
}
/**
* Holds if this guard evaluating to `branch` controls the control-flow
* branch edge from `bb1` to `bb2`. That is, following the edge from
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
*/
predicate controlsBranchEdge(js::BasicBlock bb1, js::BasicBlock bb2, boolean branch) {
this.hasBranchEdge(bb1, bb2, branch)
}
}
pragma[inline]

View File

@@ -1,4 +1,138 @@
- description: Security-and-quality queries for JavaScript
- queries: .
- apply: security-and-quality-selectors.yml
from: codeql/suite-helpers
- include:
kind:
- problem
- path-problem
precision:
- high
- very-high
tags contain:
- security
- include:
kind:
- problem
- path-problem
precision: medium
problem.severity:
- error
- warning
tags contain:
- security
- include:
id:
- js/node/assignment-to-exports-variable
- js/node/missing-exports-qualifier
- js/angular/duplicate-dependency
- js/angular/missing-explicit-injection
- js/angular/dependency-injection-mismatch
- js/angular/incompatible-service
- js/angular/expression-in-url-attribute
- js/angular/repeated-dependency-injection
- js/regex/back-reference-to-negative-lookahead
- js/regex/unmatchable-dollar
- js/regex/empty-character-class
- js/regex/back-reference-before-group
- js/regex/unbound-back-reference
- js/regex/always-matches
- js/regex/unmatchable-caret
- js/regex/duplicate-in-character-class
- js/vue/arrow-method-on-vue-instance
- js/conditional-comment
- js/superfluous-trailing-arguments
- js/illegal-invocation
- js/invalid-prototype-value
- js/incomplete-object-initialization
- js/useless-type-test
- js/template-syntax-in-string-literal
- js/with-statement
- js/property-assignment-on-primitive
- js/deletion-of-non-property
- js/setter-return
- js/index-out-of-bounds
- js/unused-index-variable
- js/non-standard-language-feature
- js/syntax-error
- js/for-in-comprehension
- js/strict-mode-call-stack-introspection
- js/automatic-semicolon-insertion
- js/inconsistent-use-of-new
- js/non-linear-pattern
- js/yield-outside-generator
- js/mixed-static-instance-this-access
- js/arguments-redefinition
- js/nested-function-reference-in-default-parameter
- js/duplicate-parameter-name
- js/unreachable-method-overloads
- js/duplicate-variable-declaration
- js/function-declaration-conflict
- js/ineffective-parameter-type
- js/assignment-to-constant
- js/use-before-declaration
- js/suspicious-method-name-declaration
- js/overwritten-property
- js/useless-assignment-to-local
- js/useless-assignment-to-property
- js/variable-initialization-conflict
- js/variable-use-in-temporal-dead-zone
- js/missing-variable-declaration
- js/missing-this-qualifier
- js/unused-local-variable
- js/label-in-switch
- js/ignore-array-result
- js/inconsistent-loop-direction
- js/unreachable-statement
- js/trivial-conditional
- js/useless-comparison-test
- js/misleading-indentation-of-dangling-else
- js/use-of-returnless-function
- js/useless-assignment-in-return
- js/loop-iteration-skipped-due-to-shifting
- js/misleading-indentation-after-control-statement
- js/unused-loop-variable
- js/implicit-operand-conversion
- js/whitespace-contradicts-precedence
- js/missing-space-in-concatenation
- js/unbound-event-handler-receiver
- js/shift-out-of-range
- js/missing-dot-length-in-comparison
- js/redundant-operation
- js/comparison-with-nan
- js/duplicate-property
- js/unclear-operator-precedence
- js/unknown-directive
- js/string-instead-of-regex
- js/unneeded-defensive-code
- js/duplicate-switch-case
- js/duplicate-condition
- js/useless-expression
- js/redundant-assignment
- js/misspelled-variable-name
- js/call-to-non-callable
- js/missing-await
- js/comparison-between-incompatible-types
- js/property-access-on-non-object
- js/malformed-html-id
- js/eval-like-call
- js/duplicate-html-attribute
- js/react/unsupported-state-update-in-lifecycle-method
- js/react/unused-or-undefined-state-property
- js/react/direct-state-mutation
- js/react/inconsistent-state-update
- js/diagnostics/extraction-errors
- js/diagnostics/successfully-extracted-files
- js/summary/lines-of-code
- js/summary/lines-of-user-code
- include:
kind:
- diagnostic
- include:
kind:
- metric
tags contain:
- summary
- exclude:
deprecated: //
- exclude:
query path:
- /^experimental\/.*/

View File

@@ -672,3 +672,15 @@ alias(
actual = "@vendor_ts__ungrammar-1.16.1//:ungrammar",
tags = ["manual"],
)
alias(
name = "zstd-0.13.3",
actual = "@vendor_ts__zstd-0.13.3//:zstd",
tags = ["manual"],
)
alias(
name = "zstd",
actual = "@vendor_ts__zstd-0.13.3//:zstd",
tags = ["manual"],
)

View File

@@ -28,6 +28,9 @@ rust_library(
"WORKSPACE.bazel",
],
),
crate_features = [
"parallel",
],
crate_root = "src/lib.rs",
edition = "2018",
rustc_flags = [
@@ -81,6 +84,42 @@ rust_library(
}),
version = "1.2.7",
deps = [
"@vendor_ts__jobserver-0.1.32//:jobserver",
"@vendor_ts__shlex-1.3.0//:shlex",
],
] + select({
"@rules_rust//rust/platform:aarch64-apple-darwin": [
"@vendor_ts__libc-0.2.171//:libc", # aarch64-apple-darwin
],
"@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # aarch64-unknown-linux-gnu
],
"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # aarch64-unknown-linux-gnu, aarch64-unknown-nixos-gnu
],
"@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [
"@vendor_ts__libc-0.2.171//:libc", # arm-unknown-linux-gnueabi
],
"@rules_rust//rust/platform:i686-unknown-linux-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # i686-unknown-linux-gnu
],
"@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # powerpc-unknown-linux-gnu
],
"@rules_rust//rust/platform:s390x-unknown-linux-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # s390x-unknown-linux-gnu
],
"@rules_rust//rust/platform:x86_64-apple-darwin": [
"@vendor_ts__libc-0.2.171//:libc", # x86_64-apple-darwin
],
"@rules_rust//rust/platform:x86_64-unknown-freebsd": [
"@vendor_ts__libc-0.2.171//:libc", # x86_64-unknown-freebsd
],
"@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # x86_64-unknown-linux-gnu
],
"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu
],
"//conditions:default": [],
}),
)

View File

@@ -0,0 +1,158 @@
###############################################################################
# @generated
# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
# regenerate this file, run the following:
#
# bazel run @@//misc/bazel/3rdparty:vendor_tree_sitter_extractors
###############################################################################
load("@rules_rust//rust:defs.bzl", "rust_library")
package(default_visibility = ["//visibility:public"])
rust_library(
name = "jobserver",
srcs = glob(
include = ["**/*.rs"],
allow_empty = True,
),
compile_data = glob(
include = ["**"],
allow_empty = True,
exclude = [
"**/* *",
".tmp_git_root/**/*",
"BUILD",
"BUILD.bazel",
"WORKSPACE",
"WORKSPACE.bazel",
],
),
crate_root = "src/lib.rs",
edition = "2021",
rustc_flags = [
"--cap-lints=allow",
],
tags = [
"cargo-bazel",
"crate-name=jobserver",
"manual",
"noclippy",
"norustfmt",
],
target_compatible_with = select({
"@rules_rust//rust/platform:aarch64-apple-darwin": [],
"@rules_rust//rust/platform:aarch64-apple-ios": [],
"@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
"@rules_rust//rust/platform:aarch64-linux-android": [],
"@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
"@rules_rust//rust/platform:aarch64-unknown-fuchsia": [],
"@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
"@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
"@rules_rust//rust/platform:aarch64-unknown-uefi": [],
"@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
"@rules_rust//rust/platform:armv7-linux-androideabi": [],
"@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
"@rules_rust//rust/platform:i686-apple-darwin": [],
"@rules_rust//rust/platform:i686-linux-android": [],
"@rules_rust//rust/platform:i686-pc-windows-msvc": [],
"@rules_rust//rust/platform:i686-unknown-freebsd": [],
"@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
"@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
"@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
"@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
"@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
"@rules_rust//rust/platform:thumbv7em-none-eabi": [],
"@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
"@rules_rust//rust/platform:wasm32-unknown-unknown": [],
"@rules_rust//rust/platform:wasm32-wasip1": [],
"@rules_rust//rust/platform:x86_64-apple-darwin": [],
"@rules_rust//rust/platform:x86_64-apple-ios": [],
"@rules_rust//rust/platform:x86_64-linux-android": [],
"@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
"@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
"@rules_rust//rust/platform:x86_64-unknown-fuchsia": [],
"@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
"@rules_rust//rust/platform:x86_64-unknown-none": [],
"@rules_rust//rust/platform:x86_64-unknown-uefi": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
version = "0.1.32",
deps = select({
"@rules_rust//rust/platform:aarch64-apple-darwin": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:aarch64-apple-ios": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:aarch64-apple-ios-sim": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:aarch64-linux-android": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:aarch64-unknown-fuchsia": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:armv7-linux-androideabi": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:i686-apple-darwin": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:i686-linux-android": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:i686-unknown-freebsd": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:i686-unknown-linux-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:s390x-unknown-linux-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:x86_64-apple-darwin": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:x86_64-apple-ios": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:x86_64-linux-android": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:x86_64-unknown-freebsd": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:x86_64-unknown-fuchsia": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [
"@vendor_ts__libc-0.2.171//:libc", # cfg(unix)
],
"//conditions:default": [],
}),
)

View File

@@ -0,0 +1,83 @@
###############################################################################
# @generated
# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
# regenerate this file, run the following:
#
# bazel run @@//misc/bazel/3rdparty:vendor_tree_sitter_extractors
###############################################################################
load("@rules_rust//rust:defs.bzl", "rust_library")
package(default_visibility = ["//visibility:public"])
rust_library(
name = "pkg_config",
srcs = glob(
include = ["**/*.rs"],
allow_empty = True,
),
compile_data = glob(
include = ["**"],
allow_empty = True,
exclude = [
"**/* *",
".tmp_git_root/**/*",
"BUILD",
"BUILD.bazel",
"WORKSPACE",
"WORKSPACE.bazel",
],
),
crate_root = "src/lib.rs",
edition = "2018",
rustc_flags = [
"--cap-lints=allow",
],
tags = [
"cargo-bazel",
"crate-name=pkg-config",
"manual",
"noclippy",
"norustfmt",
],
target_compatible_with = select({
"@rules_rust//rust/platform:aarch64-apple-darwin": [],
"@rules_rust//rust/platform:aarch64-apple-ios": [],
"@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
"@rules_rust//rust/platform:aarch64-linux-android": [],
"@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
"@rules_rust//rust/platform:aarch64-unknown-fuchsia": [],
"@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
"@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
"@rules_rust//rust/platform:aarch64-unknown-uefi": [],
"@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
"@rules_rust//rust/platform:armv7-linux-androideabi": [],
"@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
"@rules_rust//rust/platform:i686-apple-darwin": [],
"@rules_rust//rust/platform:i686-linux-android": [],
"@rules_rust//rust/platform:i686-pc-windows-msvc": [],
"@rules_rust//rust/platform:i686-unknown-freebsd": [],
"@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
"@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
"@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
"@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
"@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
"@rules_rust//rust/platform:thumbv7em-none-eabi": [],
"@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
"@rules_rust//rust/platform:wasm32-unknown-unknown": [],
"@rules_rust//rust/platform:wasm32-wasip1": [],
"@rules_rust//rust/platform:x86_64-apple-darwin": [],
"@rules_rust//rust/platform:x86_64-apple-ios": [],
"@rules_rust//rust/platform:x86_64-linux-android": [],
"@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
"@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
"@rules_rust//rust/platform:x86_64-unknown-fuchsia": [],
"@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
"@rules_rust//rust/platform:x86_64-unknown-none": [],
"@rules_rust//rust/platform:x86_64-unknown-uefi": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
version = "0.3.32",
)

View File

@@ -0,0 +1,92 @@
###############################################################################
# @generated
# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
# regenerate this file, run the following:
#
# bazel run @@//misc/bazel/3rdparty:vendor_tree_sitter_extractors
###############################################################################
load("@rules_rust//rust:defs.bzl", "rust_library")
package(default_visibility = ["//visibility:public"])
rust_library(
name = "zstd",
srcs = glob(
include = ["**/*.rs"],
allow_empty = True,
),
compile_data = glob(
include = ["**"],
allow_empty = True,
exclude = [
"**/* *",
".tmp_git_root/**/*",
"BUILD",
"BUILD.bazel",
"WORKSPACE",
"WORKSPACE.bazel",
],
),
crate_features = [
"arrays",
"default",
"legacy",
"zdict_builder",
],
crate_root = "src/lib.rs",
edition = "2018",
rustc_flags = [
"--cap-lints=allow",
],
tags = [
"cargo-bazel",
"crate-name=zstd",
"manual",
"noclippy",
"norustfmt",
],
target_compatible_with = select({
"@rules_rust//rust/platform:aarch64-apple-darwin": [],
"@rules_rust//rust/platform:aarch64-apple-ios": [],
"@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
"@rules_rust//rust/platform:aarch64-linux-android": [],
"@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
"@rules_rust//rust/platform:aarch64-unknown-fuchsia": [],
"@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
"@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
"@rules_rust//rust/platform:aarch64-unknown-uefi": [],
"@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
"@rules_rust//rust/platform:armv7-linux-androideabi": [],
"@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
"@rules_rust//rust/platform:i686-apple-darwin": [],
"@rules_rust//rust/platform:i686-linux-android": [],
"@rules_rust//rust/platform:i686-pc-windows-msvc": [],
"@rules_rust//rust/platform:i686-unknown-freebsd": [],
"@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
"@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
"@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
"@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
"@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
"@rules_rust//rust/platform:thumbv7em-none-eabi": [],
"@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
"@rules_rust//rust/platform:wasm32-unknown-unknown": [],
"@rules_rust//rust/platform:wasm32-wasip1": [],
"@rules_rust//rust/platform:x86_64-apple-darwin": [],
"@rules_rust//rust/platform:x86_64-apple-ios": [],
"@rules_rust//rust/platform:x86_64-linux-android": [],
"@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
"@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
"@rules_rust//rust/platform:x86_64-unknown-fuchsia": [],
"@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
"@rules_rust//rust/platform:x86_64-unknown-none": [],
"@rules_rust//rust/platform:x86_64-unknown-uefi": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
version = "0.13.3",
deps = [
"@vendor_ts__zstd-safe-7.2.4//:zstd_safe",
],
)

View File

@@ -0,0 +1,158 @@
###############################################################################
# @generated
# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
# regenerate this file, run the following:
#
# bazel run @@//misc/bazel/3rdparty:vendor_tree_sitter_extractors
###############################################################################
load("@rules_rust//cargo:defs.bzl", "cargo_build_script")
load("@rules_rust//rust:defs.bzl", "rust_library")
package(default_visibility = ["//visibility:public"])
rust_library(
name = "zstd_safe",
srcs = glob(
include = ["**/*.rs"],
allow_empty = True,
),
compile_data = glob(
include = ["**"],
allow_empty = True,
exclude = [
"**/* *",
".tmp_git_root/**/*",
"BUILD",
"BUILD.bazel",
"WORKSPACE",
"WORKSPACE.bazel",
],
),
crate_features = [
"arrays",
"legacy",
"std",
"zdict_builder",
],
crate_root = "src/lib.rs",
edition = "2018",
rustc_flags = [
"--cap-lints=allow",
],
tags = [
"cargo-bazel",
"crate-name=zstd-safe",
"manual",
"noclippy",
"norustfmt",
],
target_compatible_with = select({
"@rules_rust//rust/platform:aarch64-apple-darwin": [],
"@rules_rust//rust/platform:aarch64-apple-ios": [],
"@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
"@rules_rust//rust/platform:aarch64-linux-android": [],
"@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
"@rules_rust//rust/platform:aarch64-unknown-fuchsia": [],
"@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
"@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
"@rules_rust//rust/platform:aarch64-unknown-uefi": [],
"@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
"@rules_rust//rust/platform:armv7-linux-androideabi": [],
"@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
"@rules_rust//rust/platform:i686-apple-darwin": [],
"@rules_rust//rust/platform:i686-linux-android": [],
"@rules_rust//rust/platform:i686-pc-windows-msvc": [],
"@rules_rust//rust/platform:i686-unknown-freebsd": [],
"@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
"@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
"@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
"@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
"@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
"@rules_rust//rust/platform:thumbv7em-none-eabi": [],
"@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
"@rules_rust//rust/platform:wasm32-unknown-unknown": [],
"@rules_rust//rust/platform:wasm32-wasip1": [],
"@rules_rust//rust/platform:x86_64-apple-darwin": [],
"@rules_rust//rust/platform:x86_64-apple-ios": [],
"@rules_rust//rust/platform:x86_64-linux-android": [],
"@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
"@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
"@rules_rust//rust/platform:x86_64-unknown-fuchsia": [],
"@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
"@rules_rust//rust/platform:x86_64-unknown-none": [],
"@rules_rust//rust/platform:x86_64-unknown-uefi": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
version = "7.2.4",
deps = [
"@vendor_ts__zstd-safe-7.2.4//:build_script_build",
"@vendor_ts__zstd-sys-2.0.15-zstd.1.5.7//:zstd_sys",
],
)
cargo_build_script(
name = "_bs",
srcs = glob(
include = ["**/*.rs"],
allow_empty = True,
),
compile_data = glob(
include = ["**"],
allow_empty = True,
exclude = [
"**/* *",
"**/*.rs",
".tmp_git_root/**/*",
"BUILD",
"BUILD.bazel",
"WORKSPACE",
"WORKSPACE.bazel",
],
),
crate_features = [
"arrays",
"legacy",
"std",
"zdict_builder",
],
crate_name = "build_script_build",
crate_root = "build.rs",
data = glob(
include = ["**"],
allow_empty = True,
exclude = [
"**/* *",
".tmp_git_root/**/*",
"BUILD",
"BUILD.bazel",
"WORKSPACE",
"WORKSPACE.bazel",
],
),
edition = "2018",
link_deps = [
"@vendor_ts__zstd-sys-2.0.15-zstd.1.5.7//:zstd_sys",
],
pkg_name = "zstd-safe",
rustc_flags = [
"--cap-lints=allow",
],
tags = [
"cargo-bazel",
"crate-name=zstd-safe",
"manual",
"noclippy",
"norustfmt",
],
version = "7.2.4",
visibility = ["//visibility:private"],
)
alias(
name = "build_script_build",
actual = ":_bs",
tags = ["manual"],
)

View File

@@ -0,0 +1,157 @@
###############################################################################
# @generated
# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To
# regenerate this file, run the following:
#
# bazel run @@//misc/bazel/3rdparty:vendor_tree_sitter_extractors
###############################################################################
load("@rules_rust//cargo:defs.bzl", "cargo_build_script")
load("@rules_rust//rust:defs.bzl", "rust_library")
package(default_visibility = ["//visibility:public"])
rust_library(
name = "zstd_sys",
srcs = glob(
include = ["**/*.rs"],
allow_empty = True,
),
compile_data = glob(
include = ["**"],
allow_empty = True,
exclude = [
"**/* *",
".tmp_git_root/**/*",
"BUILD",
"BUILD.bazel",
"WORKSPACE",
"WORKSPACE.bazel",
],
),
crate_features = [
"legacy",
"std",
"zdict_builder",
],
crate_root = "src/lib.rs",
edition = "2018",
rustc_flags = [
"--cap-lints=allow",
],
tags = [
"cargo-bazel",
"crate-name=zstd-sys",
"manual",
"noclippy",
"norustfmt",
],
target_compatible_with = select({
"@rules_rust//rust/platform:aarch64-apple-darwin": [],
"@rules_rust//rust/platform:aarch64-apple-ios": [],
"@rules_rust//rust/platform:aarch64-apple-ios-sim": [],
"@rules_rust//rust/platform:aarch64-linux-android": [],
"@rules_rust//rust/platform:aarch64-pc-windows-msvc": [],
"@rules_rust//rust/platform:aarch64-unknown-fuchsia": [],
"@rules_rust//rust/platform:aarch64-unknown-linux-gnu": [],
"@rules_rust//rust/platform:aarch64-unknown-nixos-gnu": [],
"@rules_rust//rust/platform:aarch64-unknown-nto-qnx710": [],
"@rules_rust//rust/platform:aarch64-unknown-uefi": [],
"@rules_rust//rust/platform:arm-unknown-linux-gnueabi": [],
"@rules_rust//rust/platform:armv7-linux-androideabi": [],
"@rules_rust//rust/platform:armv7-unknown-linux-gnueabi": [],
"@rules_rust//rust/platform:i686-apple-darwin": [],
"@rules_rust//rust/platform:i686-linux-android": [],
"@rules_rust//rust/platform:i686-pc-windows-msvc": [],
"@rules_rust//rust/platform:i686-unknown-freebsd": [],
"@rules_rust//rust/platform:i686-unknown-linux-gnu": [],
"@rules_rust//rust/platform:powerpc-unknown-linux-gnu": [],
"@rules_rust//rust/platform:riscv32imc-unknown-none-elf": [],
"@rules_rust//rust/platform:riscv64gc-unknown-none-elf": [],
"@rules_rust//rust/platform:s390x-unknown-linux-gnu": [],
"@rules_rust//rust/platform:thumbv7em-none-eabi": [],
"@rules_rust//rust/platform:thumbv8m.main-none-eabi": [],
"@rules_rust//rust/platform:wasm32-unknown-unknown": [],
"@rules_rust//rust/platform:wasm32-wasip1": [],
"@rules_rust//rust/platform:x86_64-apple-darwin": [],
"@rules_rust//rust/platform:x86_64-apple-ios": [],
"@rules_rust//rust/platform:x86_64-linux-android": [],
"@rules_rust//rust/platform:x86_64-pc-windows-msvc": [],
"@rules_rust//rust/platform:x86_64-unknown-freebsd": [],
"@rules_rust//rust/platform:x86_64-unknown-fuchsia": [],
"@rules_rust//rust/platform:x86_64-unknown-linux-gnu": [],
"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu": [],
"@rules_rust//rust/platform:x86_64-unknown-none": [],
"@rules_rust//rust/platform:x86_64-unknown-uefi": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
version = "2.0.15+zstd.1.5.7",
deps = [
"@vendor_ts__zstd-sys-2.0.15-zstd.1.5.7//:build_script_build",
],
)
cargo_build_script(
name = "_bs",
srcs = glob(
include = ["**/*.rs"],
allow_empty = True,
),
compile_data = glob(
include = ["**"],
allow_empty = True,
exclude = [
"**/* *",
"**/*.rs",
".tmp_git_root/**/*",
"BUILD",
"BUILD.bazel",
"WORKSPACE",
"WORKSPACE.bazel",
],
),
crate_features = [
"legacy",
"std",
"zdict_builder",
],
crate_name = "build_script_build",
crate_root = "build.rs",
data = glob(
include = ["**"],
allow_empty = True,
exclude = [
"**/* *",
".tmp_git_root/**/*",
"BUILD",
"BUILD.bazel",
"WORKSPACE",
"WORKSPACE.bazel",
],
),
edition = "2018",
links = "zstd",
pkg_name = "zstd-sys",
rustc_flags = [
"--cap-lints=allow",
],
tags = [
"cargo-bazel",
"crate-name=zstd-sys",
"manual",
"noclippy",
"norustfmt",
],
version = "2.0.15+zstd.1.5.7",
visibility = ["//visibility:private"],
deps = [
"@vendor_ts__cc-1.2.7//:cc",
"@vendor_ts__pkg-config-0.3.32//:pkg_config",
],
)
alias(
name = "build_script_build",
actual = ":_bs",
tags = ["manual"],
)

View File

@@ -381,6 +381,7 @@ _NORMAL_DEPENDENCIES = {
"tracing": Label("@vendor_ts__tracing-0.1.41//:tracing"),
"tracing-subscriber": Label("@vendor_ts__tracing-subscriber-0.3.19//:tracing_subscriber"),
"tree-sitter": Label("@vendor_ts__tree-sitter-0.24.6//:tree_sitter"),
"zstd": Label("@vendor_ts__zstd-0.13.3//:zstd"),
},
},
}
@@ -1658,6 +1659,16 @@ def crate_repositories():
build_file = Label("//misc/bazel/3rdparty/tree_sitter_extractors_deps:BUILD.itoa-1.0.15.bazel"),
)
maybe(
http_archive,
name = "vendor_ts__jobserver-0.1.32",
sha256 = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0",
type = "tar.gz",
urls = ["https://static.crates.io/crates/jobserver/0.1.32/download"],
strip_prefix = "jobserver-0.1.32",
build_file = Label("//misc/bazel/3rdparty/tree_sitter_extractors_deps:BUILD.jobserver-0.1.32.bazel"),
)
maybe(
http_archive,
name = "vendor_ts__jod-thread-0.1.2",
@@ -2048,6 +2059,16 @@ def crate_repositories():
build_file = Label("//misc/bazel/3rdparty/tree_sitter_extractors_deps:BUILD.pin-project-lite-0.2.16.bazel"),
)
maybe(
http_archive,
name = "vendor_ts__pkg-config-0.3.32",
sha256 = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c",
type = "tar.gz",
urls = ["https://static.crates.io/crates/pkg-config/0.3.32/download"],
strip_prefix = "pkg-config-0.3.32",
build_file = Label("//misc/bazel/3rdparty/tree_sitter_extractors_deps:BUILD.pkg-config-0.3.32.bazel"),
)
maybe(
http_archive,
name = "vendor_ts__portable-atomic-1.11.0",
@@ -3647,6 +3668,36 @@ def crate_repositories():
build_file = Label("//misc/bazel/3rdparty/tree_sitter_extractors_deps:BUILD.zerocopy-derive-0.8.20.bazel"),
)
maybe(
http_archive,
name = "vendor_ts__zstd-0.13.3",
sha256 = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a",
type = "tar.gz",
urls = ["https://static.crates.io/crates/zstd/0.13.3/download"],
strip_prefix = "zstd-0.13.3",
build_file = Label("//misc/bazel/3rdparty/tree_sitter_extractors_deps:BUILD.zstd-0.13.3.bazel"),
)
maybe(
http_archive,
name = "vendor_ts__zstd-safe-7.2.4",
sha256 = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d",
type = "tar.gz",
urls = ["https://static.crates.io/crates/zstd-safe/7.2.4/download"],
strip_prefix = "zstd-safe-7.2.4",
build_file = Label("//misc/bazel/3rdparty/tree_sitter_extractors_deps:BUILD.zstd-safe-7.2.4.bazel"),
)
maybe(
http_archive,
name = "vendor_ts__zstd-sys-2.0.15-zstd.1.5.7",
sha256 = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237",
type = "tar.gz",
urls = ["https://static.crates.io/crates/zstd-sys/2.0.15+zstd.1.5.7/download"],
strip_prefix = "zstd-sys-2.0.15+zstd.1.5.7",
build_file = Label("//misc/bazel/3rdparty/tree_sitter_extractors_deps:BUILD.zstd-sys-2.0.15+zstd.1.5.7.bazel"),
)
return [
struct(repo = "vendor_ts__anyhow-1.0.97", is_dev_dep = False),
struct(repo = "vendor_ts__argfile-0.2.1", is_dev_dep = False),
@@ -3698,6 +3749,7 @@ def crate_repositories():
struct(repo = "vendor_ts__tree-sitter-ruby-0.23.1", is_dev_dep = False),
struct(repo = "vendor_ts__triomphe-0.1.14", is_dev_dep = False),
struct(repo = "vendor_ts__ungrammar-1.16.1", is_dev_dep = False),
struct(repo = "vendor_ts__zstd-0.13.3", is_dev_dep = False),
struct(repo = "vendor_ts__rand-0.9.0", is_dev_dep = True),
struct(repo = "vendor_ts__tree-sitter-json-0.24.8", is_dev_dep = True),
struct(repo = "vendor_ts__tree-sitter-ql-0.23.1", is_dev_dep = True),

View File

@@ -0,0 +1,500 @@
"""
Experimental script for bulk generation of MaD models based on a list of projects.
Note: This file must be formatted using the Black Python formatter.
"""
import os.path
import subprocess
import sys
from typing import NotRequired, TypedDict, List
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import argparse
import json
import requests
import zipfile
import tarfile
from functools import cmp_to_key
import generate_mad as mad
gitroot = (
subprocess.check_output(["git", "rev-parse", "--show-toplevel"])
.decode("utf-8")
.strip()
)
build_dir = os.path.join(gitroot, "mad-generation-build")
# A project to generate models for
class Project(TypedDict):
"""
Type definition for projects (acquired via a GitHub repo) to model.
Attributes:
name: The name of the project
git_repo: URL to the git repository
git_tag: Optional Git tag to check out
"""
name: str
git_repo: NotRequired[str]
git_tag: NotRequired[str]
with_sinks: NotRequired[bool]
with_sinks: NotRequired[bool]
with_summaries: NotRequired[bool]
def should_generate_sinks(project: Project) -> bool:
return project.get("with-sinks", True)
def should_generate_sources(project: Project) -> bool:
return project.get("with-sources", True)
def should_generate_summaries(project: Project) -> bool:
return project.get("with-summaries", True)
def clone_project(project: Project) -> str:
"""
Shallow clone a project into the build directory.
Args:
project: A dictionary containing project information with 'name', 'git_repo', and optional 'git_tag' keys.
Returns:
The path to the cloned project directory.
"""
name = project["name"]
repo_url = project["git_repo"]
git_tag = project.get("git_tag")
# Determine target directory
target_dir = os.path.join(build_dir, name)
# Clone only if directory doesn't already exist
if not os.path.exists(target_dir):
if git_tag:
print(f"Cloning {name} from {repo_url} at tag {git_tag}")
else:
print(f"Cloning {name} from {repo_url}")
subprocess.check_call(
[
"git",
"clone",
"--quiet",
"--depth",
"1", # Shallow clone
*(
["--branch", git_tag] if git_tag else []
), # Add branch if tag is provided
repo_url,
target_dir,
]
)
print(f"Completed cloning {name}")
else:
print(f"Skipping cloning {name} as it already exists at {target_dir}")
return target_dir
def clone_projects(projects: List[Project]) -> List[tuple[Project, str]]:
"""
Clone all projects in parallel.
Args:
projects: List of projects to clone
Returns:
List of (project, project_dir) pairs in the same order as the input projects
"""
start_time = time.time()
max_workers = min(8, len(projects)) # Use at most 8 threads
project_dirs_map = {} # Map to store results by project name
with ThreadPoolExecutor(max_workers=max_workers) as executor:
# Start cloning tasks and keep track of them
future_to_project = {
executor.submit(clone_project, project): project for project in projects
}
# Process results as they complete
for future in as_completed(future_to_project):
project = future_to_project[future]
try:
project_dir = future.result()
project_dirs_map[project["name"]] = (project, project_dir)
except Exception as e:
print(f"ERROR: Failed to clone {project['name']}: {e}")
if len(project_dirs_map) != len(projects):
failed_projects = [
project["name"]
for project in projects
if project["name"] not in project_dirs_map
]
print(
f"ERROR: Only {len(project_dirs_map)} out of {len(projects)} projects were cloned successfully. Failed projects: {', '.join(failed_projects)}"
)
sys.exit(1)
project_dirs = [project_dirs_map[project["name"]] for project in projects]
clone_time = time.time() - start_time
print(f"Cloning completed in {clone_time:.2f} seconds")
return project_dirs
def build_database(
language: str, extractor_options, project: Project, project_dir: str
) -> str | None:
"""
Build a CodeQL database for a project.
Args:
language: The language for which to build the database (e.g., "rust").
extractor_options: Additional options for the extractor.
project: A dictionary containing project information with 'name' and 'git_repo' keys.
project_dir: Path to the CodeQL database.
Returns:
The path to the created database directory.
"""
name = project["name"]
# Create database directory path
database_dir = os.path.join(build_dir, f"{name}-db")
# Only build the database if it doesn't already exist
if not os.path.exists(database_dir):
print(f"Building CodeQL database for {name}...")
extractor_options = [option for x in extractor_options for option in ("-O", x)]
try:
subprocess.check_call(
[
"codeql",
"database",
"create",
f"--language={language}",
"--source-root=" + project_dir,
"--overwrite",
*extractor_options,
"--",
database_dir,
]
)
print(f"Successfully created database at {database_dir}")
except subprocess.CalledProcessError as e:
print(f"Failed to create database for {name}: {e}")
return None
else:
print(
f"Skipping database creation for {name} as it already exists at {database_dir}"
)
return database_dir
def generate_models(config, project: Project, database_dir: str) -> None:
"""
Generate models for a project.
Args:
args: Command line arguments passed to this script.
name: The name of the project.
database_dir: Path to the CodeQL database.
"""
name = project["name"]
language = config["language"]
generator = mad.Generator(language)
# Note: The argument parser converts with-sinks to with_sinks, etc.
generator.generateSinks = should_generate_sinks(project)
generator.generateSources = should_generate_sources(project)
generator.generateSummaries = should_generate_summaries(project)
generator.setenvironment(database=database_dir, folder=name)
generator.run()
def build_databases_from_projects(
language: str, extractor_options, projects: List[Project]
) -> List[tuple[Project, str | None]]:
"""
Build databases for all projects in parallel.
Args:
language: The language for which to build the databases (e.g., "rust").
extractor_options: Additional options for the extractor.
projects: List of projects to build databases for.
Returns:
List of (project_name, database_dir) pairs, where database_dir is None if the build failed.
"""
# Clone projects in parallel
print("=== Cloning projects ===")
project_dirs = clone_projects(projects)
# Build databases for all projects
print("\n=== Building databases ===")
database_results = [
(
project,
build_database(language, extractor_options, project, project_dir),
)
for project, project_dir in project_dirs
]
return database_results
def get_json_from_github(
url: str, pat: str, extra_headers: dict[str, str] = {}
) -> dict:
"""
Download a JSON file from GitHub using a personal access token (PAT).
Args:
url: The URL to download the JSON file from.
pat: Personal Access Token for GitHub API authentication.
extra_headers: Additional headers to include in the request.
Returns:
The JSON response as a dictionary.
"""
headers = {"Authorization": f"token {pat}"} | extra_headers
response = requests.get(url, headers=headers)
if response.status_code != 200:
print(f"Failed to download JSON: {response.status_code} {response.text}")
sys.exit(1)
else:
return response.json()
def download_artifact(url: str, artifact_name: str, pat: str) -> str:
"""
Download a GitHub Actions artifact from a given URL.
Args:
url: The URL to download the artifact from.
artifact_name: The name of the artifact (used for naming the downloaded file).
pat: Personal Access Token for GitHub API authentication.
Returns:
The path to the downloaded artifact file.
"""
headers = {"Authorization": f"token {pat}", "Accept": "application/vnd.github+json"}
response = requests.get(url, stream=True, headers=headers)
zipName = artifact_name + ".zip"
if response.status_code != 200:
print(f"Failed to download file. Status code: {response.status_code}")
sys.exit(1)
target_zip = os.path.join(build_dir, zipName)
with open(target_zip, "wb") as file:
for chunk in response.iter_content(chunk_size=8192):
file.write(chunk)
print(f"Download complete: {target_zip}")
return target_zip
def remove_extension(filename: str) -> str:
while "." in filename:
filename, _ = os.path.splitext(filename)
return filename
def pretty_name_from_artifact_name(artifact_name: str) -> str:
return artifact_name.split("___")[1]
def download_dca_databases(
experiment_name: str, pat: str, projects: List[Project]
) -> List[tuple[Project, str | None]]:
"""
Download databases from a DCA experiment.
Args:
experiment_name: The name of the DCA experiment to download databases from.
pat: Personal Access Token for GitHub API authentication.
projects: List of projects to download databases for.
Returns:
List of (project_name, database_dir) pairs, where database_dir is None if the download failed.
"""
database_results = {}
print("\n=== Finding projects ===")
response = get_json_from_github(
f"https://raw.githubusercontent.com/github/codeql-dca-main/data/{experiment_name}/reports/downloads.json",
pat,
)
targets = response["targets"]
project_map = {project["name"]: project for project in projects}
for data in targets.values():
downloads = data["downloads"]
analyzed_database = downloads["analyzed_database"]
artifact_name = analyzed_database["artifact_name"]
pretty_name = pretty_name_from_artifact_name(artifact_name)
if not pretty_name in project_map:
print(f"Skipping {pretty_name} as it is not in the list of projects")
continue
repository = analyzed_database["repository"]
run_id = analyzed_database["run_id"]
print(f"=== Finding artifact: {artifact_name} ===")
response = get_json_from_github(
f"https://api.github.com/repos/{repository}/actions/runs/{run_id}/artifacts",
pat,
{"Accept": "application/vnd.github+json"},
)
artifacts = response["artifacts"]
artifact_map = {artifact["name"]: artifact for artifact in artifacts}
print(f"=== Downloading artifact: {artifact_name} ===")
archive_download_url = artifact_map[artifact_name]["archive_download_url"]
artifact_zip_location = download_artifact(
archive_download_url, artifact_name, pat
)
print(f"=== Extracting artifact: {artifact_name} ===")
# The database is in a zip file, which contains a tar.gz file with the DB
# First we open the zip file
with zipfile.ZipFile(artifact_zip_location, "r") as zip_ref:
artifact_unzipped_location = os.path.join(build_dir, artifact_name)
# And then we extract it to build_dir/artifact_name
zip_ref.extractall(artifact_unzipped_location)
# And then we iterate over the contents of the extracted directory
# and extract the tar.gz files inside it
for entry in os.listdir(artifact_unzipped_location):
artifact_tar_location = os.path.join(artifact_unzipped_location, entry)
with tarfile.open(artifact_tar_location, "r:gz") as tar_ref:
# And we just untar it to the same directory as the zip file
tar_ref.extractall(artifact_unzipped_location)
database_results[pretty_name] = os.path.join(
artifact_unzipped_location, remove_extension(entry)
)
print(f"\n=== Extracted {len(database_results)} databases ===")
return [(project, database_results[project["name"]]) for project in projects]
def get_mad_destination_for_project(config, name: str) -> str:
return os.path.join(config["destination"], name)
def get_strategy(config) -> str:
return config["strategy"].lower()
def main(config, args) -> None:
"""
Main function to handle the bulk generation of MaD models.
Args:
config: Configuration dictionary containing project details and other settings.
args: Command line arguments passed to this script.
"""
projects = config["targets"]
if not "language" in config:
print("ERROR: 'language' key is missing in the configuration file.")
sys.exit(1)
language = config["language"]
# Create build directory if it doesn't exist
if not os.path.exists(build_dir):
os.makedirs(build_dir)
# Check if any of the MaD directories contain working directory changes in git
for project in projects:
mad_dir = get_mad_destination_for_project(config, project["name"])
if os.path.exists(mad_dir):
git_status_output = subprocess.check_output(
["git", "status", "-s", mad_dir], text=True
).strip()
if git_status_output:
print(
f"""ERROR: Working directory changes detected in {mad_dir}.
Before generating new models, the existing models are deleted.
To avoid loss of data, please commit your changes."""
)
sys.exit(1)
database_results = []
match get_strategy(config):
case "repo":
extractor_options = config.get("extractor_options", [])
database_results = build_databases_from_projects(
language, extractor_options, projects
)
case "dca":
experiment_name = args.dca
if experiment_name is None:
print("ERROR: --dca argument is required for DCA strategy")
sys.exit(1)
if args.pat is None:
print("ERROR: --pat argument is required for DCA strategy")
sys.exit(1)
if not os.path.exists(args.pat):
print(f"ERROR: Personal Access Token file '{pat}' does not exist.")
sys.exit(1)
with open(args.pat, "r") as f:
pat = f.read().strip()
database_results = download_dca_databases(
experiment_name, pat, projects
)
# Generate models for all projects
print("\n=== Generating models ===")
failed_builds = [
project["name"] for project, db_dir in database_results if db_dir is None
]
if failed_builds:
print(
f"ERROR: {len(failed_builds)} database builds failed: {', '.join(failed_builds)}"
)
sys.exit(1)
# Delete the MaD directory for each project
for project, database_dir in database_results:
mad_dir = get_mad_destination_for_project(config, project["name"])
if os.path.exists(mad_dir):
print(f"Deleting existing MaD directory at {mad_dir}")
subprocess.check_call(["rm", "-rf", mad_dir])
for project, database_dir in database_results:
if database_dir is not None:
generate_models(config, project, database_dir)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"--config", type=str, help="Path to the configuration file.", required=True
)
parser.add_argument(
"--dca",
type=str,
help="Name of a DCA run that built all the projects",
required=False,
)
parser.add_argument(
"--pat",
type=str,
help="Path to a file containing the PAT token required to grab DCA databases (the same as the one you use for DCA)",
required=False,
)
args = parser.parse_args()
# Load config file
config = {}
if not os.path.exists(args.config):
print(f"ERROR: Config file '{args.config}' does not exist.")
sys.exit(1)
try:
with open(args.config, "r") as f:
config = json.load(f)
except json.JSONDecodeError as e:
print(f"ERROR: Failed to parse JSON file {args.config}: {e}")
sys.exit(1)
main(config, args)

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