From 19ff5c09d233c1ade20cc56b3d4d40a74f742b05 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 17 Nov 2025 09:30:20 +0100 Subject: [PATCH 01/15] Rust: Cache `inferCertainType` Ideally, this shouldn't be needed, as we already cache `inferType`. However, since we have consistency checks that directly call `inferCertainType`, we need to cache it as well to avoid recomputation. --- rust/ql/lib/codeql/rust/internal/TypeInference.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 804fc017194..080bac5d1b7 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -9,6 +9,7 @@ private import TypeMention private import typeinference.FunctionType private import typeinference.FunctionOverloading as FunctionOverloading private import typeinference.BlanketImplementation as BlanketImplementation +private import codeql.rust.internal.CachedStages private import codeql.typeinference.internal.TypeInference private import codeql.rust.frameworks.stdlib.Stdlib private import codeql.rust.frameworks.stdlib.Builtins as Builtins @@ -437,9 +438,10 @@ module CertainTypeInference { * Holds if `n` has complete and certain type information and if `n` has the * resulting type at `path`. */ - pragma[nomagic] + cached Type inferCertainType(AstNode n, TypePath path) { - result = inferAnnotatedType(n, path) + result = inferAnnotatedType(n, path) and + Stages::TypeInferenceStage::ref() or result = inferCertainCallExprType(n, path) or @@ -3454,8 +3456,6 @@ private Type inferCastExprType(CastExpr ce, TypePath path) { cached private module Cached { - private import codeql.rust.internal.CachedStages - /** Holds if `receiver` is the receiver of a method call with an implicit dereference. */ cached predicate receiverHasImplicitDeref(AstNode receiver) { From ddee385f371ab5b00d69ed3b251b9c24f2cf80fe Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Tue, 18 Nov 2025 17:18:05 +0100 Subject: [PATCH 02/15] Ripunzip: use releases from github This uses the ripunzip releases from github instead of building them ourselves. --- .gitattributes | 3 - .github/workflows/build-ripunzip.yml | 169 ------------------------- MODULE.bazel | 26 ++-- misc/ripunzip/BUILD.bazel | 2 +- misc/ripunzip/BUILD.ripunzip.bazel | 2 +- misc/ripunzip/ripunzip-Linux.tar.zst | 3 - misc/ripunzip/ripunzip-Windows.tar.zst | 3 - misc/ripunzip/ripunzip-macOS.tar.zst | 3 - misc/ripunzip/ripunzip.bzl | 51 ++++++++ 9 files changed, 62 insertions(+), 200 deletions(-) delete mode 100644 .github/workflows/build-ripunzip.yml delete mode 100644 misc/ripunzip/ripunzip-Linux.tar.zst delete mode 100644 misc/ripunzip/ripunzip-Windows.tar.zst delete mode 100644 misc/ripunzip/ripunzip-macOS.tar.zst create mode 100644 misc/ripunzip/ripunzip.bzl diff --git a/.gitattributes b/.gitattributes index df5bed028be..610342ef78b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -82,9 +82,6 @@ /csharp/paket.main.bzl linguist-generated=true /csharp/paket.main_extension.bzl linguist-generated=true -# ripunzip tool -/misc/ripunzip/ripunzip-* filter=lfs diff=lfs merge=lfs -text - # swift prebuilt resources /swift/third_party/resources/*.zip filter=lfs diff=lfs merge=lfs -text /swift/third_party/resources/*.tar.zst filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/build-ripunzip.yml b/.github/workflows/build-ripunzip.yml deleted file mode 100644 index 041d34bd046..00000000000 --- a/.github/workflows/build-ripunzip.yml +++ /dev/null @@ -1,169 +0,0 @@ -name: Build ripunzip - -on: - workflow_dispatch: - inputs: - ripunzip-version: - description: What reference to checkout from google/ripunzip. Latest by default - required: false - openssl-version: - description: What reference to checkout from openssl/openssl for Linux. Latest by default - required: false - open-pr: - description: Open a pull request updating the ripunzip versions committed to lfs - required: false - default: true # will be false on PRs - pull_request: - paths: - - .github/workflows/build-ripunzip.yml - -permissions: {} - -jobs: - versions: - runs-on: ubuntu-slim - outputs: - ripunzip-version: ${{ inputs.ripunzip-version || steps.fetch-ripunzip-version.outputs.version }} - openssl-version: ${{ inputs.openssl-version || steps.fetch-openssl-version.outputs.version }} - steps: - - name: Fetch latest ripunzip version - id: fetch-ripunzip-version - if: "!inputs.ripunzip-version" - run: &fetch-version - echo "version=$(gh release view --repo $REPO --json tagName --jq .tagName)" | tee -a $GITHUB_OUTPUT - env: - REPO: "google/ripunzip" - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Fetch latest openssl version - id: fetch-openssl-version - if: "!inputs.openssl-version" - run: *fetch-version - env: - REPO: "openssl/openssl" - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - build: - needs: versions - strategy: - fail-fast: false - matrix: - os: - - ubuntu-22.04 # keep at lowest supported ubuntu version for broader glibc compatibility - - macos-15 - - windows-2025 - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v5 - with: - repository: google/ripunzip - ref: ${{ needs.versions.outputs.ripunzip-version }} - # we need to avoid ripunzip dynamically linking into libssl - # see https://github.com/sfackler/rust-openssl/issues/183 - - if: runner.os == 'Linux' - name: checkout openssl - uses: actions/checkout@v5 - with: - repository: openssl/openssl - path: openssl - ref: ${{ needs.versions.outputs.openssl-version }} - - if: runner.os == 'Linux' - name: build and install openssl with fPIC - shell: bash - working-directory: openssl - run: | - ./config -fPIC --prefix=$HOME/.local --openssldir=$HOME/.local/ssl - make -j $(nproc) - make install_sw -j $(nproc) - - if: runner.os == 'Linux' - name: build (linux) - shell: bash - run: | - env OPENSSL_LIB_DIR=$HOME/.local/lib64 OPENSSL_INCLUDE_DIR=$HOME/.local/include OPENSSL_STATIC=yes cargo build --release - mv target/release/ripunzip ripunzip-linux - - if: runner.os == 'Windows' - name: build (windows) - shell: bash - run: | - cargo build --release - mv target/release/ripunzip ripunzip-windows - - name: build (macOS) - if: runner.os == 'macOS' - shell: bash - run: | - rustup target install x86_64-apple-darwin - rustup target install aarch64-apple-darwin - cargo build --target x86_64-apple-darwin --release - cargo build --target aarch64-apple-darwin --release - lipo -create -output ripunzip-macos \ - -arch x86_64 target/x86_64-apple-darwin/release/ripunzip \ - -arch arm64 target/aarch64-apple-darwin/release/ripunzip - - name: Archive - shell: bash - run: | - tar acf ripunzip-$RUNNER_OS.tar.zst ripunzip-$(echo $RUNNER_OS | tr '[:upper:]' '[:lower:]') - - name: Upload built binary - uses: actions/upload-artifact@v4 - with: - name: ripunzip-${{ runner.os }} - path: ripunzip-${{ runner.os }}.tar.zst - retention-days: 5 - compression: 0 - - name: Check built binary - shell: bash - run: | - rm -f ripunzip-*.tar.zst - ./ripunzip-* --version - publish: - needs: [versions, build] - if: inputs.open-pr == 'true' - permissions: - contents: write - pull-requests: write - runs-on: ubuntu-slim - steps: - # workaround for git-lfs not being installed yet on ubuntu-slim runners - - name: Ensure git-lfs is installed - shell: bash - run: | - if which git-lfs &>/dev/null; then - echo "git-lfs is already installed" - exit 0 - fi - cd $TMP - gh release download --repo git-lfs/git-lfs --pattern "git-lfs-linux-amd64-*.tar.gz" --clobber - tar xzf git-lfs-linux-amd64-*.tar.gz - rm git-lfs-linux-amd64-*.tar.gz - cd git-lfs-* - pwd | tee -a $GITHUB_PATH - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/checkout@v5 - with: - sparse-checkout: | - .github - misc/ripunzip - lfs: true - - name: Download built binaries - uses: actions/download-artifact@v4 - with: - merge-multiple: true - path: misc/ripunzip - - name: Open PR - shell: bash - run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git switch -c update-ripunzip - git add misc/ripunzip - git commit -m "Update ripunzip binaries to version $VERSION" - git push --set-upstream origin update-ripunzip --force - TITLE="Update ripunzip binaries to version $VERSION" - gh pr create \ - --draft \ - --title "$TITLE" \ - --body "Automated update of ripunzip binaries." \ - --assignee "$ACTOR" || - (gh pr edit --title "$TITLE" --add-assignee "$ACTOR" && gh pr ready --undo) - env: - ACTOR: ${{ github.actor }} - VERSION: ${{ needs.versions.outputs.ripunzip-version }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/MODULE.bazel b/MODULE.bazel index dfd2c469a5e..a17d0bd36c4 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -269,24 +269,16 @@ go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps") go_deps.from_file(go_mod = "//go/extractor:go.mod") use_repo(go_deps, "org_golang_x_mod", "org_golang_x_tools") -lfs_archive = use_repo_rule("//misc/bazel:lfs.bzl", "lfs_archive") +ripunzip_archive = use_repo_rule("//misc/ripunzip:ripunzip.bzl", "ripunzip_archive") -lfs_archive( - name = "ripunzip-linux", - src = "//misc/ripunzip:ripunzip-Linux.tar.zst", - build_file = "//misc/ripunzip:BUILD.ripunzip.bazel", -) - -lfs_archive( - name = "ripunzip-windows", - src = "//misc/ripunzip:ripunzip-Windows.tar.zst", - build_file = "//misc/ripunzip:BUILD.ripunzip.bazel", -) - -lfs_archive( - name = "ripunzip-macos", - src = "//misc/ripunzip:ripunzip-macOS.tar.zst", - build_file = "//misc/ripunzip:BUILD.ripunzip.bazel", +# go to https://github.com/GoogleChrome/ripunzip/releases to find latest version and corresponding sha256s +ripunzip_archive( + name = "ripunzip", + version = "2.0.3", + sha256_linux = "ee0e8a957687a5dc3a66b2a4b25883bf762df4c9c07f0651af527a32a405054b", + sha256_windows = "66d0c1375301bf5ab815348048f43b110631d3fa7200acd50d50a8ed8655ca62", + sha256_macos_intel = "4457a18bfcc5feabe09f5ea3d1157128e07b4873392cb404a870e611924abf64", + sha256_macos_arm = "8a88eea54eac232d162a72a42065e0429b82dbf4f05e9642915dff9d7a81f846", ) register_toolchains( diff --git a/misc/ripunzip/BUILD.bazel b/misc/ripunzip/BUILD.bazel index fb33124f3b2..abd9c082887 100644 --- a/misc/ripunzip/BUILD.bazel +++ b/misc/ripunzip/BUILD.bazel @@ -2,7 +2,7 @@ load("@rules_shell//shell:sh_binary.bzl", "sh_binary") alias( name = "ripunzip", - actual = select({"@platforms//os:" + os: "@ripunzip-%s//:ripunzip" % os for os in ("linux", "windows", "macos")}), + actual = "@ripunzip", visibility = ["//visibility:public"], ) diff --git a/misc/ripunzip/BUILD.ripunzip.bazel b/misc/ripunzip/BUILD.ripunzip.bazel index e2832d1e275..582138dd3e1 100644 --- a/misc/ripunzip/BUILD.ripunzip.bazel +++ b/misc/ripunzip/BUILD.ripunzip.bazel @@ -2,7 +2,7 @@ load("@bazel_skylib//rules:native_binary.bzl", "native_binary") native_binary( name = "ripunzip", - src = glob(["ripunzip-*"])[0], + src = glob(["bin/ripunzip*"])[0], out = "ripunzip" + select({ "@platforms//os:windows": ".exe", "//conditions:default": "", diff --git a/misc/ripunzip/ripunzip-Linux.tar.zst b/misc/ripunzip/ripunzip-Linux.tar.zst deleted file mode 100644 index c9a5ff1e590..00000000000 --- a/misc/ripunzip/ripunzip-Linux.tar.zst +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:252a54114fde9932d2bf3e7a1592bc6767611682a913519585402b9c51d6e2c7 -size 4707184 diff --git a/misc/ripunzip/ripunzip-Windows.tar.zst b/misc/ripunzip/ripunzip-Windows.tar.zst deleted file mode 100644 index 80e41538135..00000000000 --- a/misc/ripunzip/ripunzip-Windows.tar.zst +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3a4388816c72e0bc8c30741aaae05dc91b46174db406133cad40c783acf4fad6 -size 1765498 diff --git a/misc/ripunzip/ripunzip-macOS.tar.zst b/misc/ripunzip/ripunzip-macOS.tar.zst deleted file mode 100644 index 3ff3253ca5d..00000000000 --- a/misc/ripunzip/ripunzip-macOS.tar.zst +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5a5d8ca7ed78b0da3a572b91556fbf03431c99770072060743c63e2d581d8580 -size 3796231 diff --git a/misc/ripunzip/ripunzip.bzl b/misc/ripunzip/ripunzip.bzl new file mode 100644 index 00000000000..ce2dfbba785 --- /dev/null +++ b/misc/ripunzip/ripunzip.bzl @@ -0,0 +1,51 @@ +def _impl(repository_ctx): + version = repository_ctx.attr.version + url_prefix = "https://github.com/GoogleChrome/ripunzip/releases/download/v%s" % version + build_file = Label("//misc/ripunzip:BUILD.ripunzip.bazel") + if repository_ctx.os.name == "linux": + repository_ctx.download_and_extract( + url="%s/ripunzip_%s-1_amd64.deb" % (url_prefix, version), + sha256=repository_ctx.attr.sha256_linux, + canonical_id="ripunzip-deb", + output="deb", + ) + repository_ctx.extract( + "deb/data.tar.xz", + strip_prefix="usr", + ) + elif repository_ctx.os.name == "windows": + repository_ctx.download_and_extract( + url="%s/ripunzip_v%s-x86_64-pc-windows-msvc.zip" % (url_prefix, version), + sha256=repository_ctx.attr.sha256_windows, + output="bin", + ) + elif repository_ctx.os.name == "macos": + arch = repository_ctx.os.arch + if arch == "x86_64": + suffix = "x86_64-apple-darwin" + sha256 = repository_ctx.attr.sha256_macos_intel + elif arch == "aarch64": + suffix = "aarch64-apple-darwin" + sha256 = repository_ctx.attr.sha256_macos_arm + else: + fail("Unsupported macOS architecture: %s" % arch) + repository_ctx.download_and_extract( + url="%s/ripunzip_v%s-%s.tar.gz" % (url_prefix, version, suffix), + sha256=sha256, + output="bin", + ) + else: + fail("Unsupported OS: %s" % repository_ctx.os.name) + repository_ctx.file("WORKSPACE.bazel") + repository_ctx.symlink(build_file, "BUILD.bazel") + +ripunzip_archive = repository_rule( + implementation=_impl, + attrs={ + "version": attr.string(mandatory=True), + "sha256_linux": attr.string(mandatory=True), + "sha256_windows": attr.string(mandatory=True), + "sha256_macos_intel": attr.string(mandatory=True), + "sha256_macos_arm": attr.string(mandatory=True), + }, +) From a5601ce7344cc2f8ed5b84948d49549f39681b49 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 18 Nov 2025 19:52:05 +0000 Subject: [PATCH 03/15] C++: Lift 'getTypeOperand' to the superclass. --- cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll | 30 ++++++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll index 83364e422eb..e5df5cb160f 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll @@ -750,6 +750,16 @@ class SizeofPackTypeOperator extends SizeofPackOperator { */ class SizeofOperator extends Expr, @runtime_sizeof { override int getPrecedence() { result = 16 } + + /** + * Gets the contained type of this `sizeof`. For example, + * the result is `int` in both cases below: + * ``` + * sizeof(int); + * sizeof(42); + * ``` + */ + Type getTypeOperand() { none() } // overridden in subclasses } /** @@ -766,6 +776,8 @@ class SizeofExprOperator extends SizeofOperator { /** Gets the contained expression. */ Expr getExprOperand() { result = this.getChild(0) } + override Type getTypeOperand() { result = this.getExprOperand().getType() } + override string toString() { result = "sizeof()" } override predicate mayBeImpure() { this.getExprOperand().mayBeImpure() } @@ -784,8 +796,7 @@ class SizeofTypeOperator extends SizeofOperator { override string getAPrimaryQlClass() { result = "SizeofTypeOperator" } - /** Gets the contained type. */ - Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) } + override Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) } override string toString() { result = "sizeof(" + this.getTypeOperand().getName() + ")" } @@ -842,6 +853,16 @@ class AlignofTypeOperator extends AlignofOperator { */ class DatasizeofOperator extends Expr, @datasizeof { override int getPrecedence() { result = 16 } + + /** + * Gets the contained type of this `__datasizeof`. For example, + * the result is `int` in both cases below: + * ``` + * __datasizeof(int); + * __datasizeof(42); + * ``` + */ + Type getTypeOperand() { none() } } /** @@ -855,6 +876,8 @@ class DatasizeofExprOperator extends DatasizeofOperator { /** Gets the contained expression. */ Expr getExprOperand() { result = this.getChild(0) } + override Type getTypeOperand() { result = this.getExprOperand().getType() } + override string toString() { result = "__datasizeof()" } override predicate mayBeImpure() { this.getExprOperand().mayBeImpure() } @@ -870,8 +893,7 @@ class DatasizeofTypeOperator extends DatasizeofOperator { override string getAPrimaryQlClass() { result = "DatasizeofTypeOperator" } - /** Gets the contained type. */ - Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) } + override Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) } override string toString() { result = "__datasizeof(" + this.getTypeOperand().getName() + ")" } From d4a8dbb5f3f5ac168be028d1b9b6aec9142993d1 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 18 Nov 2025 19:52:30 +0000 Subject: [PATCH 04/15] C++: Slightly modify a test so that we can see the effect of this change. --- cpp/ql/test/library-tests/types/sizeof/sizeof.expected | 6 ++++++ cpp/ql/test/library-tests/types/sizeof/sizeof.ql | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/types/sizeof/sizeof.expected b/cpp/ql/test/library-tests/types/sizeof/sizeof.expected index c0d075126df..1e2963bc93b 100644 --- a/cpp/ql/test/library-tests/types/sizeof/sizeof.expected +++ b/cpp/ql/test/library-tests/types/sizeof/sizeof.expected @@ -3,8 +3,14 @@ | sizeof.cpp:21:15:21:27 | sizeof(int *) | 8 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int * | | sizeof.cpp:22:15:22:29 | sizeof(MyClass) | 16 | SizeofTypeOperator.getTypeOperand() | sizeof.cpp:4:7:4:13 | MyClass | | sizeof.cpp:23:15:23:23 | sizeof() | 4 | SizeofExprOperator.getExprOperand() | sizeof.cpp:23:22:23:22 | i | +| sizeof.cpp:23:15:23:23 | sizeof() | 4 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int | | sizeof.cpp:24:15:24:23 | sizeof() | 1 | SizeofExprOperator.getExprOperand() | sizeof.cpp:24:22:24:22 | c | +| sizeof.cpp:24:15:24:23 | sizeof() | 1 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | char | | sizeof.cpp:25:15:25:25 | sizeof() | 8 | SizeofExprOperator.getExprOperand() | sizeof.cpp:25:22:25:24 | ptr | +| sizeof.cpp:25:15:25:25 | sizeof() | 8 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int * | | sizeof.cpp:26:15:26:24 | sizeof() | 16 | SizeofExprOperator.getExprOperand() | sizeof.cpp:26:22:26:23 | mc | +| sizeof.cpp:26:15:26:24 | sizeof() | 16 | SizeofTypeOperator.getTypeOperand() | sizeof.cpp:4:7:4:13 | MyClass | | sizeof.cpp:27:15:27:25 | sizeof() | 40 | SizeofExprOperator.getExprOperand() | sizeof.cpp:27:22:27:24 | arr | +| sizeof.cpp:27:15:27:25 | sizeof() | 40 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int[10] | | sizeof.cpp:28:16:28:29 | sizeof() | 4 | SizeofExprOperator.getExprOperand() | sizeof.cpp:28:23:28:28 | access to array | +| sizeof.cpp:28:16:28:29 | sizeof() | 4 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int | diff --git a/cpp/ql/test/library-tests/types/sizeof/sizeof.ql b/cpp/ql/test/library-tests/types/sizeof/sizeof.ql index 531f55ee45c..0ec6711adb8 100644 --- a/cpp/ql/test/library-tests/types/sizeof/sizeof.ql +++ b/cpp/ql/test/library-tests/types/sizeof/sizeof.ql @@ -3,7 +3,7 @@ import cpp from SizeofOperator sto, string elemDesc, Element e where elemDesc = "SizeofTypeOperator.getTypeOperand()" and - e = sto.(SizeofTypeOperator).getTypeOperand() + e = sto.(SizeofOperator).getTypeOperand() or elemDesc = "SizeofExprOperator.getExprOperand()" and e = sto.(SizeofExprOperator).getExprOperand() From 6b136e3a53229352370d314aa4207d6c89ccd298 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 18 Nov 2025 20:00:32 +0000 Subject: [PATCH 05/15] Update cpp/ql/test/library-tests/types/sizeof/sizeof.ql Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- cpp/ql/test/library-tests/types/sizeof/sizeof.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/types/sizeof/sizeof.ql b/cpp/ql/test/library-tests/types/sizeof/sizeof.ql index 0ec6711adb8..46d78ebbe60 100644 --- a/cpp/ql/test/library-tests/types/sizeof/sizeof.ql +++ b/cpp/ql/test/library-tests/types/sizeof/sizeof.ql @@ -2,7 +2,7 @@ import cpp from SizeofOperator sto, string elemDesc, Element e where - elemDesc = "SizeofTypeOperator.getTypeOperand()" and + elemDesc = "SizeofOperator.getTypeOperand()" and e = sto.(SizeofOperator).getTypeOperand() or elemDesc = "SizeofExprOperator.getExprOperand()" and From a27ac9d59dc47d49ddfd5d64dba052a4e85e5d35 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 18 Nov 2025 20:03:10 +0000 Subject: [PATCH 06/15] C++: Updated expected after Copilot change. --- .../types/sizeof/sizeof.expected | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cpp/ql/test/library-tests/types/sizeof/sizeof.expected b/cpp/ql/test/library-tests/types/sizeof/sizeof.expected index 1e2963bc93b..ac55caf5a02 100644 --- a/cpp/ql/test/library-tests/types/sizeof/sizeof.expected +++ b/cpp/ql/test/library-tests/types/sizeof/sizeof.expected @@ -1,16 +1,16 @@ -| sizeof.cpp:19:15:19:25 | sizeof(int) | 4 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int | -| sizeof.cpp:20:15:20:26 | sizeof(char) | 1 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | char | -| sizeof.cpp:21:15:21:27 | sizeof(int *) | 8 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int * | -| sizeof.cpp:22:15:22:29 | sizeof(MyClass) | 16 | SizeofTypeOperator.getTypeOperand() | sizeof.cpp:4:7:4:13 | MyClass | +| sizeof.cpp:19:15:19:25 | sizeof(int) | 4 | SizeofOperator.getTypeOperand() | file://:0:0:0:0 | int | +| sizeof.cpp:20:15:20:26 | sizeof(char) | 1 | SizeofOperator.getTypeOperand() | file://:0:0:0:0 | char | +| sizeof.cpp:21:15:21:27 | sizeof(int *) | 8 | SizeofOperator.getTypeOperand() | file://:0:0:0:0 | int * | +| sizeof.cpp:22:15:22:29 | sizeof(MyClass) | 16 | SizeofOperator.getTypeOperand() | sizeof.cpp:4:7:4:13 | MyClass | | sizeof.cpp:23:15:23:23 | sizeof() | 4 | SizeofExprOperator.getExprOperand() | sizeof.cpp:23:22:23:22 | i | -| sizeof.cpp:23:15:23:23 | sizeof() | 4 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int | +| sizeof.cpp:23:15:23:23 | sizeof() | 4 | SizeofOperator.getTypeOperand() | file://:0:0:0:0 | int | | sizeof.cpp:24:15:24:23 | sizeof() | 1 | SizeofExprOperator.getExprOperand() | sizeof.cpp:24:22:24:22 | c | -| sizeof.cpp:24:15:24:23 | sizeof() | 1 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | char | +| sizeof.cpp:24:15:24:23 | sizeof() | 1 | SizeofOperator.getTypeOperand() | file://:0:0:0:0 | char | | sizeof.cpp:25:15:25:25 | sizeof() | 8 | SizeofExprOperator.getExprOperand() | sizeof.cpp:25:22:25:24 | ptr | -| sizeof.cpp:25:15:25:25 | sizeof() | 8 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int * | +| sizeof.cpp:25:15:25:25 | sizeof() | 8 | SizeofOperator.getTypeOperand() | file://:0:0:0:0 | int * | | sizeof.cpp:26:15:26:24 | sizeof() | 16 | SizeofExprOperator.getExprOperand() | sizeof.cpp:26:22:26:23 | mc | -| sizeof.cpp:26:15:26:24 | sizeof() | 16 | SizeofTypeOperator.getTypeOperand() | sizeof.cpp:4:7:4:13 | MyClass | +| sizeof.cpp:26:15:26:24 | sizeof() | 16 | SizeofOperator.getTypeOperand() | sizeof.cpp:4:7:4:13 | MyClass | | sizeof.cpp:27:15:27:25 | sizeof() | 40 | SizeofExprOperator.getExprOperand() | sizeof.cpp:27:22:27:24 | arr | -| sizeof.cpp:27:15:27:25 | sizeof() | 40 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int[10] | +| sizeof.cpp:27:15:27:25 | sizeof() | 40 | SizeofOperator.getTypeOperand() | file://:0:0:0:0 | int[10] | | sizeof.cpp:28:16:28:29 | sizeof() | 4 | SizeofExprOperator.getExprOperand() | sizeof.cpp:28:23:28:28 | access to array | -| sizeof.cpp:28:16:28:29 | sizeof() | 4 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int | +| sizeof.cpp:28:16:28:29 | sizeof() | 4 | SizeofOperator.getTypeOperand() | file://:0:0:0:0 | int | From 4279a970fa8dd14b555775bbb0746feef8212d54 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 18 Nov 2025 20:03:24 +0000 Subject: [PATCH 07/15] C++: Remove unnecessary cast. --- cpp/ql/test/library-tests/types/sizeof/sizeof.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/types/sizeof/sizeof.ql b/cpp/ql/test/library-tests/types/sizeof/sizeof.ql index 46d78ebbe60..31834e0180f 100644 --- a/cpp/ql/test/library-tests/types/sizeof/sizeof.ql +++ b/cpp/ql/test/library-tests/types/sizeof/sizeof.ql @@ -3,7 +3,7 @@ import cpp from SizeofOperator sto, string elemDesc, Element e where elemDesc = "SizeofOperator.getTypeOperand()" and - e = sto.(SizeofOperator).getTypeOperand() + e = sto.getTypeOperand() or elemDesc = "SizeofExprOperator.getExprOperand()" and e = sto.(SizeofExprOperator).getExprOperand() From 702d1bbbeacb4e3999f0d4ee516d6be9b851a5e0 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 19 Nov 2025 08:05:17 +0100 Subject: [PATCH 08/15] Ripunzip: fix mac os string --- misc/ripunzip/ripunzip.bzl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/misc/ripunzip/ripunzip.bzl b/misc/ripunzip/ripunzip.bzl index ce2dfbba785..f9046af95a0 100644 --- a/misc/ripunzip/ripunzip.bzl +++ b/misc/ripunzip/ripunzip.bzl @@ -6,7 +6,7 @@ def _impl(repository_ctx): repository_ctx.download_and_extract( url="%s/ripunzip_%s-1_amd64.deb" % (url_prefix, version), sha256=repository_ctx.attr.sha256_linux, - canonical_id="ripunzip-deb", + canonical_id="ripunzip-linux", output="deb", ) repository_ctx.extract( @@ -16,22 +16,26 @@ def _impl(repository_ctx): elif repository_ctx.os.name == "windows": repository_ctx.download_and_extract( url="%s/ripunzip_v%s-x86_64-pc-windows-msvc.zip" % (url_prefix, version), + canonical_id="ripunzip-windows", sha256=repository_ctx.attr.sha256_windows, output="bin", ) - elif repository_ctx.os.name == "macos": + elif repository_ctx.os.name == "mac os x": arch = repository_ctx.os.arch if arch == "x86_64": suffix = "x86_64-apple-darwin" sha256 = repository_ctx.attr.sha256_macos_intel + canonical_id = "ripunzip-macos-intel" elif arch == "aarch64": suffix = "aarch64-apple-darwin" sha256 = repository_ctx.attr.sha256_macos_arm + canonical_id = "ripunzip-macos-arm" else: fail("Unsupported macOS architecture: %s" % arch) repository_ctx.download_and_extract( url="%s/ripunzip_v%s-%s.tar.gz" % (url_prefix, version, suffix), sha256=sha256, + canonical_id=canonical_id, output="bin", ) else: From f1afe5cd9d3a30af59cba095858b535d577ac3c9 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 19 Nov 2025 08:06:17 +0100 Subject: [PATCH 09/15] Bazel: format --- MODULE.bazel | 6 +++--- misc/ripunzip/ripunzip.bzl | 40 +++++++++++++++++++------------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index a17d0bd36c4..fc6acfc1137 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -274,11 +274,11 @@ ripunzip_archive = use_repo_rule("//misc/ripunzip:ripunzip.bzl", "ripunzip_archi # go to https://github.com/GoogleChrome/ripunzip/releases to find latest version and corresponding sha256s ripunzip_archive( name = "ripunzip", - version = "2.0.3", sha256_linux = "ee0e8a957687a5dc3a66b2a4b25883bf762df4c9c07f0651af527a32a405054b", - sha256_windows = "66d0c1375301bf5ab815348048f43b110631d3fa7200acd50d50a8ed8655ca62", - sha256_macos_intel = "4457a18bfcc5feabe09f5ea3d1157128e07b4873392cb404a870e611924abf64", sha256_macos_arm = "8a88eea54eac232d162a72a42065e0429b82dbf4f05e9642915dff9d7a81f846", + sha256_macos_intel = "4457a18bfcc5feabe09f5ea3d1157128e07b4873392cb404a870e611924abf64", + sha256_windows = "66d0c1375301bf5ab815348048f43b110631d3fa7200acd50d50a8ed8655ca62", + version = "2.0.3", ) register_toolchains( diff --git a/misc/ripunzip/ripunzip.bzl b/misc/ripunzip/ripunzip.bzl index f9046af95a0..b843cdff76b 100644 --- a/misc/ripunzip/ripunzip.bzl +++ b/misc/ripunzip/ripunzip.bzl @@ -4,21 +4,21 @@ def _impl(repository_ctx): build_file = Label("//misc/ripunzip:BUILD.ripunzip.bazel") if repository_ctx.os.name == "linux": repository_ctx.download_and_extract( - url="%s/ripunzip_%s-1_amd64.deb" % (url_prefix, version), - sha256=repository_ctx.attr.sha256_linux, - canonical_id="ripunzip-linux", - output="deb", + url = "%s/ripunzip_%s-1_amd64.deb" % (url_prefix, version), + sha256 = repository_ctx.attr.sha256_linux, + canonical_id = "ripunzip-linux", + output = "deb", ) repository_ctx.extract( "deb/data.tar.xz", - strip_prefix="usr", + strip_prefix = "usr", ) elif repository_ctx.os.name == "windows": repository_ctx.download_and_extract( - url="%s/ripunzip_v%s-x86_64-pc-windows-msvc.zip" % (url_prefix, version), - canonical_id="ripunzip-windows", - sha256=repository_ctx.attr.sha256_windows, - output="bin", + url = "%s/ripunzip_v%s-x86_64-pc-windows-msvc.zip" % (url_prefix, version), + canonical_id = "ripunzip-windows", + sha256 = repository_ctx.attr.sha256_windows, + output = "bin", ) elif repository_ctx.os.name == "mac os x": arch = repository_ctx.os.arch @@ -33,10 +33,10 @@ def _impl(repository_ctx): else: fail("Unsupported macOS architecture: %s" % arch) repository_ctx.download_and_extract( - url="%s/ripunzip_v%s-%s.tar.gz" % (url_prefix, version, suffix), - sha256=sha256, - canonical_id=canonical_id, - output="bin", + url = "%s/ripunzip_v%s-%s.tar.gz" % (url_prefix, version, suffix), + sha256 = sha256, + canonical_id = canonical_id, + output = "bin", ) else: fail("Unsupported OS: %s" % repository_ctx.os.name) @@ -44,12 +44,12 @@ def _impl(repository_ctx): repository_ctx.symlink(build_file, "BUILD.bazel") ripunzip_archive = repository_rule( - implementation=_impl, - attrs={ - "version": attr.string(mandatory=True), - "sha256_linux": attr.string(mandatory=True), - "sha256_windows": attr.string(mandatory=True), - "sha256_macos_intel": attr.string(mandatory=True), - "sha256_macos_arm": attr.string(mandatory=True), + implementation = _impl, + attrs = { + "version": attr.string(mandatory = True), + "sha256_linux": attr.string(mandatory = True), + "sha256_windows": attr.string(mandatory = True), + "sha256_macos_intel": attr.string(mandatory = True), + "sha256_macos_arm": attr.string(mandatory = True), }, ) From 69ee9cdb9f91fdbc10f51db052dad976f7e09ce1 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 19 Nov 2025 08:12:07 +0100 Subject: [PATCH 10/15] Ripunzip: fix mac os and windows URLs --- misc/ripunzip/ripunzip.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc/ripunzip/ripunzip.bzl b/misc/ripunzip/ripunzip.bzl index b843cdff76b..823b563b60d 100644 --- a/misc/ripunzip/ripunzip.bzl +++ b/misc/ripunzip/ripunzip.bzl @@ -15,7 +15,7 @@ def _impl(repository_ctx): ) elif repository_ctx.os.name == "windows": repository_ctx.download_and_extract( - url = "%s/ripunzip_v%s-x86_64-pc-windows-msvc.zip" % (url_prefix, version), + url = "%s/ripunzip_v%s_x86_64-pc-windows-msvc.zip" % (url_prefix, version), canonical_id = "ripunzip-windows", sha256 = repository_ctx.attr.sha256_windows, output = "bin", @@ -33,7 +33,7 @@ def _impl(repository_ctx): else: fail("Unsupported macOS architecture: %s" % arch) repository_ctx.download_and_extract( - url = "%s/ripunzip_v%s-%s.tar.gz" % (url_prefix, version, suffix), + url = "%s/ripunzip_v%s_%s.tar.gz" % (url_prefix, version, suffix), sha256 = sha256, canonical_id = canonical_id, output = "bin", From 3be8591370b2018506e96473d2a36ad86352c1e5 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 19 Nov 2025 08:56:06 +0100 Subject: [PATCH 11/15] Ripunzip: fix windows os check, add comments --- misc/ripunzip/ripunzip.bzl | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/misc/ripunzip/ripunzip.bzl b/misc/ripunzip/ripunzip.bzl index 823b563b60d..2e707c267e2 100644 --- a/misc/ripunzip/ripunzip.bzl +++ b/misc/ripunzip/ripunzip.bzl @@ -1,8 +1,10 @@ -def _impl(repository_ctx): +def _ripunzip_archive_impl(repository_ctx): version = repository_ctx.attr.version url_prefix = "https://github.com/GoogleChrome/ripunzip/releases/download/v%s" % version build_file = Label("//misc/ripunzip:BUILD.ripunzip.bazel") - if repository_ctx.os.name == "linux": + if "linux" in repository_ctx.os.name: + # ripunzip only provides a deb package for Linux: we fish the binary out of it + # a deb archive contains a data.tar.xz one which contains the files to be installed under usr/bin repository_ctx.download_and_extract( url = "%s/ripunzip_%s-1_amd64.deb" % (url_prefix, version), sha256 = repository_ctx.attr.sha256_linux, @@ -11,16 +13,17 @@ def _impl(repository_ctx): ) repository_ctx.extract( "deb/data.tar.xz", - strip_prefix = "usr", + strip_prefix = "usr/bin", + output = "bin", ) - elif repository_ctx.os.name == "windows": + elif "windows" in repository_ctx.os.name: repository_ctx.download_and_extract( url = "%s/ripunzip_v%s_x86_64-pc-windows-msvc.zip" % (url_prefix, version), canonical_id = "ripunzip-windows", sha256 = repository_ctx.attr.sha256_windows, output = "bin", ) - elif repository_ctx.os.name == "mac os x": + elif "mac os" in repository_ctx.os.name: arch = repository_ctx.os.arch if arch == "x86_64": suffix = "x86_64-apple-darwin" @@ -44,7 +47,8 @@ def _impl(repository_ctx): repository_ctx.symlink(build_file, "BUILD.bazel") ripunzip_archive = repository_rule( - implementation = _impl, + implementation = _ripunzip_archive_impl, + doc = "Downloads a prebuilt ripunzip binary for the host platform from https://github.com/GoogleChrome/ripunzip/releases", attrs = { "version": attr.string(mandatory = True), "sha256_linux": attr.string(mandatory = True), From e235e0473ad3ffd9a2d60febd0df14185e436f01 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Wed, 19 Nov 2025 12:49:02 +0100 Subject: [PATCH 12/15] C++: Fix `getAnExpandedArgument` The fix was accidentially lost when rebasing the branch that introduced this predicate. --- cpp/ql/lib/semmle/code/cpp/Compilation.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/Compilation.qll b/cpp/ql/lib/semmle/code/cpp/Compilation.qll index c4b3796dec8..87bf586842c 100644 --- a/cpp/ql/lib/semmle/code/cpp/Compilation.qll +++ b/cpp/ql/lib/semmle/code/cpp/Compilation.qll @@ -97,7 +97,7 @@ class Compilation extends @compilation { /** * Gets an expanded argument passed to the extractor on this invocation. */ - string getAnExpandedArgument() { result = this.getArgument(_) } + string getAnExpandedArgument() { result = this.getExpandedArgument(_) } /** * Gets the `i`th expanded argument passed to the extractor on this From fe3f90e0415b8923955aad56c89b663dfcdded08 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Wed, 19 Nov 2025 12:49:54 +0100 Subject: [PATCH 13/15] C++: Make `getExpandedArgument` more robust This make the predicate give back sensible results on (upgraded) databases where we do not have expanded arguments, and avoid having to write case distinctions in places where we would want to use `getExpandedArgument`. --- cpp/ql/lib/semmle/code/cpp/Compilation.qll | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/Compilation.qll b/cpp/ql/lib/semmle/code/cpp/Compilation.qll index 87bf586842c..6f19be0481a 100644 --- a/cpp/ql/lib/semmle/code/cpp/Compilation.qll +++ b/cpp/ql/lib/semmle/code/cpp/Compilation.qll @@ -107,7 +107,11 @@ class Compilation extends @compilation { * includes the arguments from that file, rather than just taking the * argument literally. */ - string getExpandedArgument(int i) { compilation_expanded_args(this, i, result) } + string getExpandedArgument(int i) { + if exists(string arg | compilation_expanded_args(this, _, arg)) + then compilation_expanded_args(this, i, result) + else result = this.getArgument(i) + } /** * Gets the total amount of CPU time spent processing all the files in the From 481f627ae0b8d581b18267f221081dba9989127f Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Wed, 19 Nov 2025 13:34:26 +0100 Subject: [PATCH 14/15] Rust: Add string literal test --- .../extractor-tests/literal/literal.expected | 48 +++++++++---------- .../test/extractor-tests/literal/literal.rs | 11 +++++ 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/rust/ql/test/extractor-tests/literal/literal.expected b/rust/ql/test/extractor-tests/literal/literal.expected index d229d968467..90857eebe63 100644 --- a/rust/ql/test/extractor-tests/literal/literal.expected +++ b/rust/ql/test/extractor-tests/literal/literal.expected @@ -17,29 +17,29 @@ stringLiteral | literal.rs:22:5:22:11 | "\\\\x52" | | literal.rs:23:5:23:11 | r"\\x52" | integerLiteral -| literal.rs:28:5:28:7 | 123 | | -| literal.rs:29:5:29:10 | 123i32 | i32 | -| literal.rs:30:5:30:10 | 123u32 | u32 | -| literal.rs:31:5:31:11 | 123_u32 | u32 | -| literal.rs:33:5:33:8 | 0xff | | -| literal.rs:34:5:34:11 | 0xff_u8 | u8 | -| literal.rs:35:5:35:12 | 0x01_f32 | | -| literal.rs:36:5:36:11 | 0x01_e3 | | -| literal.rs:38:5:38:8 | 0o70 | | -| literal.rs:39:5:39:12 | 0o70_i16 | i16 | -| literal.rs:41:5:41:25 | 0b1111_1111_1001_0000 | | -| literal.rs:42:5:42:28 | 0b1111_1111_1001_0000i64 | i64 | -| literal.rs:43:5:43:15 | 0b________1 | | -| literal.rs:45:5:45:10 | 0usize | usize | -| literal.rs:48:5:49:10 | 128_i8 | i8 | -| literal.rs:50:5:51:10 | 256_u8 | u8 | +| literal.rs:39:5:39:7 | 123 | | +| literal.rs:40:5:40:10 | 123i32 | i32 | +| literal.rs:41:5:41:10 | 123u32 | u32 | +| literal.rs:42:5:42:11 | 123_u32 | u32 | +| literal.rs:44:5:44:8 | 0xff | | +| literal.rs:45:5:45:11 | 0xff_u8 | u8 | +| literal.rs:46:5:46:12 | 0x01_f32 | | +| literal.rs:47:5:47:11 | 0x01_e3 | | +| literal.rs:49:5:49:8 | 0o70 | | +| literal.rs:50:5:50:12 | 0o70_i16 | i16 | +| literal.rs:52:5:52:25 | 0b1111_1111_1001_0000 | | +| literal.rs:53:5:53:28 | 0b1111_1111_1001_0000i64 | i64 | +| literal.rs:54:5:54:15 | 0b________1 | | +| literal.rs:56:5:56:10 | 0usize | usize | +| literal.rs:59:5:60:10 | 128_i8 | i8 | +| literal.rs:61:5:62:10 | 256_u8 | u8 | floatLiteral -| literal.rs:56:5:56:8 | 5f32 | f32 | -| literal.rs:58:5:58:12 | 123.0f64 | f64 | -| literal.rs:59:5:59:10 | 0.1f64 | f64 | -| literal.rs:60:5:60:10 | 0.1f32 | f32 | -| literal.rs:61:5:61:14 | 12E+99_f64 | f64 | -| literal.rs:62:18:62:19 | 2. | | +| literal.rs:67:5:67:8 | 5f32 | f32 | +| literal.rs:69:5:69:12 | 123.0f64 | f64 | +| literal.rs:70:5:70:10 | 0.1f64 | f64 | +| literal.rs:71:5:71:10 | 0.1f32 | f32 | +| literal.rs:72:5:72:14 | 12E+99_f64 | f64 | +| literal.rs:73:18:73:19 | 2. | | booleanLiteral -| literal.rs:66:5:66:8 | true | -| literal.rs:67:5:67:9 | false | +| literal.rs:77:5:77:8 | true | +| literal.rs:78:5:78:9 | false | diff --git a/rust/ql/test/extractor-tests/literal/literal.rs b/rust/ql/test/extractor-tests/literal/literal.rs index ea4ccdece63..4a91c3e7041 100644 --- a/rust/ql/test/extractor-tests/literal/literal.rs +++ b/rust/ql/test/extractor-tests/literal/literal.rs @@ -21,6 +21,17 @@ fn string_literals() { r"R"; // R "\\x52"; r"\x52"; // \x52 + + " + A normal string literal + across many + lines + "; + + r#" + A raw string literal + across multiple lines + "#; } fn integer_literals() { From 0e539dbca5716c6e643620770309704ef579ec23 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Wed, 19 Nov 2025 13:39:48 +0100 Subject: [PATCH 15/15] Rust: Handle string literals with line breaks --- rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll | 2 +- rust/ql/test/extractor-tests/literal/literal.expected | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll index a836a4c4075..45c18ac3a9d 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll @@ -68,7 +68,7 @@ module Impl { * [1]: https://doc.rust-lang.org/reference/tokens.html#string-literals */ class StringLiteralExpr extends LiteralExpr { - StringLiteralExpr() { this.getTextValue().regexpMatch("r?#*\".*\"#*") } + StringLiteralExpr() { this.getTextValue().charAt(0) = ["\"", "r"] } override string getAPrimaryQlClass() { result = "StringLiteralExpr" } } diff --git a/rust/ql/test/extractor-tests/literal/literal.expected b/rust/ql/test/extractor-tests/literal/literal.expected index 90857eebe63..bc08d37fc96 100644 --- a/rust/ql/test/extractor-tests/literal/literal.expected +++ b/rust/ql/test/extractor-tests/literal/literal.expected @@ -16,6 +16,8 @@ stringLiteral | literal.rs:21:5:21:8 | r"R" | | literal.rs:22:5:22:11 | "\\\\x52" | | literal.rs:23:5:23:11 | r"\\x52" | +| literal.rs:25:5:29:5 | "\n A normal string literal\n... | +| literal.rs:31:5:34:6 | r#"\n A raw string literal\n ... | integerLiteral | literal.rs:39:5:39:7 | 123 | | | literal.rs:40:5:40:10 | 123i32 | i32 |