Compare commits

..

286 Commits

Author SHA1 Message Date
Henry Mercer
fedb9464af Merge pull request #21248 from github/henrymercer/fix-mysql-typo
Fix capitalization of MySQL
2026-02-02 05:33:39 -08:00
Henry Mercer
1a6b2b9b82 Fix capitalization of MySQL 2026-02-02 12:37:32 +00:00
Henry Mercer
57c2208f7a Merge pull request #21246 from github/henrymercer/kotlin/version-range-formatting
Fix formatting of Kotlin version ranges
2026-02-02 04:30:52 -08:00
Henry Mercer
5f1fd57f84 Fix formatting of Kotlin version ranges 2026-02-02 12:22:50 +00:00
Henry Mercer
6b78313701 Merge pull request #21245 from github/release-prep/2.24.1
Release preparation for version 2.24.1
2026-02-02 04:12:14 -08:00
Henry Mercer
38fcc61817 Fix formatting in Kotlin changelog 2026-02-02 12:10:15 +00:00
github-actions[bot]
0db542e9f0 Release preparation for version 2.24.1 2026-02-02 12:09:09 +00:00
Tom Hvitved
4a04f7b66f Merge pull request #21243 from hvitved/csharp/insecure-object-tests
C#: Add more tests for `InsecureDirectObjectReference.ql`
2026-02-02 13:03:23 +01:00
Tom Hvitved
fe0634574d C#: Add more tests for InsecureDirectObjectReference.ql 2026-02-02 11:09:26 +01:00
Michael B. Gale
9a00c75460 Merge pull request #21236 from github/mbg/csharp/fix-registry-feeds
C#: Make sure `allFeeds` contains at least `explicitFeeds`
2026-02-02 07:49:33 +00:00
Owen Mansel-Chan
5204255615 Merge pull request #21234 from owen-mc/python/convert-sanitizers-to-mad
Python: Allow models-as-data sanitizers
2026-01-30 14:28:39 +00:00
Owen Mansel-Chan
0222159df5 Specify vulnerable args instead of safe ones 2026-01-30 14:10:03 +00:00
Michael B. Gale
454d13b485 Remove element check 2026-01-30 14:03:43 +00:00
Mathias Vorreiter Pedersen
16670511de Merge pull request #21239 from MathiasVP/logical-binary-fix-guards-cpp
C++: Ensure that there are AST `GuardCondition`s for `||` and `&&`
2026-01-30 13:50:55 +00:00
Michael B. Gale
ad2aa6d4f8 Accept expected diagnostic output 2026-01-30 13:38:50 +00:00
Michael B. Gale
3e0719609f Fix missing negation 2026-01-30 13:30:47 +00:00
Michael B. Gale
1aba0b20cd Add integration test 2026-01-30 13:19:47 +00:00
Michael B. Gale
1b5ed129ac Log and emit diagnostic if incorrectly named files are found 2026-01-30 13:19:46 +00:00
Mathias Vorreiter Pedersen
5f079c1d51 C++: Add change note. 2026-01-30 12:19:28 +00:00
Michael B. Gale
5ba3b679dd Move into if statement 2026-01-30 12:18:56 +00:00
yoff
8c0baefd3b Merge pull request #21141 from mbaluda/prompt-injection
Python: Prompt injection in OpenAI clients
2026-01-30 12:55:56 +01:00
Anders Peter Fugmann
78495035a6 Merge pull request #20965 from github/andersfugmann/kotlin_2.3.0-beta2
Kotlin: Support Kotlin 2.3.0
2026-01-30 11:37:19 +01:00
Owen Mansel-Chan
a3885cd8b2 Replace sanitizer by exclusion from sink definition 2026-01-30 09:28:02 +00:00
Owen Mansel-Chan
b4cb2c3f13 Make qldoc slightly more specific 2026-01-30 09:28:01 +00:00
Owen Mansel-Chan
ef6332c581 Allow MaD sanitizers for queries with MaD sinks 2026-01-30 09:27:59 +00:00
Owen Mansel-Chan
ad6f800022 Pretty print model numbers in tests 2026-01-30 09:21:24 +00:00
Owen Mansel-Chan
e5f52f086c Merge pull request #21235 from owen-mc/shared/docs/provenance-path-graph
Shared: Add missing QLDocs
2026-01-30 09:02:48 +00:00
Jon Janego
18a2aca42f Merge pull request #21237 from github/urllib-typo-fix
Urllib typo fix
2026-01-29 17:32:12 -06:00
yoff
e7a0fc7140 python: Add query for prompt injection
This pull request introduces a new CodeQL query for detecting prompt injection vulnerabilities in Python code targeting AI prompting APIs such as agents and openai. The changes includes a new experimental query, new taint flow and type models, a customizable dataflow configuration, documentation, and comprehensive test coverage.
2026-01-29 23:47:52 +01:00
Jon Janego
f14ccd8c81 Fix typo in taint flow model for urllib.parse 2026-01-29 16:21:14 -06:00
Jon Janego
e54d7c7c73 Update CHANGELOG.md 2026-01-29 16:20:25 -06:00
Jon Janego
813d4639ca Fix typo in taint flow model for urllib.parse 2026-01-29 16:18:21 -06:00
Michael B. Gale
76fe3fa502 C#: Make sure allFeeds contains at least explicitFeeds 2026-01-29 21:43:44 +00:00
Owen Mansel-Chan
8b936c5dbe Add missing QLDocs 2026-01-29 16:45:23 +00:00
Taus
34800d1519 Merge pull request #20945 from joefarebrother/python-websockets
Python: Model remote flow sources for the `websockets` library
2026-01-29 15:47:46 +01:00
Jon Janego
1644376cc9 Merge pull request #21222 from github/codeql-spark-run-21376405640
Update changelog documentation site
2026-01-29 08:44:11 -06:00
Mathias Vorreiter Pedersen
1b1c9c680c Merge pull request #21227 from MathiasVP/postfix-fix
C++: Get rid of an ugly workaround in dataflow
2026-01-29 12:25:02 +00:00
Mathias Vorreiter Pedersen
61a53fadc0 C++: Fix spelling. 2026-01-29 11:50:44 +00:00
Mathias Vorreiter Pedersen
25647badbd C++: Fix the AST wrapper for binary logical operators. 2026-01-28 14:06:10 +00:00
Mathias Vorreiter Pedersen
6445fd805d C++: Fix IR -> AST mapping for basic blocks. 2026-01-28 14:01:34 +00:00
Owen Mansel-Chan
a35e7b27af Merge pull request #21226 from owen-mc/java/update-qhelp-unrelease-lock
Java: Improve qhelp for `java/unreleased-lock` and add lock type exclusion
2026-01-28 09:46:31 +00:00
Anders Fugmann
ab495fa843 Kotlin: Inline cast 2026-01-28 10:11:22 +01:00
Anders Fugmann
2320d502db Kotlin: Address detections from kotin internal queries 2026-01-28 10:11:21 +01:00
Anders Fugmann
31867a56fb Kotlin: Accept test changes
Accept test changes from Kotlin 2.3.0 update

Updates expected test outputs for kotlin2 library tests to match
actual compiler output. Changes include:
- Location adjustments for properties/methods (now point to identifiers)
- CastExpr -> ImplicitCastExpr for implicit type casts
- Removed duplicate BlockStmt entries in loop ASTs
- Super constructor call location changes

Note that in Kotlin 2.3.0 super constructor calls now have locations spanning
entire class declarations instead of the actual super call site.
2026-01-28 10:11:21 +01:00
Anders Fugmann
86d9c349ec Kotlin: Accept test changes 2026-01-28 10:11:21 +01:00
Anders Fugmann
59fa01e386 Kotlin: Add bitwise 'and' operation expected by Kotlin 2.3 compiler to exist in the stdlib 2026-01-28 10:11:20 +01:00
Anders Fugmann
a6f8af0de5 Kotlin: Accept column location changes in tests 2026-01-28 10:11:20 +01:00
Anders Fugmann
f6f5b7e1e9 Kotlin: Accept test changes after rebasing to include changes from https://github.com/github/codeql/pull/21216 2026-01-28 10:11:19 +01:00
Anders Fugmann
275724000b Kotlin: Update kotlin serialization integration test to use Kotlin compiler 1.8.10 and accept test changes 2026-01-28 09:30:22 +01:00
Anders Fugmann
939f3e83aa Kotlin: Update kotlin compiler version in integration tests 2026-01-28 09:30:22 +01:00
Anders Fugmann
d69fe20d7d Kotlin: Bump upper bound for supported kotlin version in integration test 2026-01-28 09:30:22 +01:00
Anders Fugmann
9f5de6b4f2 Kotlin: Bump versions in documentation 2026-01-28 09:30:21 +01:00
Anders Fugmann
6d60595d73 Kotlin: Add changenotes for Kotlin 2.3 support and removal of support for Kotlin 1.6 and 1.7 2026-01-28 09:30:21 +01:00
Anders Fugmann
e1f3d5b374 Kotlin: Do not skip writing of getter and setters if the local deligate is null 2026-01-28 09:30:20 +01:00
Anders Fugmann
5cdfb77504 Kotlin: Add additional warning suppresion to v1_9_0 and remove copy in v2_3_0 2026-01-28 09:30:20 +01:00
Anders Fugmann
8ee35231c2 Kotlin: Remove support for Kotlin versions 1.6 and 1.7
This change rolls up all files from v1_6_0, v1_6_20, v1_7_0 and v_1_7_20.
In addition, versioned files that are not overridden by any later Kotlin versions (i.e. files that only have one copy under utils/versions) are inlined and removed to simplify list of changes.

List of removed/inlined files:
     allOverriddenIncludingSelf.kt
     copyTo.kt
     ExperimentalCompilerApi.kt
     getFileClassFqName.kt
     IsUnderscoreParameter.kt
     ReferenceEntity.kt
     SyntheticBodyKind.kt
     Types.kt
     withHasQuestionMark.kt
2026-01-28 09:30:20 +01:00
Anders Fugmann
55525279ca Kotlin: Remove obsolete file 2026-01-28 09:30:19 +01:00
Anders Fugmann
4d7c84178a Kotlin: Fix spelling 2026-01-28 09:30:19 +01:00
Anders Fugmann
eb37255c4b Kotlin: Create IrSimpleType factory function to support constructor changes introduced in Kotlin 2.3 2026-01-28 09:30:18 +01:00
Anders Fugmann
164cae845d Kotlin: Strip prefix when building plugin 2026-01-28 09:30:18 +01:00
Anders Fugmann
b8d01ed21b Kotlin: Fix bazel format and address copilot review comments 2026-01-28 09:30:18 +01:00
Anders Fugmann
cc25d30fed Kotlin: Update compiler plugin for Kotlin 2.3.0 2026-01-28 09:30:17 +01:00
Anders Fugmann
07e5479aff Kotlin: Add support for Kotlin 2.3.0 2026-01-28 09:30:17 +01:00
Anders Fugmann
bc419fd35c Kotlin: Silence compilation warnings 2026-01-28 09:30:16 +01:00
Anders Fugmann
772503bad8 Kotlin: Remove resource_strip_prefix for kotlin extraction 2026-01-28 09:30:16 +01:00
Anders Fugmann
beff080ee7 Kotlin: Update kotlin_rules to 2.2.0 and remove support for Kotlin 1.6 and 1.7 2026-01-28 09:30:16 +01:00
Anders Peter Fugmann
f4edff9452 Merge pull request #21216 from github/andersfugmann/kotlin_extractor_load_last
Kotlin: Load kotlin extractor last
2026-01-28 09:22:46 +01:00
Mathias Vorreiter Pedersen
4503c625b4 C++: Implement copilot suggestions. 2026-01-27 19:02:28 +00:00
Mathias Vorreiter Pedersen
28fec0c129 C++: Accept test changes. 2026-01-27 18:29:21 +00:00
Mathias Vorreiter Pedersen
445cca1432 C++: Proper SSA support for post-crement reads. 2026-01-27 18:29:12 +00:00
Henry Mercer
497135593c Merge branch 'main' into codeql-spark-run-21376405640 2026-01-27 09:11:02 -08:00
Henry Mercer
2214a944bb Merge pull request #21225 from github/rc/3.20
Merge `rc/3.20` back to `main`
2026-01-27 07:56:58 -08:00
Owen Mansel-Chan
a0c35516bd Add change note 2026-01-27 15:48:04 +00:00
Owen Mansel-Chan
42cbe0734e Specify what lock types are considered in qhelp 2026-01-27 15:39:03 +00:00
Owen Mansel-Chan
516b84b59a Add test for *Pool exclusion 2026-01-27 15:38:29 +00:00
Owen Mansel-Chan
4f1ad0ff5d Exclude *Pool classes from LockType 2026-01-27 15:38:06 +00:00
Jon Janego
ccc4d8ae3f Update docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.24.0.rst
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-27 09:18:25 -06:00
Jon Janego
1c5a9053f9 Fix typo in call graph description in change notes 2026-01-27 09:17:40 -06:00
Jon Janego
5a08adc06c Update docs/codeql/codeql-overview/codeql-changelog/codeql-cli-2.23.1.rst
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-27 09:11:01 -06:00
Jon Janego
0b8b75ac25 Update codeql-cli-2.23.1.rst 2026-01-27 09:10:37 -06:00
Mads Navntoft
b7125a009e Merge pull request #21221 from github/navntoft/struts
Java: Add support for Struts 7.x package names
2026-01-27 15:53:26 +01:00
Owen Mansel-Chan
97a0b9f0ca (trivial) Remove double spaces in qhelp 2026-01-27 14:40:23 +00:00
Ian Lynagh
46a5035543 Merge pull request #21200 from github/igfoo/rename-holdsInBase-to-isBase
C++: Rename `holdsInBase` to `isBase`
2026-01-27 13:50:04 +00:00
Ian Lynagh
bb71790a53 Merge pull request #21199 from github/igfoo/refactorOverlayFunctionCalls
C++ overlay: Simplify QL
2026-01-27 13:03:01 +00:00
Mathias Vorreiter Pedersen
db3f22a2e8 C++: Another small refactor. 2026-01-27 12:46:52 +00:00
Mathias Vorreiter Pedersen
3d445be926 C++: Small refactor. 2026-01-27 12:46:48 +00:00
Mads Navntoft
ede05b54ea Java: Add change note for Struts 7.x package name support 2026-01-27 13:00:16 +01:00
Mads Navntoft
9a94d0474c Java: Add support for Struts 7.x package names
Updates Struts library to recognize both legacy xwork2 and new struts2
packages:
- StrutsActions.qll: Add org.apache.struts2 alternatives for Action,
  Preparable, ActionSupport
- StrutsConventions.qll: Add org.apache.struts2.action.Action
  alternative

This maintains backward compatibility for analyzing Struts 2.x-6.x apps
while supporting Struts 7.x which renamed packages from
com.opensymphony.xwork2 to org.apache.struts2.
2026-01-27 12:57:55 +01:00
Mathias Vorreiter Pedersen
9e9d57bac5 Merge pull request #21219 from MathiasVP/force-more-uniquess-in-buffer-overflow
C++: Enforce more uniqueness in `Buffer.qll`
2026-01-27 11:00:40 +00:00
Owen Mansel-Chan
8e3c373548 Merge pull request #21223 from github/workflow/coverage/update
Update CSV framework coverage reports
2026-01-27 10:35:28 +00:00
github-actions[bot]
f49531b3ca Add changed framework coverage reports 2026-01-27 00:28:39 +00:00
github-actions[bot]
0f4f0b880a update codeql documentation 2026-01-26 22:32:02 +00:00
Mathias Vorreiter Pedersen
e0a7889b71 C++: Undo the hack. 2026-01-26 21:28:21 +00:00
Mathias Vorreiter Pedersen
bd09aad7d5 C++: Add tests. 2026-01-26 21:24:22 +00:00
Mathias Vorreiter Pedersen
980c4cf5f4 Update cpp/ql/lib/semmle/code/cpp/commons/Buffer.qll
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-26 19:12:38 +00:00
Mathias Vorreiter Pedersen
544015d0a6 C++: Add change note. 2026-01-26 19:12:14 +00:00
Tom Hvitved
b974a84bef Merge pull request #21051 from hvitved/shared/flow-summary-provenance-filtering
Shared: Provenance-based filtering of flow summaries
2026-01-26 17:24:34 +01:00
Mathias Vorreiter Pedersen
aed0e688f5 C++: Remove uniqueness since it is enforced earlier now. 2026-01-26 15:01:40 +00:00
Mathias Vorreiter Pedersen
13a5249a9d C++: Enforce uniqueness in the other branch of 'getSize'. 2026-01-26 15:00:58 +00:00
Mathias Vorreiter Pedersen
91752e5307 C++: Enforce uniqueness in 'getVariableSize'. 2026-01-26 15:00:00 +00:00
Anders Fugmann
73850f1b56 Kotlin: Add changenote 2026-01-26 13:27:34 +01:00
yoff
2bd4ccee45 Merge pull request #21004 from yoff/python/mad-barriers
Python: MaD barriers
2026-01-26 13:11:21 +01:00
Tom Hvitved
df09f02981 Shared: Shadow hasManualModel in RelevantSummarizedCallable 2026-01-26 12:40:25 +01:00
Tom Hvitved
732c60c07c C#: Revert change to getASummarizedCallableTarget 2026-01-26 12:40:24 +01:00
Tom Hvitved
0f6bae0ae1 Add change notes 2026-01-26 12:40:22 +01:00
Tom Hvitved
93dad867cd JS: Adapt to changes in FlowSummaryImpl 2026-01-26 12:40:21 +01:00
Tom Hvitved
3b1e062985 C++: Adapt to changes in FlowSummaryImpl 2026-01-26 12:40:20 +01:00
Tom Hvitved
0adece7cde Python: Adapt to changes in FlowSummaryImpl 2026-01-26 12:40:19 +01:00
Tom Hvitved
739748c29b Go: Adapt to changes in FlowSummaryImpl 2026-01-26 12:40:18 +01:00
Tom Hvitved
47d9e8a357 Swift: Adapt to changes in FlowSummaryImpl 2026-01-26 12:40:17 +01:00
Tom Hvitved
7024b07dd2 Java: Adapt to changes in FlowSummaryImpl
Missing manual models were added using the following code added to `FlowSummaryImpl.qll`:

```ql
    private predicate testsummaryElement(
      Input::SummarizedCallableBase c, string namespace, string type, boolean subtypes, string name,
      string signature, string ext, string originalInput, string originalOutput, string kind,
      string provenance, string model, boolean isExact
    ) {
      exists(string input, string output, Callable baseCallable |
        summaryModel(namespace, type, subtypes, name, signature, ext, originalInput, originalOutput,
          kind, provenance, model) and
        baseCallable = interpretElement(namespace, type, subtypes, name, signature, ext, isExact) and
        (
          c.asCallable() = baseCallable and input = originalInput and output = originalOutput
          or
          correspondingKotlinParameterDefaultsArgSpec(baseCallable, c.asCallable(), originalInput,
            input) and
          correspondingKotlinParameterDefaultsArgSpec(baseCallable, c.asCallable(), originalOutput,
            output)
        )
      )
    }

    private predicate testsummaryElement2(
      string namespace, string type, boolean subtypes, string name, string signature, string ext,
      string originalInput, string originalOutput, string kind, string provenance, string model,
      string namespace2, string type2
    ) {
      exists(Input::SummarizedCallableBase c |
        testsummaryElement(c, namespace2, type2, _, _, _, ext, originalInput, originalOutput, kind,
          provenance, model, false) and
        testsummaryElement(c, namespace, type, subtypes, name, _, _, _, _, _, provenance, _, true) and
        signature = paramsString(c.asCallable()) and
        not testsummaryElement(c, _, _, _, _, _, _, originalInput, originalOutput, kind, provenance,
          _, true)
      )
    }

    private string getAMissingManualModel(string namespace2, string type2) {
      exists(
        string namespace, string type, boolean subtypes, string name, string signature, string ext,
        string originalInput, string originalOutput, string kind, string provenance, string model
      |
        testsummaryElement2(namespace, type, subtypes, name, signature, ext, originalInput,
          originalOutput, kind, provenance, model, namespace2, type2) and
        result =
          "- [\"" + namespace + "\", \"" + type + "\", True, \"" + name + "\", \"" + signature +
            "\", \"\", \"" + originalInput + "\", \"" + originalOutput + "\", \"" + kind + "\", \"" +
            provenance + "\"]"
      )
    }
```
2026-01-26 12:40:15 +01:00
Tom Hvitved
c975ae5231 Ruby: Adapt to changes in FlowSummaryImpl 2026-01-26 12:40:14 +01:00
Tom Hvitved
c4e0dda178 Rust: Adapt to changes in FlowSummaryImpl 2026-01-26 12:40:10 +01:00
Tom Hvitved
b11b091559 C#: Adapt to changes in FlowSummaryImpl 2026-01-26 12:39:38 +01:00
Tom Hvitved
4ce04e4749 Shared: Provenance-based filtering of flow summaries 2026-01-26 12:39:37 +01:00
Simon Friis Vindum
793d2c79de Merge pull request #21215 from paldepind/shared/type-mention-tree
Shared, Rust: Use `HasTypeTreeSig` for `TypeMention`
2026-01-26 12:00:02 +01:00
Michael B. Gale
f76211c64a Merge pull request #21136 from github/mbg/java/maven-plugin-repo-changenote
Java: Add change note for plugin repo support
2026-01-26 10:44:51 +00:00
Michael B. Gale
ffa700c825 Merge pull request #21214 from github/mbg/go/diagnostics-unit-tests
Go: Make diagnostics unit-testable and add test for `EmitCannotFindPackages`
2026-01-26 10:44:03 +00:00
Michael B. Gale
bd8a127565 Merge pull request #21213 from github/mbg/go/improve-package-not-found 2026-01-26 09:59:01 +00:00
Anders Fugmann
c488086135 Kotlin: Ensure the kotlin extractor is loaded as the last extension to be able to capture expansions from other extensions 2026-01-26 10:38:11 +01:00
Simon Friis Vindum
452d307fd5 Rust: Make TypeMention directly satisfy HasTypeTree 2026-01-26 09:46:33 +01:00
Simon Friis Vindum
7100ca4262 Rust: Adapt to changes in shared type inference library 2026-01-26 09:33:50 +01:00
Simon Friis Vindum
a7fecaaa1b Shared: Use HasTypeTreeSig for TypeMention 2026-01-26 09:29:51 +01:00
Michael B. Gale
45e0a929a8 Move nil check into FileDiagnosticsWriter implementation of WriteDiagnostic 2026-01-25 15:33:26 +00:00
Michael B. Gale
8e7d62600d Make EmitCannotFindPackages testable and add tests 2026-01-25 15:24:43 +00:00
Michael B. Gale
f1f4ddb76c Add dependency on testify/assert 2026-01-25 15:20:06 +00:00
Michael B. Gale
fafc2ddc0b Add DiagnosticsWriter interface to abstract over diagnostics output implementation 2026-01-25 15:20:05 +00:00
Michael B. Gale
f837d90060 Improve go/autobuilder/package-not-found diagnostic message 2026-01-25 15:18:19 +00:00
Michael B. Gale
fdc5ae375b Add IsActionsWorkflow 2026-01-25 12:39:56 +00:00
Michael B. Gale
e250c711aa Add IsDynamicActionsWorkflow 2026-01-25 12:06:30 +00:00
Mathias Vorreiter Pedersen
cabcb83b2f Merge pull request #21212 from MathiasVP/fix-as-definition
C++: Fix missing results for `Node.asDefinition`
2026-01-23 19:39:22 +00:00
Jeroen Ketema
e36080061d Merge pull request #21162 from owen-mc/cpp/mad-barriers
C++: Allow MaD barriers
2026-01-23 18:14:01 +01:00
Mathias Vorreiter Pedersen
6c2a3a68b6 C++: Add change note. 2026-01-23 16:35:02 +00:00
Mathias Vorreiter Pedersen
a556152b9d C++: Fix asDefinition to not only work for SSA definitions. 2026-01-23 16:23:21 +00:00
Mathias Vorreiter Pedersen
e58a8330cd C++: Add test for asDefinition. 2026-01-23 16:22:39 +00:00
Chris Smowton
949fc3745a Merge pull request #21211 from smowton/smowton/fix/long-actions-expressions
Actions: tolerate long `${{ ... }}` expressions
2026-01-23 07:54:59 -08:00
Chris Smowton
a326ce34a8 change note 2026-01-23 15:47:17 +00:00
Chris Smowton
9018401722 Add test 2026-01-23 15:37:40 +00:00
Chris Smowton
6c2e0f7658 Move library tests into subdirectory 2026-01-23 15:35:25 +00:00
Chris Smowton
dc26a57548 Use posessive quantifier to avoid stack overflow on large ${{}} expressions 2026-01-23 15:35:24 +00:00
Owen Mansel-Chan
82e2afc93c Merge pull request #5 from jketema/cpp/mad-barriers
C++: Add MySQL MaD taint and barrier models
2026-01-23 15:06:32 +00:00
Jeroen Ketema
7ed1c0a2ee C++: Add change note 2026-01-23 14:15:29 +01:00
Jeroen Ketema
ecd247bf16 C++: Add MaD models for MySQL escaping 2026-01-23 14:15:27 +01:00
Jeroen Ketema
ad590f30c1 Merge branch 'main' into cpp/mad-barriers 2026-01-23 14:14:22 +01:00
Jeroen Ketema
075041f1ae Merge pull request #21209 from jketema/jketema/sql
C++: Simplify `cpp/sql-injection` barrier
2026-01-23 13:33:19 +01:00
Rasmus Wriedt Larsen
7e674f3227 Merge pull request #21160 from owen-mc/scripts/accept-ci-changes-more-robust
Scripts: be more robust when parsing test logs
2026-01-23 11:49:06 +01:00
Geoffrey White
573ab025b4 Merge pull request #21191 from geoffw0/addsub
Rust: More test cases for add, sub etc
2026-01-23 10:30:21 +00:00
Simon Friis Vindum
7bdf2ab9d2 Merge pull request #21210 from paldepind/rust/self-tests
Rust: Add tests for `Self` constructors
2026-01-23 11:27:58 +01:00
Simon Friis Vindum
8f6f7d0985 Rust: Fix typo
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-23 10:07:11 +01:00
Simon Friis Vindum
3d7049265f Rust: Add tests for Self constructors 2026-01-23 09:06:49 +01:00
Jeroen Ketema
ccd07b8a63 C++: Simplify cpp/sql-injection barrier
SQL sanitizers will not likely also be sources, so using `isBarrierIn` here
does not make a lot of sense.

I ran with and without this change on MRVA and got identical results.
2026-01-23 09:03:48 +01:00
yoff
55abc52c61 python: format file 2026-01-22 20:51:46 +01:00
Simon Friis Vindum
e40f896b17 Merge pull request #21205 from paldepind/shared/ti-boound-tm
Rust: Change `getATypeParameterConstraint` to not require a `TypeMention`
2026-01-22 19:08:53 +01:00
yoff
d05901ad3f python/javascript/ruby: mark internal predicates 2026-01-22 17:30:24 +01:00
yoff
7f00a7f67e Update python/ql/lib/semmle/python/security/dataflow/UrlRedirectCustomizations.qll
Co-authored-by: Anders Schack-Mulligen <aschackmull@users.noreply.github.com>
2026-01-22 17:30:24 +01:00
yoff
b08c972cc3 ruby: Add back sanitizer as MaD model 2026-01-22 17:30:24 +01:00
yoff
15980cb1da ruby: remove sanitizer to be replaced by MaD model 2026-01-22 17:30:24 +01:00
yoff
75bd4a7a12 javascript: add MaD model
- consider if the model is in the right place
- consider if the barrier kind (sink kind) is the appropriate one
2026-01-22 17:30:24 +01:00
yoff
da2f77d615 javascript: remove sanitizer to be replaced by model 2026-01-22 17:30:24 +01:00
yoff
3dbfb9fa4b python: add machinery for MaD barriers
and reinstate previously removed barrier
now as a MaD row
2026-01-22 17:30:24 +01:00
yoff
699ed50432 python: remove barrier that can be expressed in MaD 2026-01-22 17:30:24 +01:00
Geoffrey White
f484d95081 Merge remote-tracking branch 'upstream/main' into addsub 2026-01-22 16:03:42 +00:00
Simon Friis Vindum
ffaf1c0a24 Rust: Change getATypeParameterConstraint to not require a TypeMention 2026-01-22 14:54:24 +01:00
Tom Hvitved
201512525b Merge pull request #21203 from hvitved/ql4ql/use-nightly
QL4QL: Use nightly CodeQL CLI
2026-01-22 14:30:24 +01:00
Geoffrey White
b8581e89bf Rust: More affected tests. 2026-01-22 13:22:43 +00:00
Simon Friis Vindum
7d34f6e262 Merge pull request #21204 from paldepind/rust/assoc-tp-fix
Rust: Remove mistakenly included inherited associated types
2026-01-22 13:46:09 +01:00
Geoffrey White
67b52e29e0 Rust: Update other affected tests. 2026-01-22 12:29:21 +00:00
Geoffrey White
3d6765ba1c Rust: Clean up / fix some existing models. 2026-01-22 12:29:20 +00:00
Geoffrey White
fa9677d615 Rust: Add model variants for core::ops::bit on Wrapping. 2026-01-22 12:29:14 +00:00
Geoffrey White
9d645508ea Rust: Add model variants for core::ops:arith on Wrapping. 2026-01-22 10:46:15 +00:00
Simon Friis Vindum
114db99dca Rust: Remove mistakenly included inherited associated types 2026-01-22 11:44:26 +01:00
Tom Hvitved
8ce2618b7d Merge pull request #21151 from hvitved/rust/disable-universal-conds-by-default
Type inference: Disable universal conditions by default
2026-01-22 11:19:50 +01:00
Geoffrey White
e8ef58d381 Rust: Fix an issue with identifying sources and sinks in the test. 2026-01-22 09:58:58 +00:00
Geoffrey White
f8d0a0d509 Rust: Expand the Wrapping test some more. 2026-01-22 09:52:26 +00:00
Tom Hvitved
80d543ecae QL4QL: Use nightly CodeQL CLI 2026-01-22 10:14:05 +01:00
Tom Hvitved
65ca8849f2 Type inference: Disable universal conditions 2026-01-22 09:56:52 +01:00
Mathias Vorreiter Pedersen
73eb3e262d Merge pull request #21202 from MathiasVP/add-is-live-predicate-to-ssa-definition
C++: Add `isLiveAtEndOfBlock` predicate to `Ssa::Definition`
2026-01-21 22:50:46 +00:00
Mathias Vorreiter Pedersen
60ee92d834 C++: Drive-by fix: Don't use the uncached ''getAPhiInputOrPriorDefinition' predicate. Instead, cache it and call it like we are supposed to. 2026-01-21 20:28:28 +00:00
Mathias Vorreiter Pedersen
d89967ce8e C++: Add ''isLiveAtEndOfBlock' predicate to 'Definition'. 2026-01-21 20:27:39 +00:00
Mathias Vorreiter Pedersen
dd415386ea Merge pull request #21142 from MathiasVP/ir-support-for-assertions
C++: Generate IR for assertions in release builds
2026-01-21 19:32:24 +00:00
Mathias Vorreiter Pedersen
64a7d7d836 C++: Also output variable name in test. 2026-01-21 19:14:50 +00:00
Ian Lynagh
5e536fb121 C++: Rename holdsInBase to isBase
Makes it consistent with isOverlay.
2026-01-21 18:13:58 +00:00
Ian Lynagh
7bd62087a4 C++ overlay: Simplify QL
Remove redundant variable names.
2026-01-21 18:06:43 +00:00
Owen Mansel-Chan
656ebab776 Allow MaD barriers
This commit was done by Opus 4.5 with the following prompt:

In the commit 004d40ee93 I have made it so that C# CodeQL queries which use sinks defined using data extensions (also known as "models-as-data"), which are accessed using `sinkNode(Node node, string kind)`, also use barriers defined using models-as-data, which are accessed using `barrierNode(Node node, string kind)`, with the same `kind` string. Please do the same for C++. If there are any complicated cases then list them at the end for me to do manually.
2026-01-21 14:45:05 +00:00
Mathias Vorreiter Pedersen
e1089c8d89 Merge branch 'main' into ir-support-for-assertions 2026-01-21 13:56:30 +00:00
Mathias Vorreiter Pedersen
11566ee256 C++: Accept test changes. 2026-01-21 13:50:28 +00:00
Mathias Vorreiter Pedersen
e4ec79255b C++: Fix bugs in variable resolution for assertions following review comments. 2026-01-21 13:50:27 +00:00
Mathias Vorreiter Pedersen
c30dffc7b9 C++: Add more tests. 2026-01-21 13:50:13 +00:00
Geoffrey White
1d461ff5ad Rust: Test unpacking the Wrapping number. 2026-01-21 12:49:59 +00:00
Mathias Vorreiter Pedersen
6ae1ea73f7 Merge pull request #21185 from MathiasVP/mad-cpp-guards
C++: Support models-as-data barriers and barrier guards
2026-01-21 12:13:49 +00:00
Paolo Tranquilli
0b9691aca2 Merge pull request #21047 from github/redsun82/codegen-readme
codegen: mention Rust in the README
2026-01-21 02:51:07 -08:00
Tom Hvitved
9a9e9ac23c Merge pull request #21168 from hvitved/rust/type-inference-remove-blanket-constraint-restriction
Rust: Remove restriction that blanket(-like) impls must have a constraint
2026-01-21 11:05:17 +01:00
Taus
5414bd2716 Merge pull request #21134 from yoff/python/support-ListElement-in-MaD
Python support `ListElement` in MaD
2026-01-20 23:38:02 +01:00
Mathias Vorreiter Pedersen
048afc2c88 C++: Add assertion inside catch block. This does not yet work because the 'LocalScopeVariable' does not have a result for 'getFunction'. 2026-01-20 21:31:52 +00:00
Tom Hvitved
f76d85c9c6 Address review comments 2026-01-20 21:06:20 +01:00
yoff
fa926456ef python: add changenote 2026-01-20 18:16:03 +01:00
Jon Janego
1c38fb6ad6 Merge pull request #21196 from github/changedocs-2.23.9
Changedocs 2.23.9
2026-01-20 10:43:21 -06:00
Jon Janego
b3b30a15b8 Changedocs for 2.23.9 2026-01-20 10:27:54 -06:00
Jon Janego
4ca508d420 Changedocs for 2.23.9 2026-01-20 10:23:36 -06:00
Jeroen Ketema
fbcb65a5d9 Merge pull request #21195 from jketema/jketema/embed
C++: Support C23/C++26 `#embed` preprocessor directives
2026-01-20 16:27:44 +01:00
Jeroen Ketema
701569bb20 Update cpp/ql/lib/semmle/code/cpp/Preprocessor.qll
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-20 16:05:51 +01:00
Jeroen Ketema
b35271a2ca C++: Add upgrade and downgrade script 2026-01-20 15:40:24 +01:00
Jeroen Ketema
28047fe625 C++: Update dbscheme stats file 2026-01-20 14:39:00 +01:00
Jeroen Ketema
e7044061fb C++: Support C23/C++26 #embed preprocessor directives 2026-01-20 14:38:58 +01:00
Ian Lynagh
f8f5094452 Merge pull request #20957 from igfoo/igfoo/consistent-metadata-and-overlay-support
C++ / JS / python: Be consistent in TRAP sections
2026-01-20 12:43:49 +00:00
Ian Lynagh
51b1ea84d3 ql for ql: Fix formatting 2026-01-20 12:12:20 +00:00
Ian Lynagh
49ced5fd9d C++: Add up/downgrade scripts 2026-01-20 11:57:29 +00:00
Ian Lynagh
d6d2855626 rust: Add up/downgrade scripts 2026-01-20 11:56:20 +00:00
Ian Lynagh
c37ab8f98e rust: Regenerate dbscheme 2026-01-20 11:56:16 +00:00
Ian Lynagh
1fd60c7671 Ruby: Add up/downgrade scripts 2026-01-20 11:56:16 +00:00
Ian Lynagh
82e9ea2da0 python: Add up/downgrade scripts 2026-01-20 11:56:16 +00:00
Ian Lynagh
a299174f4d javascript: Add up/downgrade scripts 2026-01-20 11:56:15 +00:00
Ian Lynagh
fdefb4d23a ql-for-ql: Regenerate dbscheme 2026-01-20 11:56:15 +00:00
Ian Lynagh
d2da49220b python: Regenerate dbscheme 2026-01-20 11:56:15 +00:00
Ian Lynagh
4b9c9e7a5a Ruby: Regenerate dbscheme 2026-01-20 11:56:15 +00:00
Ian Lynagh
df8029ff87 tree-sitter: Use more standard shared dbscheme sections
We now use the shared "Overlay support" and "Database metadata".
2026-01-20 11:56:15 +00:00
Ian Lynagh
4140121e96 javascript: Use more standard shared dbscheme sections
We now use the shared "Overlay support" and "Database metadata".
2026-01-20 11:56:14 +00:00
Ian Lynagh
7d6a1f72d5 C++: Use more standard shared dbscheme sections
We now use the shared "Overlay support" and "Database metadata".
2026-01-20 11:56:14 +00:00
Ian Lynagh
c6500e2759 tree-sitter: Add dbscheme regeneration instructions 2026-01-20 11:56:14 +00:00
Ian Lynagh
470bc7d6da ruby: Make 'dbscheme' a phony target 2026-01-20 11:56:14 +00:00
Ian Lynagh
d1175276ca python: Use more standard shared dbscheme sections
We now use the shared "Overlay support" and "Database metadata".
2026-01-20 11:56:13 +00:00
Ian Lynagh
d125e224ac python: Add dbscheme regeneration instructions 2026-01-20 11:56:13 +00:00
Philip Ginsbach-Chen
dc3b7aaab0 Merge pull request #21184 from github/ginsbach/OverlayDocumentation
add documentation for overlay annotations
2026-01-20 11:26:46 +00:00
Philip Ginsbach
8d5eb407ad incorporate additional suggestions from PR review 2026-01-20 11:17:15 +00:00
Tom Hvitved
224e5dece4 Merge pull request #21170 from paldepind/rust/type-inference-fns
Rust: Improve type inference for closures and function traits
2026-01-20 11:52:10 +01:00
Simon Friis Vindum
dd73399238 Rust: Tweak a comment
Co-authored-by: Tom Hvitved <hvitved@github.com>
2026-01-20 09:57:27 +01:00
Simon Friis Vindum
8e6f920ae2 Rust: Fix naming of mention_dyn_fn 2026-01-20 08:50:58 +01:00
Simon Friis Vindum
75cab960e2 Rust: Make AnyTraitFn abstract 2026-01-20 08:50:57 +01:00
Nick Rolfe
6fe76b3b11 Merge pull request #21190 from github/post-release-prep/codeql-cli-2.24.0
Post-release preparation for codeql-cli-2.24.0
2026-01-19 10:09:32 -08:00
Geoffrey White
ff6e598f72 Rust: Annotate failures with explanation. 2026-01-19 17:33:44 +00:00
Geoffrey White
fc5d5b4fcc Rust: Compress the existing core::ops::arith models a bit. 2026-01-19 17:33:41 +00:00
Geoffrey White
50fdc99b8c Rust: More test cases for operators, std::ops and std::num::Wrapping. 2026-01-19 16:58:03 +00:00
github-actions[bot]
48475e66af Post-release preparation for codeql-cli-2.24.0 2026-01-19 15:49:08 +00:00
Michael Nebel
93b3f65388 Merge pull request #21158 from michaelnebel/csharp/cfgforaccess
C# 14: Null conditional assignments.
2026-01-19 16:22:55 +01:00
Geoffrey White
a0311c0ea3 Rust: Test spacing. 2026-01-19 15:07:42 +00:00
Philip Ginsbach
930b17a2e2 clarify compileForOverlayEval only needed in language packs 2026-01-19 14:06:45 +00:00
Philip Ginsbach
efe413cbd0 expand overlay introduction with base/overlay context 2026-01-19 13:59:01 +00:00
Michael Nebel
7ff1c12e8f C#: Add some more tests. 2026-01-19 13:17:47 +01:00
Michael Nebel
7ae2b7698e C#: Relax the condition for when a qualified expression might be null. 2026-01-19 13:17:07 +01:00
Mathias Vorreiter Pedersen
d183dcd6fc C++: Add 'internal: do not use' comment. 2026-01-19 12:04:12 +00:00
Mathias Vorreiter Pedersen
c11b464492 C++: Autoformat. 2026-01-19 11:58:11 +00:00
Mathias Vorreiter Pedersen
b3631545d4 C++: Delete unnecessary conjuncts after review comments. 2026-01-19 11:57:45 +00:00
Mathias Vorreiter Pedersen
c47a9ddf83 Apply suggestions from code review
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-19 11:46:42 +00:00
Philip Ginsbach
4e478c3629 add overlay documentation to handbook and language spec 2026-01-19 11:45:18 +00:00
Mathias Vorreiter Pedersen
7aca94b1ca C++: Add change note. 2026-01-19 11:43:59 +00:00
Mathias Vorreiter Pedersen
c70633a0f7 C++: Fix Code Scanning alert. 2026-01-19 11:41:26 +00:00
Mathias Vorreiter Pedersen
58a3260c96 Update cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedAssertion.qll
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2026-01-19 11:33:48 +00:00
Mathias Vorreiter Pedersen
a11b271d6e C++: Finish up implementation of MaD barriers. 2026-01-19 11:30:23 +00:00
Anders Schack-Mulligen
48254800b1 WIP
C++: Add support for MaD barriers and barrier guards.
2026-01-19 11:30:21 +00:00
Mathias Vorreiter Pedersen
07ac8a5d81 C++: Parameterize the BarrierGuard modules. This is useful for barrier guards with flow states and will be necessary in the next commit for adding MaD specified barriers. 2026-01-19 11:30:19 +00:00
Mathias Vorreiter Pedersen
2b31928c7b C++: Add MaD barrier guard tests. 2026-01-19 11:30:17 +00:00
Philip Ginsbach
948623e767 add overlay annotation support to QL syntax highlighter 2026-01-19 10:36:11 +00:00
Tom Hvitved
fd309d6e49 Rust: Remove restriction that blanket(-like) impls must have a constraint 2026-01-19 11:21:58 +01:00
Michael Nebel
33fc2bab33 C#: Update test expected output. 2026-01-19 10:19:15 +01:00
Michael Nebel
beb7750c21 C#: Address review comments. 2026-01-19 10:06:14 +01:00
Michael Nebel
86198e3c43 C#: Add tests for out writeacceses. 2026-01-16 11:54:10 +01:00
Michael Nebel
bd1c6e6352 C#: Exclude the field access cases from missing argument call. 2026-01-16 11:54:09 +01:00
Michael Nebel
3d988e8e94 C#: Add field access for out assignments in the CFG. 2026-01-16 11:54:07 +01:00
Michael Nebel
812fdbe412 C#: Add change-note. 2026-01-16 11:54:06 +01:00
Michael Nebel
ab432ec2e9 C#: Update test expected output. 2026-01-16 11:54:04 +01:00
Michael Nebel
5942edf2d9 C#: Take null conditional assignments into account in MaybeNullExpr. 2026-01-16 11:54:02 +01:00
Michael Nebel
f0135e93c5 C#: Add a tests for MaybeNullExpr. 2026-01-16 11:54:01 +01:00
Michael Nebel
4ba89230db C#: Update test expected output. 2026-01-16 11:53:59 +01:00
Michael Nebel
0bf0cbae8f C#: Add some null conditional assignments CFG tests. 2026-01-16 11:53:57 +01:00
Michael Nebel
b061c4d083 C#: Update test expected output. 2026-01-16 11:53:55 +01:00
Michael Nebel
98949937dd C#: Add CFG support for null conditional assignments and include eg. field access in the CFG. 2026-01-16 11:53:54 +01:00
Simon Friis Vindum
78b88d3a44 Rust: Fix grammar in QLDoc
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-16 11:26:05 +01:00
Simon Friis Vindum
9ab29f9be0 Rust: Add a change note for type inference improvements for closures 2026-01-16 10:05:45 +01:00
Simon Friis Vindum
dabc5d54c9 Rust: Improve type inference for closures and function traits 2026-01-16 10:01:00 +01:00
Mathias Vorreiter Pedersen
03d6528687 Update cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedAssertion.qll
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2026-01-15 15:58:28 +00:00
Mathias Vorreiter Pedersen
1b117900c2 Update cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2026-01-15 14:42:11 +00:00
Mathias Vorreiter Pedersen
d6ca1ca846 Update cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll
Co-authored-by: Jeroen Ketema <93738568+jketema@users.noreply.github.com>
2026-01-15 14:41:13 +00:00
Simon Friis Vindum
196f6e1931 Rust: Add type inference tests for closures and function traits 2026-01-15 12:00:41 +01:00
Owen Mansel-Chan
657e26a375 Scripts: be more robust when parsing test logs 2026-01-13 11:36:27 +00:00
Mathias Vorreiter Pedersen
4f4baee888 C++: Fix Code Scanning alerts. 2026-01-12 21:08:02 +00:00
Mathias Vorreiter Pedersen
aa058c2cca C++: Generate IR for assertions in release builds. 2026-01-12 21:07:55 +00:00
Mathias Vorreiter Pedersen
a18f3b6859 C++: Avoid generating IR for a few cases where we will be synthesizing assertions. 2026-01-12 21:06:09 +00:00
Mathias Vorreiter Pedersen
67ab0fee83 C++: Add a few helper predicates. 2026-01-12 21:06:07 +00:00
Mathias Vorreiter Pedersen
6e3fd25b09 C++: Add tests for assertions in release builds. 2026-01-12 21:06:02 +00:00
Michael B. Gale
157487d8f2 Java: Add change note for plugin repo support 2026-01-09 12:49:12 +00:00
yoff
1ac3706e75 Python support ListElement in MaD 2026-01-09 13:08:06 +01:00
Paolo Tranquilli
6fc963177c codegen: mention Rust in the README
Updated README to reflect support for the Rust extractor and added details about Rust generated files.
2025-12-16 11:05:39 +01:00
Joe Farebrother
ac55cf9544 Update test and qldoc 2025-12-01 20:41:59 +00:00
Joe Farebrother
6fbae45d49 Update qldoc 2025-12-01 20:14:36 +00:00
Joe Farebrother
6a1e26c566 Add change note 2025-12-01 20:06:24 +00:00
Joe Farebrother
384e17a4ef Implement websockets models 2025-12-01 16:24:59 +00:00
718 changed files with 86178 additions and 33168 deletions

View File

@@ -27,6 +27,7 @@ jobs:
uses: github/codeql-action/init@main
with:
languages: javascript # does not matter
tools: nightly
- uses: ./.github/actions/os-version
id: os_version
### Build the extractor ###

View File

@@ -30,6 +30,7 @@ jobs:
uses: github/codeql-action/init@main
with:
languages: javascript # does not matter
tools: nightly
- uses: ./.github/actions/os-version
id: os_version
- uses: actions/cache@v3
@@ -75,6 +76,7 @@ jobs:
uses: github/codeql-action/init@main
with:
languages: javascript # does not matter
tools: nightly
- uses: ./.github/actions/os-version
id: os_version
- uses: actions/cache@v3

View File

@@ -24,7 +24,7 @@ bazel_dep(name = "bazel_skylib", version = "1.8.1")
bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "absl")
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
bazel_dep(name = "fmt", version = "12.1.0-codeql.1")
bazel_dep(name = "rules_kotlin", version = "2.1.3-codeql.1")
bazel_dep(name = "rules_kotlin", version = "2.2.0-codeql.1")
bazel_dep(name = "gazelle", version = "0.40.0")
bazel_dep(name = "rules_dotnet", version = "0.21.5-codeql.1")
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
@@ -221,10 +221,6 @@ use_repo(
kotlin_extractor_deps,
"codeql_kotlin_defaults",
"codeql_kotlin_embeddable",
"kotlin-compiler-1.6.0",
"kotlin-compiler-1.6.20",
"kotlin-compiler-1.7.0",
"kotlin-compiler-1.7.20",
"kotlin-compiler-1.8.0",
"kotlin-compiler-1.9.0-Beta",
"kotlin-compiler-1.9.20-Beta",
@@ -234,10 +230,7 @@ use_repo(
"kotlin-compiler-2.1.20-Beta1",
"kotlin-compiler-2.2.0-Beta1",
"kotlin-compiler-2.2.20-Beta2",
"kotlin-compiler-embeddable-1.6.0",
"kotlin-compiler-embeddable-1.6.20",
"kotlin-compiler-embeddable-1.7.0",
"kotlin-compiler-embeddable-1.7.20",
"kotlin-compiler-2.3.0",
"kotlin-compiler-embeddable-1.8.0",
"kotlin-compiler-embeddable-1.9.0-Beta",
"kotlin-compiler-embeddable-1.9.20-Beta",
@@ -247,10 +240,7 @@ use_repo(
"kotlin-compiler-embeddable-2.1.20-Beta1",
"kotlin-compiler-embeddable-2.2.0-Beta1",
"kotlin-compiler-embeddable-2.2.20-Beta2",
"kotlin-stdlib-1.6.0",
"kotlin-stdlib-1.6.20",
"kotlin-stdlib-1.7.0",
"kotlin-stdlib-1.7.20",
"kotlin-compiler-embeddable-2.3.0",
"kotlin-stdlib-1.8.0",
"kotlin-stdlib-1.9.0-Beta",
"kotlin-stdlib-1.9.20-Beta",
@@ -260,6 +250,7 @@ use_repo(
"kotlin-stdlib-2.1.20-Beta1",
"kotlin-stdlib-2.2.0-Beta1",
"kotlin-stdlib-2.2.20-Beta2",
"kotlin-stdlib-2.3.0",
)
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")

View File

@@ -1,3 +1,9 @@
## 0.4.27
### Bug Fixes
* Fixed a crash when analysing a `${{ ... }}` expression over around 300 characters in length.
## 0.4.26
### Major Analysis Improvements

View File

@@ -0,0 +1,5 @@
## 0.4.27
### Bug Fixes
* Fixed a crash when analysing a `${{ ... }}` expression over around 300 characters in length.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.26
lastReleaseVersion: 0.4.27

View File

@@ -27,8 +27,8 @@ string getADelimitedExpression(YamlString s, int offset) {
// not just the last (greedy match) or first (reluctant match).
result =
s.getValue()
.regexpFind("\\$\\{\\{(?:[^}]|}(?!}))*\\}\\}", _, offset)
.regexpCapture("(\\$\\{\\{(?:[^}]|}(?!}))*\\}\\})", 1)
.regexpFind("\\$\\{\\{(?:[^}]|}(?!}))*+\\}\\}", _, offset)
.regexpCapture("(\\$\\{\\{(?:[^}]|}(?!}))*+\\}\\})", 1)
.trim()
}

View File

@@ -1,5 +1,5 @@
name: codeql/actions-all
version: 0.4.26
version: 0.4.27
library: true
warnOnImplicitThis: true
dependencies:

View File

@@ -1,3 +1,7 @@
## 0.6.19
No user-facing changes.
## 0.6.18
No user-facing changes.

View File

@@ -0,0 +1,3 @@
## 0.6.19
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.6.18
lastReleaseVersion: 0.6.19

View File

@@ -1,5 +1,5 @@
name: codeql/actions-queries
version: 0.6.18
version: 0.6.19
library: false
warnOnImplicitThis: true
groups: [actions, queries]

View File

@@ -0,0 +1,5 @@
import codeql.actions.ast.internal.Ast
int getAnExpressionLength() { result = any(ExpressionImpl e).toString().length() }
select max(getAnExpressionLength())

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,2 @@
description: Sections for databaseMetadata and overlayChangedFiles
compatibility: full

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
class PreprocessorDirective extends @preprocdirect {
string toString() { none() }
}
class Location extends @location_default {
string toString() { none() }
}
from PreprocessorDirective ppd, int kind, int kind_new, Location l
where
preprocdirects(ppd, kind, l) and
if kind = 17 then kind_new = /* ppd_warning */ 18 else kind_new = kind
select ppd, kind_new, l

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
description: Support embed preprocessor directive
compatibility: partial
embeds.rel: delete
preprocdirects.rel: run preprocdirects.qlo

View File

@@ -1,3 +1,21 @@
## 7.1.0
### New Features
* Added a subclass `Embed` of `PreprocessorDirective` for C23 and C++26 `#embed` preprocessor directives.
* Added modules `DataFlow::ParameterizedBarrierGuard` and `DataFlow::ParameterizedInstructionBarrierGuard`. These modules provide the same features as `DataFlow::BarrierGuard` and `DataFlow::InstructionBarrierGuard`, but allow for an additional parameter to support properly using them in dataflow configurations that uses flow states.
### Minor Analysis Improvements
* The `Buffer.qll` library will no longer report incorrect buffer sizes on certain malformed databases. As a result, the queries `cpp/static-buffer-overflow`, `cpp/overflow-buffer`, `cpp/badly-bounded-write`, `cpp/overrunning-write`, `cpp/overrunning-write-with-float`, and `cpp/very-likely-overrunning-write` will report fewer false positives on such databases.
* Added `taint` summary models and `sql-injection` barrier models for the MySQL `mysql_real_escape_string` and `mysql_real_escape_string_quote` escaping functions.
* The predicate `SummarizedCallable.propagatesFlow` has been extended with the columns `Provenance p` and `boolean isExact`, and as a consequence the predicates `SummarizedCallable.hasProvenance` and `SummarizedCallable.hasExactModel` have been removed.
### Bug Fixes
* Fixed a bug in the `GuardCondition` library which sometimes prevented binary logical operators from being recognized as guard conditions. As a result, queries using `GuardCondition` may see improved results.
* Fixed a bug which caused `Node.asDefinition()` to not have a result for certain assignments.
## 7.0.0
### Breaking Changes

View File

@@ -0,0 +1,17 @@
## 7.1.0
### New Features
* Added a subclass `Embed` of `PreprocessorDirective` for C23 and C++26 `#embed` preprocessor directives.
* Added modules `DataFlow::ParameterizedBarrierGuard` and `DataFlow::ParameterizedInstructionBarrierGuard`. These modules provide the same features as `DataFlow::BarrierGuard` and `DataFlow::InstructionBarrierGuard`, but allow for an additional parameter to support properly using them in dataflow configurations that uses flow states.
### Minor Analysis Improvements
* The `Buffer.qll` library will no longer report incorrect buffer sizes on certain malformed databases. As a result, the queries `cpp/static-buffer-overflow`, `cpp/overflow-buffer`, `cpp/badly-bounded-write`, `cpp/overrunning-write`, `cpp/overrunning-write-with-float`, and `cpp/very-likely-overrunning-write` will report fewer false positives on such databases.
* Added `taint` summary models and `sql-injection` barrier models for the MySQL `mysql_real_escape_string` and `mysql_real_escape_string_quote` escaping functions.
* The predicate `SummarizedCallable.propagatesFlow` has been extended with the columns `Provenance p` and `boolean isExact`, and as a consequence the predicates `SummarizedCallable.hasProvenance` and `SummarizedCallable.hasExactModel` have been removed.
### Bug Fixes
* Fixed a bug in the `GuardCondition` library which sometimes prevented binary logical operators from being recognized as guard conditions. As a result, queries using `GuardCondition` may see improved results.
* Fixed a bug which caused `Node.asDefinition()` to not have a result for certain assignments.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 7.0.0
lastReleaseVersion: 7.1.0

View File

@@ -0,0 +1,14 @@
# partial model of the MySQL api
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["", "", False, "mysql_real_escape_string", "", "", "Argument[*2]", "Argument[*1]", "taint", "manual"]
- ["", "", False, "mysql_real_escape_string_quote", "", "", "Argument[*2]", "Argument[*1]", "taint", "manual"]
- addsTo:
pack: codeql/cpp-all
extensible: barrierModel
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
- ["", "", False, "mysql_real_escape_string", "", "", "Argument[*1]", "sql-injection", "manual"]
- ["", "", False, "mysql_real_escape_string_quote", "", "", "Argument[*1]", "sql-injection", "manual"]

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 7.0.0
version: 7.1.0
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -192,6 +192,15 @@ class Element extends ElementBase {
*/
predicate isAffectedByMacro() { affectedByMacro(this) }
/**
* INTERNAL: Do not use.
*
* Holds if this element is affected by the expansion of `mi`.
*/
predicate isAffectedByMacro(MacroInvocation mi) {
affectedbymacroexpansion(underlyingElement(this), unresolveElement(mi))
}
private Element getEnclosingElementPref() {
enclosingfunction(underlyingElement(this), unresolveElement(result)) or
result.(Function) = stmtEnclosingElement(this) or

View File

@@ -239,6 +239,9 @@ class MacroInvocation extends MacroAccess {
macro_argument_unexpanded(underlyingElement(this), i, result)
}
/** Gets the number of arguments for this macro invocation. */
int getNumberOfArguments() { result = count(int i | exists(this.getUnexpandedArgument(i)) | i) }
/**
* Gets the `i`th _expanded_ argument of this macro invocation, where the
* first argument has `i = 0`. The result has been expanded for macros _and_

View File

@@ -328,3 +328,27 @@ class PreprocessorPragma extends PreprocessorDirective, @ppd_pragma {
class PreprocessorLine extends PreprocessorDirective, @ppd_line {
override string toString() { result = "#line " + this.getHead() }
}
/**
* A C23 or C++26 `#embed` preprocessor directive. For example, the following code
* contains one `Embed` directive:
* ```cpp
* char arr[] = {
* #embed "bin"
* };
* ```
*/
class Embed extends PreprocessorDirective, @ppd_embed {
override string toString() { result = "#embed " + this.getIncludeText() }
/**
* Gets the token which occurs after `#embed`, for example `"filename"`
* or `<filename>`.
*/
string getIncludeText() { result = this.getHead() }
/**
* Gets the file directly embedded by this `#embed`.
*/
File getEmbeddedFile() { embeds(underlyingElement(this), unresolveElement(result)) }
}

View File

@@ -62,11 +62,13 @@ private Class getRootType(FieldAccess fa) {
* unspecified type of `v` is a `ReferenceType`.
*/
private int getVariableSize(Variable v) {
exists(Type t |
t = v.getUnspecifiedType() and
not t instanceof ReferenceType and
result = t.getSize()
)
result =
unique(Type t |
t = v.getUnspecifiedType() and
not t instanceof ReferenceType
|
t.getSize()
)
}
/**
@@ -79,30 +81,32 @@ private int getSize(VariableAccess va) {
not v instanceof Field and
result = getVariableSize(v)
or
exists(Class c, int trueSize |
// Otherwise, we find the "outermost" object and compute the size
// as the difference between the size of the type of the "outermost
// object" and the offset of the field relative to that type.
// For example, consider the following structs:
// ```
// struct S {
// uint32_t x;
// uint32_t y;
// };
// struct S2 {
// S s;
// uint32_t z;
// };
// ```
// Given an object `S2 s2` the size of the buffer `&s2.s.y`
// is the size of the base object type (i.e., `S2`) minutes the offset
// of `y` relative to the type `S2` (i.e., `4`). So the size of the
// buffer is `12 - 4 = 8`.
c = getRootType(va) and
// we calculate the size based on the last field, to avoid including any padding after it
trueSize = max(Field f | | f.getOffsetInClass(c) + getVariableSize(f)) and
result = trueSize - v.(Field).getOffsetInClass(c)
)
result =
unique(Class c, int trueSize |
// Otherwise, we find the "outermost" object and compute the size
// as the difference between the size of the type of the "outermost
// object" and the offset of the field relative to that type.
// For example, consider the following structs:
// ```
// struct S {
// uint32_t x;
// uint32_t y;
// };
// struct S2 {
// S s;
// uint32_t z;
// };
// ```
// Given an object `S2 s2` the size of the buffer `&s2.s.y`
// is the size of the base object type (i.e., `S2`) minus the offset
// of `y` relative to the type `S2` (i.e., `4`). So the size of the
// buffer is `12 - 4 = 8`.
c = getRootType(va) and
// we calculate the size based on the last field, to avoid including any padding after it
trueSize = max(Field f | | f.getOffsetInClass(c) + getVariableSize(f))
|
trueSize - v.(Field).getOffsetInClass(c)
)
)
}
@@ -116,12 +120,8 @@ private int isSource(Expr bufferExpr, Element why) {
exists(Variable bufferVar | bufferVar = bufferExpr.(VariableAccess).getTarget() |
// buffer is a fixed size array
exists(bufferVar.getUnspecifiedType().(ArrayType).getSize()) and
result =
unique(int size | // more generous than .getSize() itself, when the array is a class field or similar.
size = getSize(bufferExpr)
|
size
) and
// more generous than .getSize() itself, when the array is a class field or similar.
result = getSize(bufferExpr) and
why = bufferVar and
not memberMayBeVarSize(_, bufferVar) and
not exists(BuiltInOperationBuiltInOffsetOf offsetof | offsetof.getAChild*() = bufferExpr) and

View File

@@ -8,7 +8,8 @@ import semmle.code.cpp.ir.IR
private import codeql.util.Void
private import codeql.controlflow.Guards as SharedGuards
private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr as TE
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedFunction as TF
private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
private class BasicBlock = IRCfg::BasicBlock;
@@ -683,24 +684,26 @@ final class GuardCondition = GuardConditionImpl;
*/
private class GuardConditionFromBinaryLogicalOperator extends GuardConditionImpl instanceof Cpp::BinaryLogicalOperation
{
GuardConditionImpl l;
GuardConditionImpl r;
GuardConditionFromBinaryLogicalOperator() {
super.getLeftOperand() = l and
super.getRightOperand() = r
}
override predicate valueControls(Cpp::BasicBlock controlled, GuardValue v) {
exists(Cpp::BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs |
this = binop and
lhs = binop.getLeftOperand() and
rhs = binop.getRightOperand() and
lhs.valueControls(controlled, v) and
rhs.valueControls(controlled, v)
)
// `l || r` does not control `r` even though `l` does.
not r.(Cpp::Expr).getBasicBlock() = controlled and
l.valueControls(controlled, v)
or
r.valueControls(controlled, v)
}
override predicate valueControlsEdge(Cpp::BasicBlock pred, Cpp::BasicBlock succ, GuardValue v) {
exists(Cpp::BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs |
this = binop and
lhs = binop.getLeftOperand() and
rhs = binop.getRightOperand() and
lhs.valueControlsEdge(pred, succ, v) and
rhs.valueControlsEdge(pred, succ, v)
)
l.valueControlsEdge(pred, succ, v)
or
r.valueControlsEdge(pred, succ, v)
}
pragma[nomagic]
@@ -1026,7 +1029,7 @@ private class GuardConditionFromIR extends GuardConditionImpl {
private predicate excludeAsControlledInstruction(Instruction instr) {
// Exclude the temporaries generated by a ternary expression.
exists(TranslatedConditionalExpr tce |
exists(TE::TranslatedConditionalExpr tce |
instr = tce.getInstruction(ConditionValueFalseStoreTag())
or
instr = tce.getInstruction(ConditionValueTrueStoreTag())
@@ -1038,6 +1041,14 @@ private predicate excludeAsControlledInstruction(Instruction instr) {
or
// Exclude unreached instructions, as their AST is the whole function and not a block.
instr instanceof UnreachedInstruction
or
// Exclude instructions generated by a translated function as they map to the function itself
// and the function is considered the last basic block of a function body.
any(TF::TranslatedFunction tf).getInstruction(_) = instr
or
// `ChiInstruction`s generated by instructions in the above case don't come from `getInstruction` (since they are generated by AliasedSSA)
// so we need to special case them.
excludeAsControlledInstruction(instr.(ChiInstruction).getPartial())
}
/**

View File

@@ -95,6 +95,7 @@
import cpp
private import new.DataFlow
private import semmle.code.cpp.controlflow.IRGuards
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as Private
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import internal.FlowSummaryImpl
@@ -367,6 +368,8 @@ private predicate elementSpec(
) {
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
barrierModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
barrierGuardModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _) or
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _)
}
@@ -1028,6 +1031,84 @@ private module Cached {
isSinkNode(n, kind, model) and n.asNode() = node
)
}
private newtype TKindModelPair =
TMkPair(string kind, string model) { isBarrierGuardNode(_, _, kind, model) }
private GuardValue convertAcceptingValue(Public::AcceptingValue av) {
av.isTrue() and result.asBooleanValue() = true
or
av.isFalse() and result.asBooleanValue() = false
or
// NOTE: The below cases don't contribute anything currently since the
// callers immediately use `.asBooleanValue()` to convert the `GuardValue`
// to a boolean. Once we're willing to accept the breaking change of
// converting the barrier guard API to use `GuardValue`s instead `Boolean`s
// we can remove this restriction.
av.isNoException() and result.getDualValue().isThrowsException()
or
av.isZero() and result.asIntValue() = 0
or
av.isNotZero() and result.getDualValue().asIntValue() = 0
or
av.isNull() and result.isNullValue()
or
av.isNotNull() and result.isNonNullValue()
}
private predicate barrierGuardChecks(IRGuardCondition g, Expr e, boolean gv, TKindModelPair kmp) {
exists(
SourceSinkInterpretationInput::InterpretNode n, Public::AcceptingValue acceptingvalue,
string kind, string model
|
isBarrierGuardNode(n, acceptingvalue, kind, model) and
n.asNode().asExpr() = e and
kmp = TMkPair(kind, model) and
gv = convertAcceptingValue(acceptingvalue).asBooleanValue() and
n.asNode().(Private::ArgumentNode).getCall().asCallInstruction() = g
)
}
private newtype TKindModelPairIntPair =
MkKindModelPairIntPair(TKindModelPair pair, int indirectionIndex) {
indirectionIndex > 0 and
Private::nodeHasInstruction(_, _, indirectionIndex) and
exists(pair)
}
private predicate indirectBarrierGuardChecks(
IRGuardCondition g, Expr e, boolean gv, TKindModelPairIntPair kmp
) {
exists(
SourceSinkInterpretationInput::InterpretNode interpretNode,
Public::AcceptingValue acceptingvalue, string kind, string model, int indirectionIndex,
Private::ArgumentNode arg
|
isBarrierGuardNode(interpretNode, acceptingvalue, kind, model) and
arg = interpretNode.asNode() and
arg.asIndirectExpr(indirectionIndex) = e and
kmp = MkKindModelPairIntPair(TMkPair(kind, model), indirectionIndex) and
gv = convertAcceptingValue(acceptingvalue).asBooleanValue() and
arg.getCall().asCallInstruction() = g
)
}
/**
* Holds if `node` is specified as a barrier with the given kind in a MaD flow
* model.
*/
cached
predicate barrierNode(DataFlow::Node node, string kind, string model) {
exists(SourceSinkInterpretationInput::InterpretNode n |
isBarrierNode(n, kind, model) and n.asNode() = node
)
or
DataFlow::ParameterizedBarrierGuard<TKindModelPair, barrierGuardChecks/4>::getABarrierNode(TMkPair(kind,
model)) = node
or
DataFlow::ParameterizedBarrierGuard<TKindModelPairIntPair, indirectBarrierGuardChecks/4>::getAnIndirectBarrierNode(MkKindModelPairIntPair(TMkPair(kind,
model), _)) = node
}
}
import Cached
@@ -1044,6 +1125,12 @@ predicate sourceNode(DataFlow::Node node, string kind) { sourceNode(node, kind,
*/
predicate sinkNode(DataFlow::Node node, string kind) { sinkNode(node, kind, _) }
/**
* Holds if `node` is specified as a barrier with the given kind in a MaD flow
* model.
*/
predicate barrierNode(DataFlow::Node node, string kind) { barrierNode(node, kind, _) }
private predicate interpretSummary(
Function f, string input, string output, string kind, string provenance, string model
) {
@@ -1058,40 +1145,22 @@ private predicate interpretSummary(
// adapter class for converting Mad summaries to `SummarizedCallable`s
private class SummarizedCallableAdapter extends SummarizedCallable {
SummarizedCallableAdapter() { interpretSummary(this, _, _, _, _, _) }
string input_;
string output_;
string kind;
Provenance p_;
string model_;
private predicate relevantSummaryElementManual(
string input, string output, string kind, string model
) {
exists(Provenance provenance |
interpretSummary(this, input, output, kind, provenance, model) and
provenance.isManual()
)
}
private predicate relevantSummaryElementGenerated(
string input, string output, string kind, string model
) {
exists(Provenance provenance |
interpretSummary(this, input, output, kind, provenance, model) and
provenance.isGenerated()
)
}
SummarizedCallableAdapter() { interpretSummary(this, input_, output_, kind, p_, model_) }
override predicate propagatesFlow(
string input, string output, boolean preservesValue, string model
string input, string output, boolean preservesValue, Provenance p, boolean isExact, string model
) {
exists(string kind |
this.relevantSummaryElementManual(input, output, kind, model)
or
not this.relevantSummaryElementManual(_, _, _, _) and
this.relevantSummaryElementGenerated(input, output, kind, model)
|
if kind = "value" then preservesValue = true else preservesValue = false
)
}
override predicate hasProvenance(Provenance provenance) {
interpretSummary(this, _, _, _, provenance, _)
input = input_ and
output = output_ and
(if kind = "value" then preservesValue = true else preservesValue = false) and
p = p_ and
isExact = true and
model = model_
}
}

View File

@@ -20,6 +20,8 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
class SinkBase = Void;
predicate callableFromSource(SummarizedCallableBase c) { exists(c.getBlock()) }
ArgumentPosition callbackSelfParameterPosition() { result = TDirectPosition(-1) }
ReturnKind getStandardReturnValueKind() { result = getReturnValueKind("") }
@@ -149,16 +151,27 @@ module SourceSinkInterpretationInput implements
}
predicate barrierElement(
Element n, string output, string kind, Public::Provenance provenance, string model
Element e, string output, string kind, Public::Provenance provenance, string model
) {
none()
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
barrierModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance, model) and
e = interpretElement(namespace, type, subtypes, name, signature, ext)
)
}
predicate barrierGuardElement(
Element n, string input, Public::AcceptingValue acceptingvalue, string kind,
Element e, string input, Public::AcceptingValue acceptingvalue, string kind,
Public::Provenance provenance, string model
) {
none()
exists(
string package, string type, boolean subtypes, string name, string signature, string ext
|
barrierGuardModel(package, type, subtypes, name, signature, ext, input, acceptingvalue, kind,
provenance, model) and
e = interpretElement(package, type, subtypes, name, signature, ext)
)
}
private newtype TInterpretNode =

View File

@@ -23,7 +23,7 @@ class Expr extends StmtParent, @expr {
predicate hasChild(Expr e, int n) { e = this.getChild(n) }
/** Gets the enclosing function of this expression, if any. */
Function getEnclosingFunction() { result = exprEnclosingElement(this) }
override Function getEnclosingFunction() { result = exprEnclosingElement(this) }
/** Gets the nearest enclosing set of curly braces around this expression in the source, if any. */
BlockStmt getEnclosingBlock() { result = this.getEnclosingStmt().getEnclosingBlock() }

View File

@@ -45,13 +45,13 @@ private string getSingleLocationFilePath(@element e) {
overlay[local]
private string getMultiLocationFilePath(@element e) {
exists(@location_default loc |
exists(@var_decl vd | var_decls(vd, e, _, _, loc))
var_decls(_, e, _, _, loc)
or
exists(@fun_decl fd | fun_decls(fd, e, _, _, loc))
fun_decls(_, e, _, _, loc)
or
exists(@type_decl td | type_decls(td, e, loc))
type_decls(_, e, loc)
or
exists(@namespace_decl nd | namespace_decls(nd, e, loc, _))
namespace_decls(_, e, loc, _)
|
result = getLocationFilePath(loc)
)
@@ -62,7 +62,7 @@ private string getMultiLocationFilePath(@element e) {
* overlay variant.
*/
overlay[local]
private predicate holdsInBase() { not isOverlay() }
private predicate isBase() { not isOverlay() }
/**
* Discards an element from the base variant if:
@@ -71,7 +71,7 @@ private predicate holdsInBase() { not isOverlay() }
*/
overlay[discard_entity]
private predicate discardElement(@element e) {
holdsInBase() and
isBase() and
(
overlayChangedFiles(getSingleLocationFilePath(e))
or

View File

@@ -1144,7 +1144,7 @@ private newtype TDataFlowCall =
}
private predicate summarizedCallableIsManual(SummarizedCallable sc) {
sc.asSummarizedCallable().applyManualModel()
sc.asSummarizedCallable().hasManualModel()
}
/**

View File

@@ -312,6 +312,13 @@ class Node extends TIRDataFlowNode {
*/
Expr asDefinition() { result = this.asDefinition(_) }
private predicate isCertainStore() {
exists(SsaImpl::Definition def |
SsaImpl::defToNode(this, def, _) and
def.isCertain()
)
}
/**
* Gets the definition associated with this node, if any.
*
@@ -361,11 +368,10 @@ class Node extends TIRDataFlowNode {
* pointed to by `p`.
*/
Expr asDefinition(boolean uncertain) {
exists(StoreInstruction store, SsaImpl::Definition def |
exists(StoreInstruction store |
store = this.asInstruction() and
result = asDefinitionImpl(store) and
SsaImpl::defToNode(this, def, _) and
if def.isCertain() then uncertain = false else uncertain = true
if this.isCertainStore() then uncertain = false else uncertain = true
)
}
@@ -2417,6 +2423,19 @@ class ContentSet instanceof Content {
}
}
private signature class ParamSig;
private module WithParam<ParamSig P> {
/**
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
*
* The expression `e` is expected to be a syntactic part of the guard `g`.
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
* the argument `x`.
*/
signature predicate guardChecksSig(IRGuardCondition g, Expr e, boolean branch, P param);
}
/**
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
*
@@ -2438,7 +2457,7 @@ private predicate controls(IRGuardCondition g, Node n, boolean edge) {
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module BarrierGuard<guardChecksSig/3 guardChecks> {
module ParameterizedBarrierGuard<ParamSig P, WithParam<P>::guardChecksSig/4 guardChecks> {
bindingset[value, n]
pragma[inline_late]
private predicate convertedExprHasValueNumber(ValueNumber value, Node n) {
@@ -2448,12 +2467,13 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
)
}
private predicate guardChecksNode(IRGuardCondition g, Node n, boolean branch) {
guardChecks(g, n.asOperand().getDef().getConvertedResultExpression(), branch)
private predicate guardChecksNode(IRGuardCondition g, Node n, boolean branch, P p) {
guardChecks(g, n.asOperand().getDef().getConvertedResultExpression(), branch, p)
}
/**
* Gets an expression node that is safely guarded by the given guard check.
* Gets an expression node that is safely guarded by the given guard check
* when the parameter is `p`.
*
* For example, given the following code:
* ```cpp
@@ -2484,19 +2504,27 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
*
* NOTE: If an indirect expression is tracked, use `getAnIndirectBarrierNode` instead.
*/
Node getABarrierNode() {
Node getABarrierNode(P p) {
exists(IRGuardCondition g, ValueNumber value, boolean edge |
convertedExprHasValueNumber(value, result) and
guardChecks(g,
pragma[only_bind_into](value.getAnInstruction().getConvertedResultExpression()), edge) and
pragma[only_bind_into](value.getAnInstruction().getConvertedResultExpression()), edge, p) and
controls(g, result, edge)
)
or
result = SsaImpl::BarrierGuard<guardChecksNode/3>::getABarrierNode()
result = SsaImpl::BarrierGuard<P, guardChecksNode/4>::getABarrierNode(p)
}
/**
* Gets an indirect expression node that is safely guarded by the given guard check.
* Gets an expression node that is safely guarded by the given guard check.
*
* See `getABarrierNode/1` for examples.
*/
Node getABarrierNode() { result = getABarrierNode(_) }
/**
* Gets an indirect expression node that is safely guarded by the given
* guard check with parameter `p`.
*
* For example, given the following code:
* ```cpp
@@ -2528,6 +2556,13 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
*
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
*/
Node getAnIndirectBarrierNode(P p) { result = getAnIndirectBarrierNode(_, p) }
/**
* Gets an indirect expression node that is safely guarded by the given guard check.
*
* See `getAnIndirectBarrierNode/1` for examples.
*/
Node getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
bindingset[value, n]
@@ -2542,10 +2577,10 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
}
private predicate guardChecksIndirectNode(
IRGuardCondition g, Node n, boolean branch, int indirectionIndex
IRGuardCondition g, Node n, boolean branch, int indirectionIndex, P p
) {
guardChecks(g, n.asIndirectOperand(indirectionIndex).getDef().getConvertedResultExpression(),
branch)
branch, p)
}
/**
@@ -2582,19 +2617,44 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
*
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
*/
Node getAnIndirectBarrierNode(int indirectionIndex) {
Node getAnIndirectBarrierNode(int indirectionIndex, P p) {
exists(IRGuardCondition g, ValueNumber value, boolean edge |
indirectConvertedExprHasValueNumber(indirectionIndex, value, result) and
guardChecks(g,
pragma[only_bind_into](value.getAnInstruction().getConvertedResultExpression()), edge) and
pragma[only_bind_into](value.getAnInstruction().getConvertedResultExpression()), edge, p) and
controls(g, result, edge)
)
or
result =
SsaImpl::BarrierGuardWithIntParam<guardChecksIndirectNode/4>::getABarrierNode(indirectionIndex)
SsaImpl::BarrierGuardWithIntParam<P, guardChecksIndirectNode/5>::getABarrierNode(indirectionIndex,
p)
}
}
/**
* Provides a set of barrier nodes for a guard that validates an expression.
*
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module BarrierGuard<guardChecksSig/3 guardChecks> {
private predicate guardChecks(IRGuardCondition g, Expr e, boolean branch, Unit unit) {
guardChecks(g, e, branch) and
exists(unit)
}
import ParameterizedBarrierGuard<Unit, guardChecks/4>
}
private module InstrWithParam<ParamSig P> {
/**
* Holds if the guard `g` validates the instruction `instr` upon evaluating to `branch`.
*/
signature predicate instructionGuardChecksSig(
IRGuardCondition g, Instruction instr, boolean branch, P p
);
}
/**
* Holds if the guard `g` validates the instruction `instr` upon evaluating to `branch`.
*/
@@ -2606,7 +2666,9 @@ signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction in
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
module ParameterizedInstructionBarrierGuard<
ParamSig P, InstrWithParam<P>::instructionGuardChecksSig/4 instructionGuardChecks>
{
bindingset[value, n]
pragma[inline_late]
private predicate operandHasValueNumber(ValueNumber value, Node n) {
@@ -2616,21 +2678,27 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
)
}
private predicate guardChecksNode(IRGuardCondition g, Node n, boolean branch) {
instructionGuardChecks(g, n.asOperand().getDef(), branch)
private predicate guardChecksNode(IRGuardCondition g, Node n, boolean branch, P p) {
instructionGuardChecks(g, n.asOperand().getDef(), branch, p)
}
/** Gets a node that is safely guarded by the given guard check. */
Node getABarrierNode() {
/**
* Gets a node that is safely guarded by the given guard check with
* parameter `p`.
*/
Node getABarrierNode(P p) {
exists(IRGuardCondition g, ValueNumber value, boolean edge |
instructionGuardChecks(g, pragma[only_bind_into](value.getAnInstruction()), edge) and
instructionGuardChecks(g, pragma[only_bind_into](value.getAnInstruction()), edge, p) and
operandHasValueNumber(value, result) and
controls(g, result, edge)
)
or
result = SsaImpl::BarrierGuard<guardChecksNode/3>::getABarrierNode()
result = SsaImpl::BarrierGuard<P, guardChecksNode/4>::getABarrierNode(p)
}
/** Gets a node that is safely guarded by the given guard check. */
Node getABarrierNode() { result = getABarrierNode(_) }
bindingset[value, n]
pragma[inline_late]
private predicate indirectOperandHasValueNumber(ValueNumber value, int indirectionIndex, Node n) {
@@ -2641,25 +2709,52 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
}
private predicate guardChecksIndirectNode(
IRGuardCondition g, Node n, boolean branch, int indirectionIndex
IRGuardCondition g, Node n, boolean branch, int indirectionIndex, P p
) {
instructionGuardChecks(g, n.asIndirectOperand(indirectionIndex).getDef(), branch)
instructionGuardChecks(g, n.asIndirectOperand(indirectionIndex).getDef(), branch, p)
}
/**
* Gets an indirect node with indirection index `indirectionIndex` that is
* safely guarded by the given guard check.
* safely guarded by the given guard check with parameter `p`.
*/
Node getAnIndirectBarrierNode(int indirectionIndex) {
Node getAnIndirectBarrierNode(int indirectionIndex, P p) {
exists(IRGuardCondition g, ValueNumber value, boolean edge |
instructionGuardChecks(g, pragma[only_bind_into](value.getAnInstruction()), edge) and
instructionGuardChecks(g, pragma[only_bind_into](value.getAnInstruction()), edge, p) and
indirectOperandHasValueNumber(value, indirectionIndex, result) and
controls(g, result, edge)
)
or
result =
SsaImpl::BarrierGuardWithIntParam<guardChecksIndirectNode/4>::getABarrierNode(indirectionIndex)
SsaImpl::BarrierGuardWithIntParam<P, guardChecksIndirectNode/5>::getABarrierNode(indirectionIndex,
p)
}
/**
* Gets an indirect node that is safely guarded by the given guard check
* with parameter `p`.
*/
Node getAnIndirectBarrierNode(P p) { result = getAnIndirectBarrierNode(_, p) }
/** Gets an indirect node that is safely guarded by the given guard check. */
Node getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
}
/**
* Provides a set of barrier nodes for a guard that validates an instruction.
*
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
private predicate instructionGuardChecks(
IRGuardCondition g, Instruction i, boolean branch, Unit unit
) {
instructionGuardChecks(g, i, branch) and
exists(unit)
}
import ParameterizedInstructionBarrierGuard<Unit, instructionGuardChecks/4>
}
/**

View File

@@ -15,17 +15,79 @@ private import DataFlowPrivate
import SsaImplCommon
private module SourceVariables {
/**
* Holds if `store` is the `StoreInstruction` generated by a postfix
* increment or decrement operation `e`, and `postCrement` is the operand
* that represents the use of the evaluated value of `e`.
*/
private predicate isUseAfterPostfixCrement0(StoreInstruction store, Operand postCrement) {
exists(
BinaryInstruction binary, IRBlock b, int iPre, int iPost, int iStore, Operand preCrement,
Instruction left
|
binary instanceof AddInstruction
or
binary instanceof PointerAddInstruction
or
binary instanceof SubInstruction
or
binary instanceof PointerSubInstruction
|
store.getSourceValue() = binary and
left = binary.getLeft() and
strictcount(left.getAUse()) = 2 and
left.getAUse() = preCrement and
left.getAUse() = postCrement and
b.getInstruction(iPre) = preCrement.getUse() and
b.getInstruction(iPost) = postCrement.getUse() and
b.getInstruction(iStore) = store and
iPre < iStore and
iStore < iPost
)
}
/**
* Holds if `store` is the `StoreInstruction` generated by an postfix
* increment or decrement operation `e`, and `postCrement` is the fully
* converted operand that represents the use of the evaluated value of `e`.
*/
private predicate isUseAfterPostfixCrement(StoreInstruction store, Operand postCrement) {
isUseAfterPostfixCrement0(store, postCrement) and
conversionFlow(postCrement, _, false, _)
or
exists(Instruction instr, Operand postCrement0 |
isUseAfterPostfixCrement(store, postCrement0) and
conversionFlow(postCrement0, instr, false, _) and
instr = postCrement.getDef()
)
}
private predicate hasSavedPostfixCrementSourceVariable(
BaseSourceVariable base, StoreInstruction store, int ind
) {
exists(BaseSourceVariableInstruction inst, int ind0 |
isUseAfterPostfixCrement(store, _) and
inst.getBaseSourceVariable() = base and
isDef(_, _, store.getDestinationAddressOperand(), inst, ind0, 0) and
ind = [ind0 .. countIndirectionsForCppType(base.getLanguageType()) + 1]
)
}
cached
private newtype TSourceVariable =
TMkSourceVariable(BaseSourceVariable base, int ind) {
TNormalSourceVariable(BaseSourceVariable base, int ind) {
ind = [0 .. countIndirectionsForCppType(base.getLanguageType()) + 1]
} or
TSavedPostfixCrementSourceVariable(StoreInstruction store, int ind) {
hasSavedPostfixCrementSourceVariable(_, store, ind)
}
class SourceVariable extends TSourceVariable {
abstract private class AbstractSourceVariable extends TSourceVariable {
BaseSourceVariable base;
int ind;
SourceVariable() { this = TMkSourceVariable(base, ind) }
bindingset[ind]
AbstractSourceVariable() { any() }
/** Gets the IR variable associated with this `SourceVariable`, if any. */
IRVariable getIRVariable() { result = base.(BaseIRVariable).getIRVariable() }
@@ -37,7 +99,7 @@ private module SourceVariables {
BaseSourceVariable getBaseVariable() { result = base }
/** Gets a textual representation of this element. */
string toString() { result = repeatStars(this.getIndirection()) + base.toString() }
abstract string toString();
/**
* Gets the number of loads performed on the base source variable
@@ -62,6 +124,53 @@ private module SourceVariables {
/** Gets the location of this variable. */
Location getLocation() { result = this.getBaseVariable().getLocation() }
}
final class SourceVariable = AbstractSourceVariable;
/**
* A regular source variable. Most source variables are instances of this
* class.
*/
class NormalSourceVariable extends AbstractSourceVariable, TNormalSourceVariable {
NormalSourceVariable() { this = TNormalSourceVariable(base, ind) }
final override string toString() {
result = repeatStars(this.getIndirection()) + base.toString()
}
}
/**
* Before a value is postfix incremented (or decremented) we "save" its
* current value so that the pre-incremented value can be returned to the
* enclosing expression. We use the source variables represented by this
* class to represent the "saved value".
*/
class SavedPostfixCrementSourceVariable extends AbstractSourceVariable,
TSavedPostfixCrementSourceVariable
{
StoreInstruction store;
SavedPostfixCrementSourceVariable() {
this = TSavedPostfixCrementSourceVariable(store, ind) and
hasSavedPostfixCrementSourceVariable(base, store, ind)
}
final override string toString() {
result = repeatStars(this.getIndirection()) + base.toString() + " [before crement]"
}
/**
* Gets the `StoreInstruction` that writes the incremented (or decremented)
* value.
*/
StoreInstruction getStoreInstruction() { result = store }
/**
* Gets the fully converted `Operand` that represents the use of the
* value before the increment.
*/
Operand getOperand() { isUseAfterPostfixCrement(store, result) }
}
}
import SourceVariables
@@ -109,17 +218,43 @@ private newtype TDefImpl =
TDirectDefImpl(Operand address, int indirectionIndex) {
isDef(_, _, address, _, _, indirectionIndex)
} or
TSavedPostfixCrementDefImpl(SavedPostfixCrementSourceVariable sv, int indirectionIndex) {
isDef(_, _, sv.getStoreInstruction().getDestinationAddressOperand(), _, sv.getIndirection(),
indirectionIndex)
} or
TGlobalDefImpl(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
// Represents the initial "definition" of a global variable when entering
// a function body.
isGlobalDefImpl(v, f, _, indirectionIndex)
}
pragma[nomagic]
private predicate hasOperandAndIndirection(
SavedPostfixCrementSourceVariable sv, Operand operand, int indirection
) {
sv.getOperand() = operand and
sv.getIndirection() = indirection
}
private predicate hasBeforePostCrementUseImpl(
SavedPostfixCrementSourceVariable sv, Operand operand, int indirectionIndex
) {
not isDef(true, _, operand, _, _, _) and
exists(int indirection |
hasOperandAndIndirection(sv, operand, indirection) and
isUse(_, operand, _, indirection, indirectionIndex)
)
}
cached
private newtype TUseImpl =
TDirectUseImpl(Operand operand, int indirectionIndex) {
isUse(_, operand, _, _, indirectionIndex) and
not isDef(true, _, operand, _, _, _)
not isDef(true, _, operand, _, _, _) and
not hasBeforePostCrementUseImpl(_, operand, indirectionIndex)
} or
TSavedPostfixCrementUseImpl(SavedPostfixCrementSourceVariable sv, int indirectionIndex) {
hasBeforePostCrementUseImpl(sv, _, indirectionIndex)
} or
TGlobalUse(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
// Represents a final "use" of a global variable to ensure that
@@ -223,19 +358,8 @@ abstract class DefImpl extends TDefImpl {
*/
abstract int getIndirection();
/**
* Gets the base source variable (i.e., the variable without
* any indirection) of this definition or use.
*/
abstract BaseSourceVariable getBaseSourceVariable();
/** Gets the variable that is defined or used. */
SourceVariable getSourceVariable() {
exists(BaseSourceVariable v, int indirection |
sourceVariableHasBaseAndIndex(result, v, indirection) and
defHasSourceVariable(this, v, indirection)
)
}
abstract SourceVariable getSourceVariable();
/**
* Holds if this definition is guaranteed to totally overwrite the
@@ -243,8 +367,8 @@ abstract class DefImpl extends TDefImpl {
*/
abstract predicate isCertain();
/** Gets the value written to the destination variable by this definition. */
abstract Node0Impl getValue();
/** Gets the value written to the destination variable by this definition, if any. */
Node0Impl getValue() { none() }
/** Gets the operand that represents the address of this definition, if any. */
Operand getAddressOperand() { none() }
@@ -293,19 +417,8 @@ abstract class UseImpl extends TUseImpl {
/** Gets the indirection index of this use. */
final int getIndirectionIndex() { result = indirectionIndex }
/**
* Gets the base source variable (i.e., the variable without
* any indirection) of this definition or use.
*/
abstract BaseSourceVariable getBaseSourceVariable();
/** Gets the variable that is defined or used. */
SourceVariable getSourceVariable() {
exists(BaseSourceVariable v, int indirection |
sourceVariableHasBaseAndIndex(result, v, indirection) and
useHasSourceVariable(this, v, indirection)
)
}
abstract SourceVariable getSourceVariable();
/**
* Holds if this use is guaranteed to read the
@@ -314,18 +427,6 @@ abstract class UseImpl extends TUseImpl {
abstract predicate isCertain();
}
pragma[noinline]
private predicate defHasSourceVariable(DefImpl def, BaseSourceVariable bv, int ind) {
bv = def.getBaseSourceVariable() and
ind = def.getIndirection()
}
pragma[noinline]
private predicate useHasSourceVariable(UseImpl use, BaseSourceVariable bv, int ind) {
bv = use.getBaseSourceVariable() and
ind = use.getIndirection()
}
pragma[noinline]
private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVariable bv, int ind) {
v.getBaseVariable() = bv and
@@ -358,16 +459,12 @@ abstract private class DefAddressImpl extends DefImpl, TDefAddressImpl {
final override predicate isCertain() { any() }
final override Node0Impl getValue() { none() }
override Cpp::Location getLocation() { result = v.getLocation() }
final override SourceVariable getSourceVariable() {
final override NormalSourceVariable getSourceVariable() {
result.getBaseVariable() = v and
result.getIndirection() = 0
}
final override BaseSourceVariable getBaseSourceVariable() { result = v }
}
private class DefVariableAddressImpl extends DefAddressImpl {
@@ -413,8 +510,17 @@ private class DirectDef extends DefImpl, TDirectDefImpl {
isDef(_, _, address, result, _, indirectionIndex)
}
override BaseSourceVariable getBaseSourceVariable() {
result = this.getBase().getBaseSourceVariable()
pragma[nomagic]
private predicate hasBaseSourceVariableAndIndirection(BaseSourceVariable v, int indirection) {
v = this.getBase().getBaseSourceVariable() and
indirection = this.getIndirection()
}
final override NormalSourceVariable getSourceVariable() {
exists(BaseSourceVariable v, int indirection |
sourceVariableHasBaseAndIndex(result, v, indirection) and
this.hasBaseSourceVariableAndIndirection(v, indirection)
)
}
override int getIndirection() { isDef(_, _, address, _, result, indirectionIndex) }
@@ -424,6 +530,32 @@ private class DirectDef extends DefImpl, TDirectDefImpl {
override predicate isCertain() { isDef(true, _, address, _, _, indirectionIndex) }
}
/**
* A definition that "saves" the value of a variable before it is incremented
* or decremented.
*/
private class SavedPostfixCrementDefImpl extends DefImpl, TSavedPostfixCrementDefImpl {
SavedPostfixCrementSourceVariable sv;
SavedPostfixCrementDefImpl() { this = TSavedPostfixCrementDefImpl(sv, indirectionIndex) }
override Cpp::Location getLocation() { result = sv.getStoreInstruction().getLocation() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
sv.getStoreInstruction() = block.getInstruction(index)
}
override string toString() { result = "Def of " + this.getSourceVariable() }
override SourceVariable getSourceVariable() { result = sv }
override int getIndirection() { result = sv.getIndirection() }
override predicate isCertain() {
isDef(true, _, sv.getStoreInstruction().getDestinationAddressOperand(), _, _, indirectionIndex)
}
}
private class DirectUseImpl extends UseImpl, TDirectUseImpl {
Operand operand;
@@ -432,29 +564,22 @@ private class DirectUseImpl extends UseImpl, TDirectUseImpl {
override string toString() { result = "Use of " + this.getSourceVariable() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
// See the comment in `ssa0`'s `OperandBasedUse` for an explanation of this
// predicate's implementation.
if this.getBase().getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
then
exists(Operand op, int indirection, Instruction base |
indirection = this.getIndirection() and
base = this.getBase() and
op =
min(Operand cand, int i |
isUse(_, cand, base, indirection, indirectionIndex) and
block.getInstruction(i) = cand.getUse()
|
cand order by i
) and
block.getInstruction(index) = op.getUse()
)
else operand.getUse() = block.getInstruction(index)
operand.getUse() = block.getInstruction(index)
}
private BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, indirectionIndex) }
override BaseSourceVariable getBaseSourceVariable() {
result = this.getBase().getBaseSourceVariable()
pragma[nomagic]
private predicate hasBaseSourceVariableAndIndirection(BaseSourceVariable bv, int indirection) {
this.getBase().getBaseSourceVariable() = bv and
this.getIndirection() = indirection
}
override NormalSourceVariable getSourceVariable() {
exists(BaseSourceVariable v, int indirection |
sourceVariableHasBaseAndIndex(result, v, indirection) and
this.hasBaseSourceVariableAndIndirection(v, indirection)
)
}
final Operand getOperand() { result = operand }
@@ -468,6 +593,34 @@ private class DirectUseImpl extends UseImpl, TDirectUseImpl {
override Node getNode() { nodeHasOperand(result, operand, indirectionIndex) }
}
/**
* The use of the original "saved" variable after the variable has been incremented
* or decremented.
*/
private class SavedPostfixCrementUseImpl extends UseImpl, TSavedPostfixCrementUseImpl {
SavedPostfixCrementSourceVariable sv;
SavedPostfixCrementUseImpl() { this = TSavedPostfixCrementUseImpl(sv, indirectionIndex) }
override string toString() { result = "Use of " + this.getSourceVariable() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
this.getOperand().getUse() = block.getInstruction(index)
}
override SourceVariable getSourceVariable() { result = sv }
final Operand getOperand() { result = sv.getOperand() }
final override Cpp::Location getLocation() { result = this.getOperand().getLocation() }
override int getIndirection() { result = sv.getIndirection() }
override predicate isCertain() { isUse(true, this.getOperand(), _, _, indirectionIndex) }
override Node getNode() { nodeHasOperand(result, this.getOperand(), indirectionIndex) }
}
pragma[nomagic]
private predicate finalParameterNodeHasParameterAndIndex(
FinalParameterNode n, Parameter p, int indirectionIndex
@@ -532,7 +685,18 @@ class FinalParameterUse extends UseImpl, TFinalParameterUse {
result instanceof UnknownLocation
}
override BaseIRVariable getBaseSourceVariable() { result.getIRVariable().getAst() = p }
pragma[nomagic]
private predicate hasBaseSourceVariableAndIndirection(BaseIRVariable v, int indirection) {
v.getIRVariable().getAst() = p and
indirection = this.getIndirection()
}
override NormalSourceVariable getSourceVariable() {
exists(BaseIRVariable v, int indirection |
sourceVariableHasBaseAndIndex(result, v, indirection) and
this.hasBaseSourceVariableAndIndirection(v, indirection)
)
}
}
/**
@@ -612,8 +776,17 @@ class GlobalUse extends UseImpl, TGlobalUse {
hasReturnPosition(f, block, index)
}
override BaseSourceVariable getBaseSourceVariable() {
baseSourceVariableIsGlobal(result, global, f)
pragma[nomagic]
private predicate hasBaseSourceVariableAndIndirection(BaseIRVariable v, int indirection) {
baseSourceVariableIsGlobal(v, global, f) and
indirection = this.getIndirection()
}
override NormalSourceVariable getSourceVariable() {
exists(BaseIRVariable v, int indirection |
sourceVariableHasBaseAndIndex(result, v, indirection) and
this.hasBaseSourceVariableAndIndirection(v, indirection)
)
}
final override Cpp::Location getLocation() { result = f.getLocation() }
@@ -658,15 +831,15 @@ class GlobalDefImpl extends DefImpl, TGlobalDefImpl {
)
}
/** Gets the global variable associated with this definition. */
override BaseSourceVariable getBaseSourceVariable() {
baseSourceVariableIsGlobal(result, global, f)
final override NormalSourceVariable getSourceVariable() {
exists(BaseSourceVariable v |
sourceVariableHasBaseAndIndex(result, v, indirectionIndex) and
baseSourceVariableIsGlobal(v, global, f)
)
}
override int getIndirection() { result = indirectionIndex }
override Node0Impl getValue() { none() }
override predicate isCertain() { any() }
/**
@@ -704,9 +877,15 @@ predicate defToNode(Node node, Definition def, SourceVariable sv) {
}
private predicate defToNode(Node node, Definition def) {
nodeHasOperand(node, def.getValue().asOperand(), def.getIndirectionIndex())
or
nodeHasInstruction(node, def.getValue().asInstruction(), def.getIndirectionIndex())
// Only definitions of `NormalSourceVariable` need to be converted into
// dataflow nodes. The other case, `SavedPostfixCrementSourceVariable`,
// are internal definitions that don't have a dataflow node representation.
def.getSourceVariable() instanceof NormalSourceVariable and
(
nodeHasOperand(node, def.getValue().asOperand(), def.getIndirectionIndex())
or
nodeHasInstruction(node, def.getValue().asInstruction(), def.getIndirectionIndex())
)
or
node.(InitialGlobalValue).getGlobalDef() = def
}
@@ -940,6 +1119,16 @@ module SsaCached {
SsaImpl::phiHasInputFromBlock(phi, inp, bb)
}
cached
predicate uncertainWriteDefinitionInput(Definition uncertain, Definition inp) {
SsaImpl::uncertainWriteDefinitionInput(uncertain, inp)
}
cached
predicate ssaDefReachesEndOfBlock(IRBlock bb, Definition def) {
SsaImpl::ssaDefReachesEndOfBlock(bb, def, _)
}
predicate variableRead = SsaInput::variableRead/4;
predicate variableWrite = SsaInput::variableWrite/4;
@@ -1035,13 +1224,23 @@ class SynthNode extends DataFlowIntegrationImpl::SsaNode {
SynthNode() { not this.asDefinition() instanceof SsaImpl::WriteDefinition }
}
signature predicate guardChecksNodeSig(IRGuards::IRGuardCondition g, Node e, boolean branch);
private signature class ParamSig;
signature predicate guardChecksNodeSig(
IRGuards::IRGuardCondition g, Node e, boolean branch, int indirectionIndex
);
private module ParamIntPair<ParamSig P> {
newtype TPair = MkPair(P p, int indirectionIndex) { nodeHasInstruction(_, _, indirectionIndex) }
}
module BarrierGuardWithIntParam<guardChecksNodeSig/4 guardChecksNode> {
private module WithParam<ParamSig P> {
signature predicate guardChecksNodeSig(IRGuards::IRGuardCondition g, Node e, boolean gv, P param);
}
private module IntWithParam<ParamSig P> {
signature predicate guardChecksNodeSig(
IRGuards::IRGuardCondition g, Node e, boolean gv, int indirectionIndex, P param
);
}
module BarrierGuardWithIntParam<ParamSig P, IntWithParam<P>::guardChecksNodeSig/5 guardChecksNode> {
private predicate ssaDefReachesCertainUse(Definition def, UseImpl use) {
exists(SourceVariable v, IRBlock bb, int i |
use.hasIndexInBlock(bb, i, v) and
@@ -1052,21 +1251,23 @@ module BarrierGuardWithIntParam<guardChecksNodeSig/4 guardChecksNode> {
private predicate guardChecksInstr(
IRGuards::Guards_v1::Guard g, IRGuards::GuardsInput::Expr instr, IRGuards::GuardValue gv,
int indirectionIndex
ParamIntPair<P>::TPair pair
) {
exists(Node node |
exists(Node node, int indirectionIndex, P p |
pair = ParamIntPair<P>::MkPair(p, indirectionIndex) and
nodeHasInstruction(node, instr, indirectionIndex) and
guardChecksNode(g, node, gv.asBooleanValue(), indirectionIndex)
guardChecksNode(g, node, gv.asBooleanValue(), indirectionIndex, p)
)
}
private predicate guardChecksWithWrappers(
DataFlowIntegrationInput::Guard g, SsaImpl::Definition def, IRGuards::GuardValue val,
int indirectionIndex
ParamIntPair<P>::MkPair pair
) {
exists(Instruction e |
IRGuards::Guards_v1::ParameterizedValidationWrapper<int, guardChecksInstr/4>::guardChecks(g,
e, val, indirectionIndex)
exists(Instruction e, int indirectionIndex |
IRGuards::Guards_v1::ParameterizedValidationWrapper<ParamIntPair<P>::TPair, guardChecksInstr/4>::guardChecks(g,
e, val, pair) and
pair = ParamIntPair<P>::MkPair(_, indirectionIndex)
|
indirectionIndex = 0 and
def.(Definition).getAUse().getDef() = e
@@ -1075,18 +1276,19 @@ module BarrierGuardWithIntParam<guardChecksNodeSig/4 guardChecksNode> {
)
}
Node getABarrierNode(int indirectionIndex) {
Node getABarrierNode(int indirectionIndex, P p) {
// Only get the SynthNodes from the shared implementation, as the ExprNodes cannot
// be matched on SourceVariable.
result.(SsaSynthNode).getSynthNode() =
DataFlowIntegrationImpl::BarrierGuardDefWithState<int, guardChecksWithWrappers/4>::getABarrierNode(indirectionIndex)
DataFlowIntegrationImpl::BarrierGuardDefWithState<ParamIntPair<P>::MkPair, guardChecksWithWrappers/4>::getABarrierNode(ParamIntPair<P>::MkPair(p,
indirectionIndex))
or
// Calculate the guarded UseImpls corresponding to ExprNodes directly.
exists(
DataFlowIntegrationInput::Guard g, IRGuards::GuardValue branch, Definition def, IRBlock bb
|
guardChecksWithWrappers(g, def, branch, indirectionIndex) and
exists(UseImpl use |
guardChecksWithWrappers(g, def, branch, ParamIntPair<P>::MkPair(p, indirectionIndex)) and
ssaDefReachesCertainUse(def, use) and
use.getBlock() = bb and
DataFlowIntegrationInput::guardControlsBlock(g, bb, branch) and
@@ -1096,15 +1298,16 @@ module BarrierGuardWithIntParam<guardChecksNodeSig/4 guardChecksNode> {
}
}
module BarrierGuard<guardChecksNodeSig/3 guardChecksNode> {
module BarrierGuard<ParamSig P, WithParam<P>::guardChecksNodeSig/4 guardChecksNode> {
private predicate guardChecksNode(
IRGuards::IRGuardCondition g, Node e, boolean branch, int indirectionIndex
IRGuards::IRGuardCondition g, Node e, boolean gv, int indirectionIndex, P p
) {
guardChecksNode(g, e, branch) and indirectionIndex = 0
indirectionIndex = 0 and
guardChecksNode(g, e, gv, p)
}
Node getABarrierNode() {
result = BarrierGuardWithIntParam<guardChecksNode/4>::getABarrierNode(0)
Node getABarrierNode(P p) {
result = BarrierGuardWithIntParam<P, guardChecksNode/5>::getABarrierNode(0, p)
}
}
@@ -1159,9 +1362,17 @@ class Definition extends SsaImpl::Definition {
private Definition getAPhiInputOrPriorDefinition() {
result = this.(PhiNode).getAnInput()
or
SsaImpl::uncertainWriteDefinitionInput(this, result)
uncertainWriteDefinitionInput(this, result)
}
/**
* Holds if this SSA definition is live at the end of basic block `bb`.
* That is, this definition reaches the end of basic block `bb`, at which
* point it is still live, without crossing another SSA definition of the
* same source variable.
*/
predicate isLiveAtEndOfBlock(IRBlock bb) { ssaDefReachesEndOfBlock(bb, this) }
/**
* Gets a definition that ultimately defines this SSA definition and is
* not itself a phi node.

View File

@@ -104,7 +104,11 @@ newtype TInstructionTag =
} or
SizeofVlaDimensionTag(int index) {
exists(VlaDeclStmt v | exists(v.getTransitiveVlaDimensionStmt(index)))
}
} or
AssertionVarAddressTag() or
AssertionVarLoadTag() or
AssertionOpTag() or
AssertionBranchTag()
class InstructionTag extends TInstructionTag {
final string toString() { result = getInstructionTagId(this) }
@@ -296,4 +300,12 @@ string getInstructionTagId(TInstructionTag tag) {
tag = CoAwaitBranchTag() and result = "CoAwaitBranch"
or
tag = BoolToIntConversionTag() and result = "BoolToIntConversion"
or
tag = AssertionVarAddressTag() and result = "AssertionVarAddress"
or
tag = AssertionVarLoadTag() and result = "AssertionVarLoad"
or
tag = AssertionOpTag() and result = "AssertionOp"
or
tag = AssertionBranchTag() and result = "AssertionBranch"
}

View File

@@ -0,0 +1,387 @@
private import cpp
private import semmle.code.cpp.ir.internal.IRUtilities
private import semmle.code.cpp.ir.implementation.internal.OperandTag
private import semmle.code.cpp.ir.internal.CppType
private import semmle.code.cpp.ir.internal.TempVariableTag
private import InstructionTag
private import TranslatedElement
private import TranslatedStmt
private import TranslatedFunction
/**
* Holds if `s` is a statement that may be an expanded assertion in a
* release build.
*/
pragma[nomagic]
private predicate stmtCandidate(Stmt s) {
not s.isFromUninstantiatedTemplate(_) and
(
// The expansion of `__analysis_assume(x != 0);` when `__analysis_assume` is
// empty is the empty statement.
s instanceof EmptyStmt
or
// The expansion of `assert(x != 0)` when `assert` is `((void)0)` is a zero literal
// with a void type.
exists(Expr e |
e = s.(ExprStmt).getExpr() and
e.getValue() = "0" and
e.getActualType() instanceof VoidType
)
)
}
pragma[nomagic]
private predicate macroInvocationLocation(int startline, Function f, MacroInvocation mi) {
mi.getMacroName() = ["assert", "__analysis_assume"] and
mi.getNumberOfArguments() = 1 and
mi.getLocation().hasLocationInfo(_, startline, _, _, _) and
f.getEntryPoint().isAffectedByMacro(mi)
}
pragma[nomagic]
private predicate stmtParentLocation(int startline, Function f, StmtParent p) {
p.getEnclosingFunction() = f and
p.getLocation().hasLocationInfo(_, startline, _, _, _)
}
/**
* Holds if `mi` is a macro invocation with a name that is known
* to correspond to an assertion macro, and the macro invocation
* is the only thing on the line.
*/
pragma[nomagic]
private predicate assertion0(MacroInvocation mi, Stmt s, string arg) {
stmtCandidate(s) and
s =
unique(StmtParent p, int startline, Function f |
macroInvocationLocation(startline, f, mi) and
stmtParentLocation(startline, f, p) and
// Also do not count the elements from the expanded macro, i.e., when checking
// if `assert(x)` is the only thing on the line we do not count the
// generated `((void)0)` expression.
not p = mi.getAnExpandedElement()
|
p
) and
arg = mi.getUnexpandedArgument(0)
}
private Function getEnclosingFunctionForMacroInvocation(MacroInvocation mi) {
exists(Stmt s |
assertion0(mi, s, _) and
result = s.getEnclosingFunction()
)
}
/**
* Holds if `arg` has two components and the `i`'th component of the string
* `arg` is `s`, and the components are separated by an operation with
* opcode `opcode`.
*/
bindingset[arg]
pragma[inline_late]
private predicate parseArgument(string arg, string s, int i, Opcode opcode) {
s =
arg.regexpCapture("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?<=\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)",
i + 1) and
opcode instanceof Opcode::CompareLE
or
s =
arg.regexpCapture("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?>=\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)",
i + 1) and
opcode instanceof Opcode::CompareGE
or
s =
arg.regexpCapture("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?<\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)",
i + 1) and
opcode instanceof Opcode::CompareLT
or
s =
arg.regexpCapture("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?>\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)",
i + 1) and
opcode instanceof Opcode::CompareGT
or
s =
arg.regexpCapture("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?!=\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)",
i + 1) and
opcode instanceof Opcode::CompareNE
or
s =
arg.regexpCapture("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?==\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)",
i + 1) and
opcode instanceof Opcode::CompareEQ
}
private Element getAChildScope(Element scope) { result.getParentScope() = scope }
private predicate hasAVariable(MacroInvocation mi, Stmt s, Element scope) {
assertion0(mi, s, _) and
s.getParent() = scope
or
hasAVariable(mi, s, getAChildScope(scope))
}
private LocalScopeVariable getVariable(MacroInvocation mi, int i) {
exists(string operand, string arg, Stmt s |
assertion0(mi, s, arg) and
parseArgument(arg, operand, i, _) and
result =
unique(Variable v |
v.getLocation().getStartLine() < s.getLocation().getStartLine() and
hasAVariable(mi, s, v.getParentScope()) and
v.hasName(operand)
|
v
)
)
}
/**
* Holds if the `i`'th component of the macro invocation `mi` with opcode
* `opcode` is a reference to `var`.
*/
private predicate hasVarAccessMacroArgument(MacroInvocation mi, Variable var, int i, Opcode opcode) {
exists(string arg, string s, Function f |
arg = mi.getUnexpandedArgument(0) and
f = getEnclosingFunctionForMacroInvocation(mi) and
parseArgument(arg, s, i, opcode) and
var = getVariable(mi, i)
)
}
/**
* Holds if the `i`'th component of the macro invocation `mi` with opcode
* `opcode` is a constant with the value `k`.
*/
private predicate hasConstMacroArgument(MacroInvocation mi, int k, int i, Opcode opcode) {
exists(string arg, string s |
assertion0(mi, _, arg) and
s.toInt() = k and
parseArgument(arg, s, i, opcode)
)
}
predicate hasAssertionOperand(MacroInvocation mi, int i) {
hasVarAccessMacroArgument(mi, _, i, _)
or
hasConstMacroArgument(mi, _, i, _)
}
private predicate hasAssertionOpcode(MacroInvocation mi, Opcode opcode) {
hasVarAccessMacroArgument(mi, _, _, opcode)
or
hasConstMacroArgument(mi, _, _, opcode)
}
/**
* Holds if `mi` is a macro invocation that is an assertion that should be generated
* in the control-flow graph at `s`.
*/
predicate assertion(MacroInvocation mi, Stmt s) {
assertion0(mi, s, _) and
hasAssertionOperand(mi, 0) and
hasAssertionOperand(mi, 1)
}
/** The translation of an operand of an assertion. */
abstract private class TranslatedAssertionOperand extends TranslatedElement,
TTranslatedAssertionOperand
{
MacroInvocation mi;
int index;
TranslatedAssertionOperand() { this = TTranslatedAssertionOperand(mi, index) }
MacroInvocation getMacroInvocation() { result = mi }
/**
* Gets the statement that is being replaced by the assertion that uses this
* operand.
*/
Stmt getStmt() { assertion(mi, result) }
final override Locatable getAst() { result = this.getStmt() }
final override TranslatedElement getChild(int id) { none() }
final override Declaration getFunction() { result = this.getStmt().getEnclosingFunction() }
/** Gets the instruction which holds the result of this operand. */
abstract Instruction getResult();
final override string toString() { result = "Operand of assertion: " + mi }
/** Gets the index of this operand (i.e., `0` or `1`). */
final int getIndex() { result = index }
}
/** An operand of an assertion that is a variable access. */
class TranslatedAssertionVarAccess extends TranslatedAssertionOperand {
TranslatedAssertionVarAccess() { hasVarAccessMacroArgument(mi, _, index, _) }
Variable getVariable() { hasVarAccessMacroArgument(mi, result, index, _) }
final override IRUserVariable getInstructionVariable(InstructionTag tag) {
tag = AssertionVarAddressTag() and
result.getVariable() = this.getVariable()
}
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(AssertionVarAddressTag()) and kind instanceof GotoEdge
}
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
tag = AssertionVarAddressTag() and
kind instanceof GotoEdge and
result = this.getInstruction(AssertionVarLoadTag())
or
tag = AssertionVarLoadTag() and
result = getTranslatedAssertionMacroInvocation(mi).getChildSuccessor(this, kind)
}
final override Instruction getALastInstructionInternal() {
result = this.getInstruction(AssertionVarLoadTag())
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
exists(Variable v | v = this.getVariable() |
opcode instanceof Opcode::VariableAddress and
tag = AssertionVarAddressTag() and
resultType = getTypeForGLValue(v.getType())
or
opcode instanceof Opcode::Load and
tag = AssertionVarLoadTag() and
resultType = getTypeForPRValue(v.getType())
)
}
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
tag = AssertionVarLoadTag() and
operandTag instanceof AddressOperandTag and
result = this.getInstruction(AssertionVarAddressTag())
}
final override Instruction getResult() { result = this.getInstruction(AssertionVarLoadTag()) }
}
/** An operand of an assertion that is a constant access. */
private class TranslatedAssertionConst extends TranslatedAssertionOperand {
TranslatedAssertionConst() { hasConstMacroArgument(mi, _, index, _) }
int getConst() { hasConstMacroArgument(mi, result, index, _) }
final override string getInstructionConstantValue(InstructionTag tag) {
tag = OnlyInstructionTag() and
result = this.getConst().toString()
}
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = getTranslatedAssertionMacroInvocation(mi).getChildSuccessor(this, kind)
}
final override Instruction getALastInstructionInternal() {
result = this.getInstruction(OnlyInstructionTag())
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
opcode instanceof Opcode::Constant and
tag = OnlyInstructionTag() and
resultType = getIntType()
}
final override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) }
}
/**
* Gets the `TranslatedAssertionMacroInvocation` corresponding to the macro
* invocation `mi`.
*/
TranslatedAssertionMacroInvocation getTranslatedAssertionMacroInvocation(MacroInvocation mi) {
result.getMacroInvocation() = mi
}
/**
* A synthesized assertion which would have otherwise been invisible because the
* database represents a release build where assertions are disabled.
*/
private class TranslatedAssertionMacroInvocation extends TranslatedStmt {
MacroInvocation mi;
TranslatedAssertionMacroInvocation() { assertion(mi, stmt) }
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getLeft().getFirstInstruction(kind)
}
TranslatedAssertionOperand getLeft() {
result.getMacroInvocation() = mi and
result.getIndex() = 0
}
TranslatedAssertionOperand getRight() {
result.getMacroInvocation() = mi and
result.getIndex() = 1
}
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
tag = AssertionOpTag() and
kind instanceof GotoEdge and
result = this.getInstruction(AssertionBranchTag())
or
tag = AssertionBranchTag() and
kind instanceof TrueEdge and
result = this.getParent().getChildSuccessor(this, _)
}
final override TranslatedElement getChildInternal(int id) {
id = 0 and result = this.getLeft()
or
id = 1 and result = this.getRight()
}
final override Instruction getALastInstructionInternal() {
result = this.getInstruction(AssertionBranchTag())
}
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = AssertionOpTag() and
resultType = getBoolType() and
hasAssertionOpcode(mi, opcode)
or
tag = AssertionBranchTag() and
resultType = getVoidType() and
opcode instanceof Opcode::ConditionalBranch
}
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
child = this.getLeft() and
result = this.getRight().getFirstInstruction(kind)
or
child = this.getRight() and
kind instanceof GotoEdge and
result = this.getInstruction(AssertionOpTag())
}
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
tag = AssertionOpTag() and
(
operandTag instanceof LeftOperandTag and
result = this.getLeft().getResult()
or
operandTag instanceof RightOperandTag and
result = this.getRight().getResult()
)
or
tag = AssertionBranchTag() and
operandTag instanceof ConditionOperandTag and
result = this.getInstruction(AssertionOpTag())
}
MacroInvocation getMacroInvocation() { result = mi }
}

View File

@@ -12,6 +12,7 @@ private import TranslatedFunction
private import TranslatedStmt
private import TranslatedExpr
private import IRConstruction
private import TranslatedAssertion
private import semmle.code.cpp.models.interfaces.SideEffect
private import SideEffects
@@ -138,6 +139,14 @@ private predicate ignoreExprAndDescendants(Expr expr) {
// conditionally constructed (until we have a mechanism for calling these only when the
// temporary's constructor was run)
isConditionalTemporaryDestructorCall(expr)
or
// An assertion in a release build is often defined as `#define assert(x) ((void)0)`.
// We generate a synthetic assertion in release builds, and when we do that the
// expression `((void)0)` should not be translated.
exists(MacroInvocation mi |
assertion(mi, _) and
expr = mi.getExpr().getFullyConverted()
)
}
/**
@@ -909,7 +918,8 @@ newtype TTranslatedElement =
} or
// The side effect that initializes newly-allocated memory.
TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or
TTranslatedStaticStorageDurationVarInit(Variable var) { Raw::varHasIRFunc(var) }
TTranslatedStaticStorageDurationVarInit(Variable var) { Raw::varHasIRFunc(var) } or
TTranslatedAssertionOperand(MacroInvocation mi, int index) { hasAssertionOperand(mi, index) }
/**
* Gets the index of the first explicitly initialized element in `initList`

View File

@@ -10,6 +10,7 @@ private import TranslatedElement
private import TranslatedExpr
private import TranslatedFunction
private import TranslatedInitialization
private import TranslatedAssertion
TranslatedStmt getTranslatedStmt(Stmt stmt) { result.getAst() = stmt }
@@ -324,8 +325,16 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
class TranslatedEmptyStmt extends TranslatedStmt {
TranslatedEmptyStmt() {
stmt instanceof EmptyStmt or
stmt instanceof LabelStmt or
// An assertion macro invocation can expand to
// an empty statement in release builds. In that case
// we synthesize the check that would have occurred.
// This is handled by `TranslatedAssertion.qll` and so
// we exclude these statements here.
not assertion(_, stmt) and
stmt instanceof EmptyStmt
or
stmt instanceof LabelStmt
or
stmt instanceof SwitchCase
}
@@ -420,6 +429,15 @@ class TranslatedDeclStmt extends TranslatedStmt {
class TranslatedExprStmt extends TranslatedStmt {
override ExprStmt stmt;
TranslatedExprStmt() {
// An assertion macro invocation typically expand to the
// expression `((void)0)` in release builds. In that case
// we synthesize the check that would have occurred.
// This is handled by `TranslatedAssertion.qll` and so
// we exclude these statements here.
not assertion(_, stmt)
}
TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr().getFullyConverted()) }
override TranslatedElement getChildInternal(int id) { id = 0 and result = this.getExpr() }

View File

@@ -16,17 +16,3 @@ private class MySqlExecutionFunction extends SqlExecutionFunction {
override predicate hasSqlArgument(FunctionInput input) { input.isParameterDeref(1) }
}
/**
* The `mysql_real_escape_string` family of functions from the MySQL C API.
*/
private class MySqlBarrierFunction extends SqlBarrierFunction {
MySqlBarrierFunction() {
this.hasName(["mysql_real_escape_string", "mysql_real_escape_string_quote"])
}
override predicate barrierSqlArgument(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(2) and
output.isParameterDeref(1)
}
}

View File

@@ -20,7 +20,7 @@ class Stmt extends StmtParent, @stmt {
predicate hasChild(Element e, int n) { this.getChild(n) = e }
/** Gets the enclosing function of this statement, if any. */
Function getEnclosingFunction() { result = stmtEnclosingElement(this) }
override Function getEnclosingFunction() { result = stmtEnclosingElement(this) }
/**
* Gets the nearest enclosing block of this statement in the source, if any.
@@ -159,7 +159,10 @@ private class TStmtParent = @stmt or @expr;
*
* This is normally a statement, but may be a `StmtExpr`.
*/
class StmtParent extends ControlFlowNode, TStmtParent { }
class StmtParent extends ControlFlowNode, TStmtParent {
/** Gets the enclosing function of this element, if any. */
Function getEnclosingFunction() { none() }
}
/**
* A C/C++ 'expression' statement.

View File

@@ -2353,6 +2353,7 @@ case @preprocdirect.kind of
| 14 = @ppd_ms_import
| 15 = @ppd_elifdef
| 16 = @ppd_elifndef
| 17 = @ppd_embed
| 18 = @ppd_warning
;
@@ -2379,6 +2380,11 @@ includes(
int included: @file ref
);
embeds(
unique int id: @ppd_embed ref,
int included: @file ref
);
link_targets(
int id: @link_target,
int binary: @file ref
@@ -2389,6 +2395,8 @@ link_parent(
int link_target : @link_target ref
);
/*- Database metadata -*/
/**
* The CLI will automatically emit applicable tuples for this table,
* such as `databaseMetadata("isOverlay", "true")` when building an
@@ -2399,6 +2407,8 @@ databaseMetadata(
string value: string ref
);
/*- Overlay support -*/
/**
* The CLI will automatically emit tuples for each new/modified/deleted file
* when building an overlay database.

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,2 @@
description: Sections for databaseMetadata and overlayChangedFiles
compatibility: full

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Support embed preprocessor directive
compatibility: partial

View File

@@ -1,3 +1,7 @@
## 1.5.10
No user-facing changes.
## 1.5.9
### Minor Analysis Improvements

View File

@@ -45,14 +45,15 @@ module SqlTaintedConfig implements DataFlow::ConfigSig {
predicate isBarrier(DataFlow::Node node) {
node.asExpr().getUnspecifiedType() instanceof IntegralType
}
predicate isBarrierIn(DataFlow::Node node) {
or
exists(SqlBarrierFunction sql, int arg, FunctionInput input |
node.asIndirectArgument() = sql.getACallToThisFunction().getArgument(arg) and
input.isParameterDeref(arg) and
sql.barrierSqlArgument(input, _)
)
or
// barrier defined using models-as-data
barrierNode(node, "sql-injection")
}
predicate observeDiffInformedIncrementalMode() { any() }

View File

@@ -0,0 +1,3 @@
## 1.5.10
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.5.9
lastReleaseVersion: 1.5.10

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.5.9
version: 1.5.10
groups:
- cpp
- queries

View File

@@ -310,7 +310,7 @@ private module SummaryModelGeneratorInput implements SummaryModelGeneratorInputS
}
private predicate hasManualSummaryModel(Callable api) {
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()) or
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.hasManualModel()) or
api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel())
}

View File

@@ -384,7 +384,9 @@ astGuardsControl
| test.c:126:7:126:7 | 1 | true | 131 | 132 |
| test.c:126:7:126:7 | 1 | true | 134 | 123 |
| test.c:126:7:126:28 | ... && ... | true | 126 | 128 |
| test.c:126:7:126:28 | ... && ... | true | 131 | 131 |
| test.c:126:7:126:28 | ... && ... | true | 131 | 132 |
| test.c:126:7:126:28 | ... && ... | true | 134 | 123 |
| test.c:126:12:126:26 | call to test3_condition | true | 126 | 128 |
| test.c:126:12:126:26 | call to test3_condition | true | 131 | 132 |
| test.c:131:7:131:7 | b | true | 131 | 132 |
@@ -405,9 +407,7 @@ astGuardsControl
| test.c:181:9:181:9 | x | true | 181 | 182 |
| test.c:181:9:181:9 | x | true | 186 | 180 |
| test.cpp:18:8:18:10 | call to get | true | 19 | 19 |
| test.cpp:31:7:31:13 | ... == ... | false | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | false | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | true | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | true | 31 | 32 |
| test.cpp:42:13:42:20 | call to getABool | true | 43 | 45 |
astGuardsEnsure
@@ -589,13 +589,9 @@ astGuardsEnsure
| test.c:175:13:175:32 | ... == ... | test.c:175:13:175:15 | call to foo | == | test.c:175:32:175:32 | 0 | 0 | 175 | 175 |
| test.c:175:13:175:32 | ... == ... | test.c:175:32:175:32 | 0 | != | test.c:175:13:175:15 | call to foo | 0 | 175 | 175 |
| test.c:175:13:175:32 | ... == ... | test.c:175:32:175:32 | 0 | == | test.c:175:13:175:15 | call to foo | 0 | 175 | 175 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | test.cpp:31:12:31:13 | - ... | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | test.cpp:31:12:31:13 | - ... | 0 | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | test.cpp:31:12:31:13 | - ... | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | test.cpp:31:12:31:13 | - ... | 0 | 31 | 32 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | != | test.cpp:31:7:31:7 | x | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | != | test.cpp:31:7:31:7 | x | 0 | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | == | test.cpp:31:7:31:7 | x | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | == | test.cpp:31:7:31:7 | x | 0 | 31 | 32 |
astGuardsEnsure_const
| test.c:7:9:7:13 | ... > ... | test.c:7:9:7:13 | ... > ... | != | 0 | 7 | 9 |
@@ -793,13 +789,21 @@ astGuardsEnsure_const
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | == | 1 | 131 | 132 |
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | == | 1 | 134 | 123 |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | 131 | 131 |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | 131 | 132 |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | 134 | 123 |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | == | 1 | 126 | 128 |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | == | 1 | 131 | 131 |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | == | 1 | 131 | 132 |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | == | 1 | 134 | 123 |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | 131 | 131 |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | 131 | 132 |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | 134 | 123 |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | == | 1 | 126 | 128 |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | == | 1 | 131 | 131 |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | == | 1 | 131 | 132 |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | == | 1 | 134 | 123 |
| test.c:126:12:126:26 | call to test3_condition | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
| test.c:126:12:126:26 | call to test3_condition | test.c:126:12:126:26 | call to test3_condition | != | 0 | 131 | 132 |
| test.c:126:12:126:26 | call to test3_condition | test.c:126:12:126:26 | call to test3_condition | == | 1 | 126 | 128 |
@@ -846,17 +850,11 @@ astGuardsEnsure_const
| test.c:181:9:181:9 | x | test.c:181:9:181:9 | x | == | 1 | 186 | 180 |
| test.cpp:18:8:18:10 | call to get | test.cpp:18:8:18:10 | call to get | != | 0 | 19 | 19 |
| test.cpp:18:8:18:10 | call to get | test.cpp:18:8:18:10 | call to get | == | 1 | 19 | 19 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | 31 | 32 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | != | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | != | 0 | 31 | 32 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | != | 1 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | != | 1 | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | == | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | == | 0 | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | == | 1 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | == | 1 | 31 | 32 |
| test.cpp:42:13:42:20 | call to getABool | test.cpp:42:13:42:20 | call to getABool | != | 0 | 43 | 45 |
| test.cpp:42:13:42:20 | call to getABool | test.cpp:42:13:42:20 | call to getABool | == | 1 | 43 | 45 |

View File

@@ -105,9 +105,13 @@
| test.c:126:7:126:7 | 1 | true | test.c:131:10:132:16 | { ... } |
| test.c:126:7:126:7 | 1 | true | test.c:134:1:123:10 | return ... |
| test.c:126:7:126:28 | ... && ... | not 0 | test.c:126:31:128:16 | { ... } |
| test.c:126:7:126:28 | ... && ... | not 0 | test.c:131:3:131:7 | if (...) ... |
| test.c:126:7:126:28 | ... && ... | not 0 | test.c:131:10:132:16 | { ... } |
| test.c:126:7:126:28 | ... && ... | not 0 | test.c:134:1:123:10 | return ... |
| test.c:126:7:126:28 | ... && ... | true | test.c:126:31:128:16 | { ... } |
| test.c:126:7:126:28 | ... && ... | true | test.c:131:3:131:7 | if (...) ... |
| test.c:126:7:126:28 | ... && ... | true | test.c:131:10:132:16 | { ... } |
| test.c:126:7:126:28 | ... && ... | true | test.c:134:1:123:10 | return ... |
| test.c:126:12:126:26 | call to test3_condition | not 0 | test.c:126:31:128:16 | { ... } |
| test.c:126:12:126:26 | call to test3_condition | not 0 | test.c:131:10:132:16 | { ... } |
| test.c:126:12:126:26 | call to test3_condition | true | test.c:126:31:128:16 | { ... } |
@@ -162,17 +166,11 @@
| test.c:219:9:219:22 | call to __builtin_expect | true | test.c:219:25:221:5 | { ... } |
| test.cpp:18:8:18:10 | call to get | not null | test.cpp:19:5:19:14 | ExprStmt |
| test.cpp:18:8:18:10 | call to get | true | test.cpp:19:5:19:14 | ExprStmt |
| test.cpp:30:22:30:22 | x | -1 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:30:22:30:22 | x | -1 | test.cpp:31:16:32:21 | { ... } |
| test.cpp:30:22:30:22 | x | not -1 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:30:22:30:22 | x | not -1 | test.cpp:34:1:34:1 | return ... |
| test.cpp:31:7:31:7 | x | -1 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:7 | x | -1 | test.cpp:31:16:32:21 | { ... } |
| test.cpp:31:7:31:7 | x | not -1 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:7 | x | not -1 | test.cpp:34:1:34:1 | return ... |
| test.cpp:31:7:31:13 | ... == ... | false | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | false | test.cpp:34:1:34:1 | return ... |
| test.cpp:31:7:31:13 | ... == ... | true | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | true | test.cpp:31:16:32:21 | { ... } |
| test.cpp:42:13:42:20 | call to getABool | true | test.cpp:43:9:45:23 | { ... } |
| test.cpp:60:31:60:31 | i | 0 | test.cpp:62:5:64:12 | case ...: |
@@ -408,19 +406,11 @@
| test.cpp:400:11:400:25 | call to testEnumWrapper | 2 | test.cpp:404:5:406:12 | case ...: |
| test.cpp:400:27:400:27 | b | false | test.cpp:404:5:406:12 | case ...: |
| test.cpp:400:27:400:27 | b | true | test.cpp:401:5:403:12 | case ...: |
| test.cpp:410:26:410:26 | o | not null | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:410:26:410:26 | o | not null | test.cpp:412:1:412:1 | return ... |
| test.cpp:410:26:410:26 | o | null | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:410:26:410:26 | o | null | test.cpp:411:11:411:18 | ExprStmt |
| test.cpp:411:7:411:8 | ! ... | false | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:7:411:8 | ! ... | false | test.cpp:412:1:412:1 | return ... |
| test.cpp:411:7:411:8 | ! ... | true | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:7:411:8 | ! ... | true | test.cpp:411:11:411:18 | ExprStmt |
| test.cpp:411:8:411:8 | o | false | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:8:411:8 | o | false | test.cpp:411:11:411:18 | ExprStmt |
| test.cpp:411:8:411:8 | o | not null | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:8:411:8 | o | not null | test.cpp:412:1:412:1 | return ... |
| test.cpp:411:8:411:8 | o | null | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:8:411:8 | o | null | test.cpp:411:11:411:18 | ExprStmt |
| test.cpp:411:8:411:8 | o | true | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:8:411:8 | o | true | test.cpp:412:1:412:1 | return ... |

View File

@@ -195,13 +195,9 @@ binary
| test.c:215:6:215:18 | call to __builtin_expect | test.c:215:17:215:17 | b | < | test.c:215:13:215:13 | a | 0 | test.c:215:21:217:5 | { ... } |
| test.c:219:9:219:22 | call to __builtin_expect | test.c:219:16:219:16 | a | >= | test.c:219:20:219:21 | 42 | 1 | test.c:219:25:221:5 | { ... } |
| test.c:219:9:219:22 | call to __builtin_expect | test.c:219:20:219:21 | 42 | < | test.c:219:16:219:16 | a | 0 | test.c:219:25:221:5 | { ... } |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | test.cpp:31:12:31:13 | - ... | 0 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | test.cpp:31:12:31:13 | - ... | 0 | test.cpp:34:1:34:1 | return ... |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | test.cpp:31:12:31:13 | - ... | 0 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | test.cpp:31:12:31:13 | - ... | 0 | test.cpp:31:16:32:21 | { ... } |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | != | test.cpp:31:7:31:7 | x | 0 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | != | test.cpp:31:7:31:7 | x | 0 | test.cpp:34:1:34:1 | return ... |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | == | test.cpp:31:7:31:7 | x | 0 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:12:31:13 | - ... | == | test.cpp:31:7:31:7 | x | 0 | test.cpp:31:16:32:21 | { ... } |
| test.cpp:105:6:105:14 | ... != ... | test.cpp:105:6:105:6 | f | != | test.cpp:105:11:105:14 | 0.0 | 0 | test.cpp:105:17:106:7 | { ... } |
| test.cpp:105:6:105:14 | ... != ... | test.cpp:105:11:105:14 | 0.0 | != | test.cpp:105:6:105:6 | f | 0 | test.cpp:105:17:106:7 | { ... } |
@@ -762,13 +758,21 @@ unary
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | == | 1 | test.c:131:10:132:16 | { ... } |
| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | == | 1 | test.c:134:1:123:10 | return ... |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | test.c:126:31:128:16 | { ... } |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | test.c:131:3:131:7 | if (...) ... |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | test.c:131:10:132:16 | { ... } |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | test.c:134:1:123:10 | return ... |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | == | 1 | test.c:126:31:128:16 | { ... } |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | == | 1 | test.c:131:3:131:7 | if (...) ... |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | == | 1 | test.c:131:10:132:16 | { ... } |
| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | == | 1 | test.c:134:1:123:10 | return ... |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | test.c:126:31:128:16 | { ... } |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | test.c:131:3:131:7 | if (...) ... |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | test.c:131:10:132:16 | { ... } |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | test.c:134:1:123:10 | return ... |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | == | 1 | test.c:126:31:128:16 | { ... } |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | == | 1 | test.c:131:3:131:7 | if (...) ... |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | == | 1 | test.c:131:10:132:16 | { ... } |
| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | == | 1 | test.c:134:1:123:10 | return ... |
| test.c:126:12:126:26 | call to test3_condition | test.c:126:12:126:26 | call to test3_condition | != | 0 | test.c:126:31:128:16 | { ... } |
| test.c:126:12:126:26 | call to test3_condition | test.c:126:12:126:26 | call to test3_condition | != | 0 | test.c:131:10:132:16 | { ... } |
| test.c:126:12:126:26 | call to test3_condition | test.c:126:12:126:26 | call to test3_condition | == | 1 | test.c:126:31:128:16 | { ... } |
@@ -853,17 +857,11 @@ unary
| test.c:219:9:219:22 | call to __builtin_expect | test.c:219:16:219:21 | ... > ... | != | 0 | test.c:219:25:221:5 | { ... } |
| test.cpp:18:8:18:10 | call to get | test.cpp:18:8:18:10 | call to get | != | 0 | test.cpp:19:5:19:14 | ExprStmt |
| test.cpp:18:8:18:10 | call to get | test.cpp:18:8:18:10 | call to get | == | 1 | test.cpp:19:5:19:14 | ExprStmt |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | test.cpp:34:1:34:1 | return ... |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | -1 | test.cpp:31:16:32:21 | { ... } |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | != | 0 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | != | 0 | test.cpp:31:16:32:21 | { ... } |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | != | 1 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | != | 1 | test.cpp:34:1:34:1 | return ... |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | == | 0 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | == | 0 | test.cpp:34:1:34:1 | return ... |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | == | 1 | test.cpp:30:6:30:16 | doSomething |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:13 | ... == ... | == | 1 | test.cpp:31:16:32:21 | { ... } |
| test.cpp:42:13:42:20 | call to getABool | test.cpp:42:13:42:20 | call to getABool | != | 0 | test.cpp:43:9:45:23 | { ... } |
| test.cpp:42:13:42:20 | call to getABool | test.cpp:42:13:42:20 | call to getABool | == | 1 | test.cpp:43:9:45:23 | { ... } |
@@ -1401,35 +1399,19 @@ unary
| test.cpp:394:7:394:47 | ... == ... | test.cpp:394:15:394:34 | call to returnAIfNoneAreNull | == | 0 | test.cpp:394:50:395:7 | { ... } |
| test.cpp:400:11:400:25 | call to testEnumWrapper | test.cpp:400:11:400:25 | call to testEnumWrapper | == | 1 | test.cpp:401:5:403:12 | case ...: |
| test.cpp:400:11:400:25 | call to testEnumWrapper | test.cpp:400:11:400:25 | call to testEnumWrapper | == | 2 | test.cpp:404:5:406:12 | case ...: |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:7:411:8 | ! ... | != | 0 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:7:411:8 | ! ... | != | 0 | test.cpp:411:11:411:18 | ExprStmt |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:7:411:8 | ! ... | != | 1 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:7:411:8 | ! ... | != | 1 | test.cpp:412:1:412:1 | return ... |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:7:411:8 | ! ... | == | 0 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:7:411:8 | ! ... | == | 0 | test.cpp:412:1:412:1 | return ... |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:7:411:8 | ! ... | == | 1 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:7:411:8 | ! ... | == | 1 | test.cpp:411:11:411:18 | ExprStmt |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:8:411:8 | o | != | 0 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:8:411:8 | o | != | 0 | test.cpp:412:1:412:1 | return ... |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:8:411:8 | o | != | 1 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:8:411:8 | o | != | 1 | test.cpp:411:11:411:18 | ExprStmt |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:8:411:8 | o | == | 0 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:8:411:8 | o | == | 0 | test.cpp:411:11:411:18 | ExprStmt |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:8:411:8 | o | == | 1 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:7:411:8 | ! ... | test.cpp:411:8:411:8 | o | == | 1 | test.cpp:412:1:412:1 | return ... |
| test.cpp:411:8:411:8 | o | test.cpp:411:7:411:8 | ! ... | != | 0 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:8:411:8 | o | test.cpp:411:7:411:8 | ! ... | != | 0 | test.cpp:411:11:411:18 | ExprStmt |
| test.cpp:411:8:411:8 | o | test.cpp:411:7:411:8 | ! ... | != | 1 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:8:411:8 | o | test.cpp:411:7:411:8 | ! ... | != | 1 | test.cpp:412:1:412:1 | return ... |
| test.cpp:411:8:411:8 | o | test.cpp:411:7:411:8 | ! ... | == | 0 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:8:411:8 | o | test.cpp:411:7:411:8 | ! ... | == | 0 | test.cpp:412:1:412:1 | return ... |
| test.cpp:411:8:411:8 | o | test.cpp:411:7:411:8 | ! ... | == | 1 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:8:411:8 | o | test.cpp:411:7:411:8 | ! ... | == | 1 | test.cpp:411:11:411:18 | ExprStmt |
| test.cpp:411:8:411:8 | o | test.cpp:411:8:411:8 | o | != | 0 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:8:411:8 | o | test.cpp:411:8:411:8 | o | != | 0 | test.cpp:412:1:412:1 | return ... |
| test.cpp:411:8:411:8 | o | test.cpp:411:8:411:8 | o | != | 1 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:8:411:8 | o | test.cpp:411:8:411:8 | o | != | 1 | test.cpp:411:11:411:18 | ExprStmt |
| test.cpp:411:8:411:8 | o | test.cpp:411:8:411:8 | o | == | 0 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:8:411:8 | o | test.cpp:411:8:411:8 | o | == | 0 | test.cpp:411:11:411:18 | ExprStmt |
| test.cpp:411:8:411:8 | o | test.cpp:411:8:411:8 | o | == | 1 | test.cpp:410:6:410:18 | ensureNotNull |
| test.cpp:411:8:411:8 | o | test.cpp:411:8:411:8 | o | == | 1 | test.cpp:412:1:412:1 | return ... |

View File

@@ -0,0 +1,18 @@
struct S {
int x;
};
void use(int);
void test() {
int y = 43; // $ asDefinition=43
use(y);
y = 44; // $ asDefinition="... = ..."
use(y);
int x = 43; // $ asDefinition=43
x = 44; // $ asDefinition="... = ..."
S s;
s.x = 42; // $ asDefinition="... = ..."
}

View File

@@ -0,0 +1,22 @@
import cpp
import utils.test.InlineExpectationsTest
import semmle.code.cpp.dataflow.new.DataFlow::DataFlow
bindingset[s]
string quote(string s) { if s.matches("% %") then result = "\"" + s + "\"" else result = s }
module AsDefinitionTest implements TestSig {
string getARelevantTag() { result = "asDefinition" }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Node n, Expr e |
e = n.asDefinition() and
location = e.getLocation() and
element = n.toString() and
tag = "asDefinition" and
value = quote(e.toString())
)
}
}
import MakeTest<AsDefinitionTest>

View File

@@ -147,6 +147,29 @@ astFlow
| test.cpp:1165:10:1165:15 | call to source | test.cpp:1239:10:1239:26 | * ... |
| test.cpp:1195:10:1195:24 | call to indirect_source | test.cpp:1200:19:1200:36 | global_int_ptr_ptr |
| test.cpp:1195:10:1195:24 | call to indirect_source | test.cpp:1201:10:1201:27 | global_int_ptr_ptr |
| test.cpp:1258:11:1258:16 | call to source | test.cpp:1259:8:1259:10 | ... ++ |
| test.cpp:1262:7:1262:12 | call to source | test.cpp:1263:8:1263:10 | ... -- |
| test.cpp:1266:7:1266:12 | call to source | test.cpp:1267:8:1267:10 | ++ ... |
| test.cpp:1266:7:1266:12 | call to source | test.cpp:1268:8:1268:8 | x |
| test.cpp:1270:7:1270:12 | call to source | test.cpp:1271:8:1271:10 | -- ... |
| test.cpp:1270:7:1270:12 | call to source | test.cpp:1272:8:1272:8 | x |
| test.cpp:1274:7:1274:12 | call to source | test.cpp:1275:8:1275:14 | ... += ... |
| test.cpp:1274:7:1274:12 | call to source | test.cpp:1276:8:1276:8 | x |
| test.cpp:1278:7:1278:12 | call to source | test.cpp:1279:8:1279:14 | ... -= ... |
| test.cpp:1278:7:1278:12 | call to source | test.cpp:1280:8:1280:8 | x |
| test.cpp:1284:11:1284:16 | call to source | test.cpp:1285:8:1285:20 | ... ? ... : ... |
| test.cpp:1288:7:1288:12 | call to source | test.cpp:1289:8:1289:20 | ... ++ |
| test.cpp:1288:7:1288:12 | call to source | test.cpp:1290:8:1290:8 | x |
| test.cpp:1292:7:1292:12 | call to source | test.cpp:1294:8:1294:8 | x |
| test.cpp:1296:7:1296:12 | call to source | test.cpp:1297:8:1297:18 | ... ? ... : ... |
| test.cpp:1296:7:1296:12 | call to source | test.cpp:1298:8:1298:8 | x |
| test.cpp:1300:7:1300:12 | call to source | test.cpp:1301:8:1301:18 | ... ? ... : ... |
| test.cpp:1300:7:1300:12 | call to source | test.cpp:1302:8:1302:8 | x |
| test.cpp:1304:7:1304:12 | call to source | test.cpp:1305:8:1305:18 | ... ? ... : ... |
| test.cpp:1304:7:1304:12 | call to source | test.cpp:1306:8:1306:8 | x |
| test.cpp:1308:7:1308:12 | call to source | test.cpp:1309:14:1309:16 | ... ++ |
| test.cpp:1312:7:1312:12 | call to source | test.cpp:1313:8:1313:24 | ... ? ... : ... |
| test.cpp:1312:7:1312:12 | call to source | test.cpp:1314:8:1314:8 | x |
| true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x |
| true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x |
| true_upon_entry.cpp:33:11:33:16 | call to source | true_upon_entry.cpp:39:8:39:8 | x |
@@ -354,6 +377,19 @@ irFlow
| test.cpp:1195:10:1195:24 | *call to indirect_source | test.cpp:1218:19:1218:36 | **global_int_ptr_ptr |
| test.cpp:1195:10:1195:24 | *call to indirect_source | test.cpp:1224:19:1224:37 | ** ... |
| test.cpp:1195:10:1195:24 | *call to indirect_source | test.cpp:1227:10:1227:29 | * ... |
| test.cpp:1258:11:1258:16 | call to source | test.cpp:1259:8:1259:10 | ... ++ |
| test.cpp:1262:7:1262:12 | call to source | test.cpp:1263:8:1263:10 | ... -- |
| test.cpp:1284:11:1284:16 | call to source | test.cpp:1285:8:1285:20 | ... ? ... : ... |
| test.cpp:1288:7:1288:12 | call to source | test.cpp:1290:8:1290:8 | x |
| test.cpp:1292:7:1292:12 | call to source | test.cpp:1294:8:1294:8 | x |
| test.cpp:1296:7:1296:12 | call to source | test.cpp:1297:8:1297:18 | ... ? ... : ... |
| test.cpp:1296:7:1296:12 | call to source | test.cpp:1298:8:1298:8 | x |
| test.cpp:1300:7:1300:12 | call to source | test.cpp:1301:8:1301:18 | ... ? ... : ... |
| test.cpp:1300:7:1300:12 | call to source | test.cpp:1302:8:1302:8 | x |
| test.cpp:1304:7:1304:12 | call to source | test.cpp:1306:8:1306:8 | x |
| test.cpp:1308:7:1308:12 | call to source | test.cpp:1309:8:1309:16 | ... ++ |
| test.cpp:1312:7:1312:12 | call to source | test.cpp:1313:8:1313:24 | ... ? ... : ... |
| test.cpp:1312:7:1312:12 | call to source | test.cpp:1314:8:1314:8 | x |
| true_upon_entry.cpp:9:11:9:16 | call to source | true_upon_entry.cpp:13:8:13:8 | x |
| true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x |
| true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x |

View File

@@ -1252,4 +1252,64 @@ namespace globals_without_explicit_def {
calls_set_array();
sink(*global_int_array); // $ ir MISSING: ast
}
}
void crement_test1() {
int x = source();
sink(x++); // $ ir ast
sink(x);
x = source();
sink(x--); // $ ir ast
sink(x);
x = source();
sink(++x); // $ SPURIOUS: ast
sink(x); // $ SPURIOUS: ast
x = source();
sink(--x); // $ SPURIOUS: ast
sink(x); // $ SPURIOUS: ast
x = source();
sink(x += 10); // $ SPURIOUS: ast
sink(x); // $ SPURIOUS: ast
x = source();
sink(x -= 10); // $ SPURIOUS: ast
sink(x); // $ SPURIOUS: ast
}
void crement_test2(bool b, int y) {
int x = source();
sink(b ? x++ : x--); // $ ir ast
sink(x);
x = source();
sink((b ? x : y)++); // $ ast MISSING: ir
sink(x); // $ ir ast
x = source();
sink(++(b ? x : y));
sink(x); // $ ir ast
x = source();
sink(b ? x++ : y); // $ ir ast
sink(x); // $ ir ast
x = source();
sink(b ? x : y++); // $ ir ast
sink(x); // $ ir ast
x = source();
sink(b ? ++x : y); // $ SPURIOUS: ast
sink(x); // $ ir ast
x = source();
sink((long)x++); // $ ir ast
sink(x);
x = source();
sink(b ? (long)x++ : 0); // $ ir ast
sink(x); // $ ir ast
}

View File

@@ -3,6 +3,4 @@
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated |
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body |
| 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

@@ -12,4 +12,38 @@ void testCheckArgument(int p) {
if (checkArgument(&p)) {
sink(p); // $ barrier=glval<int> indirect_barrier=int
}
}
int* get_clean_value(int* x) { return x; }
bool is_clean_value(int*);
int* get_clean_pointer(int* x) { return x; }
bool is_clean_pointer(int*);
void sink(int*);
void test_mad(int x, int* p) {
{
if(is_clean_value(&x)) {
sink(x); // $ external=int
}
}
{
if(is_clean_value(p)) {
sink(*p); // $ external=int
}
}
{
if(is_clean_pointer(p)) {
sink(p); // $ external=int*
}
}
{
if(is_clean_pointer(&x)) {
sink(x); // $ external=glval<int>
}
}
}

View File

@@ -0,0 +1,13 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: barrierModel
data:
- ["", "", False, "get_clean_pointer", "", "", "ReturnValue", "test-barrier", "manual"]
- ["", "", False, "get_clean_data", "", "", "ReturnValue[*]", "test-barrier", "manual"]
- addsTo:
pack: codeql/cpp-all
extensible: barrierGuardModel
data:
- ["", "", False, "is_clean_value", "", "", "Argument[*0]", "true", "test-barrier", "manual"]
- ["", "", False, "is_clean_pointer", "", "", "Argument[0]", "true", "test-barrier", "manual"]

View File

@@ -2,6 +2,7 @@ import cpp
import semmle.code.cpp.dataflow.new.DataFlow
import semmle.code.cpp.controlflow.IRGuards
import utils.test.InlineExpectationsTest
import semmle.code.cpp.dataflow.ExternalFlow
predicate instructionGuardChecks(IRGuardCondition gc, Instruction checked, boolean branch) {
exists(CallInstruction call |
@@ -27,18 +28,26 @@ predicate barrierGuard(DataFlow::Node node, string s) {
else s = node.getType().toString().replaceAll(" ", "")
}
predicate externalBarrierGuard(DataFlow::Node node, string s) {
barrierNode(node, "test-barrier") and
if node.isGLValue()
then s = "glval<" + node.getType().toString().replaceAll(" ", "") + ">"
else s = node.getType().toString().replaceAll(" ", "")
}
module Test implements TestSig {
string getARelevantTag() { result = ["barrier", "indirect_barrier"] }
string getARelevantTag() { result = ["barrier", "indirect_barrier", "external"] }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node node, string s |
indirectBarrierGuard(node, s) and
value = s and
exists(DataFlow::Node node |
indirectBarrierGuard(node, value) and
tag = "indirect_barrier"
or
barrierGuard(node, s) and
value = s and
barrierGuard(node, value) and
tag = "barrier"
or
externalBarrierGuard(node, value) and
tag = "external"
|
element = node.toString() and
location = node.getLocation()

View File

@@ -25131,6 +25131,517 @@ ir.cpp:
# 2823| Type = [ArrayType] int[]
# 2823| ValueCategory = lvalue
# 2824| getStmt(5): [ReturnStmt] return ...
# 2830| [TopLevelFunction] void test_assert_simple(int, int, unsigned int, int)
# 2830| <params>:
# 2830| getParameter(0): [Parameter] x
# 2830| Type = [IntType] int
# 2830| getParameter(1): [Parameter] y
# 2830| Type = [IntType] int
# 2830| getParameter(2): [Parameter] u
# 2830| Type = [IntType] unsigned int
# 2830| getParameter(3): [Parameter] shadowed
# 2830| Type = [IntType] int
# 2830| getEntryPoint(): [BlockStmt] { ... }
# 2831| getStmt(0): [ExprStmt] ExprStmt
# 2831| getExpr(): [Literal] 0
# 2831| Type = [IntType] int
# 2831| Value = [Literal] 0
# 2831| ValueCategory = prvalue
# 2831| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2831| Type = [VoidType] void
# 2831| ValueCategory = prvalue
# 2831| getExpr(): [CStyleCast] (void)...
# 2831| Conversion = [VoidConversion] conversion to void
# 2831| Type = [VoidType] void
# 2831| ValueCategory = prvalue
# 2832| getStmt(1): [ExprStmt] ExprStmt
# 2832| getExpr(): [Literal] 0
# 2832| Type = [IntType] int
# 2832| Value = [Literal] 0
# 2832| ValueCategory = prvalue
# 2832| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2832| Type = [VoidType] void
# 2832| ValueCategory = prvalue
# 2832| getExpr(): [CStyleCast] (void)...
# 2832| Conversion = [VoidConversion] conversion to void
# 2832| Type = [VoidType] void
# 2832| ValueCategory = prvalue
# 2833| getStmt(2): [ExprStmt] ExprStmt
# 2833| getExpr(): [Literal] 0
# 2833| Type = [IntType] int
# 2833| Value = [Literal] 0
# 2833| ValueCategory = prvalue
# 2833| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2833| Type = [VoidType] void
# 2833| ValueCategory = prvalue
# 2833| getExpr(): [CStyleCast] (void)...
# 2833| Conversion = [VoidConversion] conversion to void
# 2833| Type = [VoidType] void
# 2833| ValueCategory = prvalue
# 2835| getStmt(3): [EmptyStmt] ;
# 2837| getStmt(4): [ExprStmt] ExprStmt
# 2837| getExpr(): [Literal] 0
# 2837| Type = [IntType] int
# 2837| Value = [Literal] 0
# 2837| ValueCategory = prvalue
# 2837| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2837| Type = [VoidType] void
# 2837| ValueCategory = prvalue
# 2837| getExpr(): [CStyleCast] (void)...
# 2837| Conversion = [VoidConversion] conversion to void
# 2837| Type = [VoidType] void
# 2837| ValueCategory = prvalue
# 2839| getStmt(5): [BlockStmt] { ... }
# 2840| getStmt(0): [DeclStmt] declaration
# 2840| getDeclarationEntry(0): [VariableDeclarationEntry] definition of shadowed
# 2840| Type = [IntType] int
# 2840| getVariable().getInitializer(): [Initializer] initializer for shadowed
# 2840| getExpr(): [VariableAccess] x
# 2840| Type = [IntType] int
# 2840| ValueCategory = prvalue(load)
# 2841| getStmt(1): [ExprStmt] ExprStmt
# 2841| getExpr(): [Literal] 0
# 2841| Type = [IntType] int
# 2841| Value = [Literal] 0
# 2841| ValueCategory = prvalue
# 2841| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2841| Type = [VoidType] void
# 2841| ValueCategory = prvalue
# 2841| getExpr(): [CStyleCast] (void)...
# 2841| Conversion = [VoidConversion] conversion to void
# 2841| Type = [VoidType] void
# 2841| ValueCategory = prvalue
# 2843| getStmt(6): [ReturnStmt] return ...
# 2846| [TemplateFunction,TopLevelFunction] void test_assert_in_template<T>(T, int, unsigned int)
# 2846| <params>:
# 2846| getParameter(0): [Parameter] x
# 2846| Type = [TypeTemplateParameter] T
# 2846| getParameter(1): [Parameter] y
# 2846| Type = [IntType] int
# 2846| getParameter(2): [Parameter] u
# 2846| Type = [IntType] unsigned int
# 2846| getEntryPoint(): [BlockStmt] { ... }
# 2847| getStmt(0): [ExprStmt] ExprStmt
# 2847| getExpr(): [Literal] 0
# 2847| Type = [IntType] int
# 2847| Value = [Literal] 0
# 2847| ValueCategory = prvalue
# 2847| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2847| Type = [VoidType] void
# 2847| ValueCategory = prvalue
# 2847| getExpr(): [CStyleCast] (void)...
# 2847| Conversion = [VoidConversion] conversion to void
# 2847| Type = [VoidType] void
# 2847| ValueCategory = prvalue
# 2848| getStmt(1): [ExprStmt] ExprStmt
# 2848| getExpr(): [Literal] 0
# 2848| Type = [IntType] int
# 2848| Value = [Literal] 0
# 2848| ValueCategory = prvalue
# 2848| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2848| Type = [VoidType] void
# 2848| ValueCategory = prvalue
# 2848| getExpr(): [CStyleCast] (void)...
# 2848| Conversion = [VoidConversion] conversion to void
# 2848| Type = [VoidType] void
# 2848| ValueCategory = prvalue
# 2849| getStmt(2): [ExprStmt] ExprStmt
# 2849| getExpr(): [Literal] 0
# 2849| Type = [IntType] int
# 2849| Value = [Literal] 0
# 2849| ValueCategory = prvalue
# 2849| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2849| Type = [VoidType] void
# 2849| ValueCategory = prvalue
# 2849| getExpr(): [CStyleCast] (void)...
# 2849| Conversion = [VoidConversion] conversion to void
# 2849| Type = [VoidType] void
# 2849| ValueCategory = prvalue
# 2851| getStmt(3): [EmptyStmt] ;
# 2853| getStmt(4): [ExprStmt] ExprStmt
# 2853| getExpr(): [Literal] 0
# 2853| Type = [IntType] int
# 2853| Value = [Literal] 0
# 2853| ValueCategory = prvalue
# 2853| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2853| Type = [VoidType] void
# 2853| ValueCategory = prvalue
# 2853| getExpr(): [CStyleCast] (void)...
# 2853| Conversion = [VoidConversion] conversion to void
# 2853| Type = [VoidType] void
# 2853| ValueCategory = prvalue
# 2855| getStmt(5): [BlockStmt] { ... }
# 2856| getStmt(0): [DeclStmt] declaration
# 2856| getDeclarationEntry(0): [VariableDeclarationEntry] definition of shadowed
# 2856| Type = [IntType] int
# 2856| getVariable().getInitializer(): [Initializer] initializer for shadowed
# 2856| getExpr(): [VariableAccess] x
# 2856| Type = [TypeTemplateParameter] T
# 2856| ValueCategory = lvalue
# 2856| getExpr().getFullyConverted(): [CStyleCast] (int)...
# 2856| Type = [IntType] int
# 2856| ValueCategory = prvalue
# 2857| getStmt(1): [ExprStmt] ExprStmt
# 2857| getExpr(): [Literal] 0
# 2857| Type = [IntType] int
# 2857| Value = [Literal] 0
# 2857| ValueCategory = prvalue
# 2857| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2857| Type = [VoidType] void
# 2857| ValueCategory = prvalue
# 2857| getExpr(): [CStyleCast] (void)...
# 2857| Conversion = [VoidConversion] conversion to void
# 2857| Type = [VoidType] void
# 2857| ValueCategory = prvalue
# 2859| getStmt(6): [ExprStmt] ExprStmt
# 2859| getExpr(): [Literal] 0
# 2859| Type = [IntType] int
# 2859| Value = [Literal] 0
# 2859| ValueCategory = prvalue
# 2859| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2859| Type = [VoidType] void
# 2859| ValueCategory = prvalue
# 2859| getExpr(): [CStyleCast] (void)...
# 2859| Conversion = [VoidConversion] conversion to void
# 2859| Type = [VoidType] void
# 2859| ValueCategory = prvalue
# 2860| getStmt(7): [ReturnStmt] return ...
# 2846| [FunctionTemplateInstantiation,TopLevelFunction] void test_assert_in_template<int>(int, int, unsigned int)
# 2846| <params>:
# 2846| getParameter(0): [Parameter] x
# 2846| Type = [IntType] int
# 2846| getParameter(1): [Parameter] y
# 2846| Type = [IntType] int
# 2846| getParameter(2): [Parameter] u
# 2846| Type = [IntType] unsigned int
# 2846| getEntryPoint(): [BlockStmt] { ... }
# 2847| getStmt(0): [ExprStmt] ExprStmt
# 2847| getExpr(): [Literal] 0
# 2847| Type = [IntType] int
# 2847| Value = [Literal] 0
# 2847| ValueCategory = prvalue
# 2847| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2847| Type = [VoidType] void
# 2847| ValueCategory = prvalue
# 2847| getExpr(): [CStyleCast] (void)...
# 2847| Conversion = [VoidConversion] conversion to void
# 2847| Type = [VoidType] void
# 2847| ValueCategory = prvalue
# 2848| getStmt(1): [ExprStmt] ExprStmt
# 2848| getExpr(): [Literal] 0
# 2848| Type = [IntType] int
# 2848| Value = [Literal] 0
# 2848| ValueCategory = prvalue
# 2848| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2848| Type = [VoidType] void
# 2848| ValueCategory = prvalue
# 2848| getExpr(): [CStyleCast] (void)...
# 2848| Conversion = [VoidConversion] conversion to void
# 2848| Type = [VoidType] void
# 2848| ValueCategory = prvalue
# 2849| getStmt(2): [ExprStmt] ExprStmt
# 2849| getExpr(): [Literal] 0
# 2849| Type = [IntType] int
# 2849| Value = [Literal] 0
# 2849| ValueCategory = prvalue
# 2849| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2849| Type = [VoidType] void
# 2849| ValueCategory = prvalue
# 2849| getExpr(): [CStyleCast] (void)...
# 2849| Conversion = [VoidConversion] conversion to void
# 2849| Type = [VoidType] void
# 2849| ValueCategory = prvalue
# 2851| getStmt(3): [EmptyStmt] ;
# 2853| getStmt(4): [ExprStmt] ExprStmt
# 2853| getExpr(): [Literal] 0
# 2853| Type = [IntType] int
# 2853| Value = [Literal] 0
# 2853| ValueCategory = prvalue
# 2853| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2853| Type = [VoidType] void
# 2853| ValueCategory = prvalue
# 2853| getExpr(): [CStyleCast] (void)...
# 2853| Conversion = [VoidConversion] conversion to void
# 2853| Type = [VoidType] void
# 2853| ValueCategory = prvalue
# 2855| getStmt(5): [BlockStmt] { ... }
# 2856| getStmt(0): [DeclStmt] declaration
# 2856| getDeclarationEntry(0): [VariableDeclarationEntry] definition of shadowed
# 2856| Type = [IntType] int
# 2856| getVariable().getInitializer(): [Initializer] initializer for shadowed
# 2856| getExpr(): [VariableAccess] x
# 2856| Type = [IntType] int
# 2856| ValueCategory = prvalue(load)
# 2857| getStmt(1): [ExprStmt] ExprStmt
# 2857| getExpr(): [Literal] 0
# 2857| Type = [IntType] int
# 2857| Value = [Literal] 0
# 2857| ValueCategory = prvalue
# 2857| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2857| Type = [VoidType] void
# 2857| ValueCategory = prvalue
# 2857| getExpr(): [CStyleCast] (void)...
# 2857| Conversion = [VoidConversion] conversion to void
# 2857| Type = [VoidType] void
# 2857| ValueCategory = prvalue
# 2859| getStmt(6): [ExprStmt] ExprStmt
# 2859| getExpr(): [Literal] 0
# 2859| Type = [IntType] int
# 2859| Value = [Literal] 0
# 2859| ValueCategory = prvalue
# 2859| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2859| Type = [VoidType] void
# 2859| ValueCategory = prvalue
# 2859| getExpr(): [CStyleCast] (void)...
# 2859| Conversion = [VoidConversion] conversion to void
# 2859| Type = [VoidType] void
# 2859| ValueCategory = prvalue
# 2860| getStmt(7): [ReturnStmt] return ...
# 2846| [FunctionTemplateInstantiation,TopLevelFunction] void test_assert_in_template<short>(short, int, unsigned int)
# 2846| <params>:
# 2846| getParameter(0): [Parameter] x
# 2846| Type = [ShortType] short
# 2846| getParameter(1): [Parameter] y
# 2846| Type = [IntType] int
# 2846| getParameter(2): [Parameter] u
# 2846| Type = [IntType] unsigned int
# 2846| getEntryPoint(): [BlockStmt] { ... }
# 2847| getStmt(0): [ExprStmt] ExprStmt
# 2847| getExpr(): [Literal] 0
# 2847| Type = [IntType] int
# 2847| Value = [Literal] 0
# 2847| ValueCategory = prvalue
# 2847| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2847| Type = [VoidType] void
# 2847| ValueCategory = prvalue
# 2847| getExpr(): [CStyleCast] (void)...
# 2847| Conversion = [VoidConversion] conversion to void
# 2847| Type = [VoidType] void
# 2847| ValueCategory = prvalue
# 2848| getStmt(1): [ExprStmt] ExprStmt
# 2848| getExpr(): [Literal] 0
# 2848| Type = [IntType] int
# 2848| Value = [Literal] 0
# 2848| ValueCategory = prvalue
# 2848| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2848| Type = [VoidType] void
# 2848| ValueCategory = prvalue
# 2848| getExpr(): [CStyleCast] (void)...
# 2848| Conversion = [VoidConversion] conversion to void
# 2848| Type = [VoidType] void
# 2848| ValueCategory = prvalue
# 2849| getStmt(2): [ExprStmt] ExprStmt
# 2849| getExpr(): [Literal] 0
# 2849| Type = [IntType] int
# 2849| Value = [Literal] 0
# 2849| ValueCategory = prvalue
# 2849| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2849| Type = [VoidType] void
# 2849| ValueCategory = prvalue
# 2849| getExpr(): [CStyleCast] (void)...
# 2849| Conversion = [VoidConversion] conversion to void
# 2849| Type = [VoidType] void
# 2849| ValueCategory = prvalue
# 2851| getStmt(3): [EmptyStmt] ;
# 2853| getStmt(4): [ExprStmt] ExprStmt
# 2853| getExpr(): [Literal] 0
# 2853| Type = [IntType] int
# 2853| Value = [Literal] 0
# 2853| ValueCategory = prvalue
# 2853| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2853| Type = [VoidType] void
# 2853| ValueCategory = prvalue
# 2853| getExpr(): [CStyleCast] (void)...
# 2853| Conversion = [VoidConversion] conversion to void
# 2853| Type = [VoidType] void
# 2853| ValueCategory = prvalue
# 2855| getStmt(5): [BlockStmt] { ... }
# 2856| getStmt(0): [DeclStmt] declaration
# 2856| getDeclarationEntry(0): [VariableDeclarationEntry] definition of shadowed
# 2856| Type = [IntType] int
# 2856| getVariable().getInitializer(): [Initializer] initializer for shadowed
# 2856| getExpr(): [VariableAccess] x
# 2856| Type = [ShortType] short
# 2856| ValueCategory = prvalue(load)
# 2856| getExpr().getFullyConverted(): [CStyleCast] (int)...
# 2856| Conversion = [IntegralConversion] integral conversion
# 2856| Type = [IntType] int
# 2856| ValueCategory = prvalue
# 2857| getStmt(1): [ExprStmt] ExprStmt
# 2857| getExpr(): [Literal] 0
# 2857| Type = [IntType] int
# 2857| Value = [Literal] 0
# 2857| ValueCategory = prvalue
# 2857| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2857| Type = [VoidType] void
# 2857| ValueCategory = prvalue
# 2857| getExpr(): [CStyleCast] (void)...
# 2857| Conversion = [VoidConversion] conversion to void
# 2857| Type = [VoidType] void
# 2857| ValueCategory = prvalue
# 2859| getStmt(6): [ExprStmt] ExprStmt
# 2859| getExpr(): [Literal] 0
# 2859| Type = [IntType] int
# 2859| Value = [Literal] 0
# 2859| ValueCategory = prvalue
# 2859| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2859| Type = [VoidType] void
# 2859| ValueCategory = prvalue
# 2859| getExpr(): [CStyleCast] (void)...
# 2859| Conversion = [VoidConversion] conversion to void
# 2859| Type = [VoidType] void
# 2859| ValueCategory = prvalue
# 2860| getStmt(7): [ReturnStmt] return ...
# 2867| [TopLevelFunction] void (unnamed namespace)::complex_assertions(int, bool, int)
# 2867| <params>:
# 2867| getParameter(0): [Parameter] x
# 2867| Type = [IntType] int
# 2867| getParameter(1): [Parameter] b
# 2867| Type = [BoolType] bool
# 2867| getParameter(2): [Parameter] max
# 2867| Type = [IntType] int
# 2867| getEntryPoint(): [BlockStmt] { ... }
# 2868| getStmt(0): [DeclStmt] declaration
# 2868| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
# 2868| Type = [IntType] int
# 2868| getVariable().getInitializer(): [Initializer] initializer for y
# 2868| getExpr(): [CommaExpr] ... , ...
# 2868| Type = [IntType] int
# 2868| ValueCategory = prvalue(load)
# 2868| getLeftOperand(): [Literal] 0
# 2868| Type = [IntType] int
# 2868| Value = [Literal] 0
# 2868| ValueCategory = prvalue
# 2868| getRightOperand(): [VariableAccess] x
# 2868| Type = [IntType] int
# 2868| ValueCategory = prvalue(load)
# 2868| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
# 2868| Type = [VoidType] void
# 2868| ValueCategory = prvalue
# 2868| getExpr(): [CStyleCast] (void)...
# 2868| Conversion = [VoidConversion] conversion to void
# 2868| Type = [VoidType] void
# 2868| ValueCategory = prvalue
# 2868| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2868| Type = [IntType] int
# 2868| ValueCategory = prvalue(load)
# 2869| getStmt(1): [DeclStmt] declaration
# 2869| getDeclarationEntry(0): [VariableDeclarationEntry] definition of z
# 2869| Type = [IntType] int
# 2869| getVariable().getInitializer(): [Initializer] initializer for z
# 2869| getExpr(): [ConditionalExpr] ... ? ... : ...
# 2869| Type = [IntType] int
# 2869| ValueCategory = prvalue
# 2869| getCondition(): [VariableAccess] b
# 2869| Type = [BoolType] bool
# 2869| ValueCategory = prvalue(load)
# 2869| getThen(): [CommaExpr] ... , ...
# 2869| Type = [IntType] int
# 2869| Value = [CommaExpr] 0
# 2869| ValueCategory = prvalue
# 2869| getLeftOperand(): [Literal] 0
# 2869| Type = [IntType] int
# 2869| Value = [Literal] 0
# 2869| ValueCategory = prvalue
# 2869| getRightOperand(): [Literal] 0
# 2869| Type = [IntType] int
# 2869| Value = [Literal] 0
# 2869| ValueCategory = prvalue
# 2869| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
# 2869| Type = [VoidType] void
# 2869| ValueCategory = prvalue
# 2869| getExpr(): [CStyleCast] (void)...
# 2869| Conversion = [VoidConversion] conversion to void
# 2869| Type = [VoidType] void
# 2869| ValueCategory = prvalue
# 2869| getElse(): [Literal] 1
# 2869| Type = [IntType] int
# 2869| Value = [Literal] 1
# 2869| ValueCategory = prvalue
# 2869| getThen().getFullyConverted(): [ParenthesisExpr] (...)
# 2869| Type = [IntType] int
# 2869| Value = [ParenthesisExpr] 0
# 2869| ValueCategory = prvalue
# 2871| getStmt(2): [TryStmt] try { ... }
# 2871| getStmt(): [BlockStmt] { ... }
# 2872| getStmt(0): [ExprStmt] ExprStmt
# 2872| getExpr(): [ThrowExpr] throw ...
# 2872| Type = [IntType] int
# 2872| ValueCategory = prvalue
# 2872| getExpr(): [Literal] 41
# 2872| Type = [IntType] int
# 2872| Value = [Literal] 41
# 2872| ValueCategory = prvalue
# 2873| getChild(1): [Handler] <handler>
# 2873| getParameter(): [Parameter] c
# 2873| Type = [IntType] int
# 2873| getBlock(): [CatchBlock] { ... }
# 2874| getStmt(0): [ExprStmt] ExprStmt
# 2874| getExpr(): [Literal] 0
# 2874| Type = [IntType] int
# 2874| Value = [Literal] 0
# 2874| ValueCategory = prvalue
# 2874| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2874| Type = [VoidType] void
# 2874| ValueCategory = prvalue
# 2874| getExpr(): [CStyleCast] (void)...
# 2874| Conversion = [VoidConversion] conversion to void
# 2874| Type = [VoidType] void
# 2874| ValueCategory = prvalue
# 2875| getStmt(1): [ExprStmt] ExprStmt
# 2875| getExpr(): [Literal] 0
# 2875| Type = [IntType] int
# 2875| Value = [Literal] 0
# 2875| ValueCategory = prvalue
# 2875| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2875| Type = [VoidType] void
# 2875| ValueCategory = prvalue
# 2875| getExpr(): [CStyleCast] (void)...
# 2875| Conversion = [VoidConversion] conversion to void
# 2875| Type = [VoidType] void
# 2875| ValueCategory = prvalue
# 2878| getStmt(3): [ExprStmt] ExprStmt
# 2878| getExpr(): [Literal] 0
# 2878| Type = [IntType] int
# 2878| Value = [Literal] 0
# 2878| ValueCategory = prvalue
# 2878| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2878| Type = [VoidType] void
# 2878| ValueCategory = prvalue
# 2878| getExpr(): [CStyleCast] (void)...
# 2878| Conversion = [VoidConversion] conversion to void
# 2878| Type = [VoidType] void
# 2878| ValueCategory = prvalue
# 2879| getStmt(4): [DeclStmt] declaration
# 2879| getDeclarationEntry(0): [VariableDeclarationEntry] definition of shadowed
# 2879| Type = [IntType] int
# 2881| getStmt(5): [TryStmt] try { ... }
# 2881| getStmt(): [BlockStmt] { ... }
# 2882| getStmt(0): [ExprStmt] ExprStmt
# 2882| getExpr(): [ThrowExpr] throw ...
# 2882| Type = [IntType] int
# 2882| ValueCategory = prvalue
# 2882| getExpr(): [Literal] 41
# 2882| Type = [IntType] int
# 2882| Value = [Literal] 41
# 2882| ValueCategory = prvalue
# 2883| getChild(1): [Handler] <handler>
# 2883| getParameter(): [Parameter] shadowed
# 2883| Type = [IntType] int
# 2883| getBlock(): [CatchBlock] { ... }
# 2884| getStmt(0): [ExprStmt] ExprStmt
# 2884| getExpr(): [Literal] 0
# 2884| Type = [IntType] int
# 2884| Value = [Literal] 0
# 2884| ValueCategory = prvalue
# 2884| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
# 2884| Type = [VoidType] void
# 2884| ValueCategory = prvalue
# 2884| getExpr(): [CStyleCast] (void)...
# 2884| Conversion = [VoidConversion] conversion to void
# 2884| Type = [VoidType] void
# 2884| ValueCategory = prvalue
# 2886| getStmt(6): [ReturnStmt] return ...
ir23.cpp:
# 1| [TopLevelFunction] bool consteval_1()
# 1| <params>:

View File

@@ -20741,6 +20741,331 @@ ir.cpp:
# 2821| v2821_10(void) = AliasedUse : m2821_3
# 2821| v2821_11(void) = ExitFunction :
# 2830| void test_assert_simple(int, int, unsigned int, int)
# 2830| Block 0
# 2830| v2830_1(void) = EnterFunction :
# 2830| m2830_2(unknown) = AliasedDefinition :
# 2830| m2830_3(unknown) = InitializeNonLocal :
# 2830| m2830_4(unknown) = Chi : total:m2830_2, partial:m2830_3
# 2830| r2830_5(glval<int>) = VariableAddress[x] :
# 2830| m2830_6(int) = InitializeParameter[x] : &:r2830_5
# 2830| r2830_7(glval<int>) = VariableAddress[y] :
# 2830| m2830_8(int) = InitializeParameter[y] : &:r2830_7
# 2830| r2830_9(glval<unsigned int>) = VariableAddress[u] :
# 2830| m2830_10(unsigned int) = InitializeParameter[u] : &:r2830_9
# 2830| r2830_11(glval<int>) = VariableAddress[shadowed] :
# 2830| m2830_12(int) = InitializeParameter[shadowed] : &:r2830_11
# 2831| r2831_1(glval<int>) = VariableAddress[x] :
# 2831| r2831_2(int) = Load[x] : &:r2831_1, m2830_6
# 2831| r2831_3(int) = Constant[0] :
# 2831| r2831_4(bool) = CompareGT : r2831_2, r2831_3
# 2831| v2831_5(void) = ConditionalBranch : r2831_4
#-----| True -> Block 1
# 2832| Block 1
# 2832| r2832_1(int) = Constant[0] :
# 2832| r2832_2(glval<int>) = VariableAddress[x] :
# 2832| r2832_3(int) = Load[x] : &:r2832_2, m2830_6
# 2832| r2832_4(bool) = CompareLT : r2832_1, r2832_3
# 2832| v2832_5(void) = ConditionalBranch : r2832_4
#-----| True -> Block 2
# 2833| Block 2
# 2833| r2833_1(glval<int>) = VariableAddress[x] :
# 2833| r2833_2(int) = Load[x] : &:r2833_1, m2830_6
# 2833| r2833_3(glval<int>) = VariableAddress[y] :
# 2833| r2833_4(int) = Load[y] : &:r2833_3, m2830_8
# 2833| r2833_5(bool) = CompareLT : r2833_2, r2833_4
# 2833| v2833_6(void) = ConditionalBranch : r2833_5
#-----| True -> Block 3
# 2835| Block 3
# 2835| r2835_1(glval<int>) = VariableAddress[x] :
# 2835| r2835_2(int) = Load[x] : &:r2835_1, m2830_6
# 2835| r2835_3(int) = Constant[2] :
# 2835| r2835_4(bool) = CompareNE : r2835_2, r2835_3
# 2835| v2835_5(void) = ConditionalBranch : r2835_4
#-----| True -> Block 4
# 2837| Block 4
# 2837| r2837_1(glval<unsigned int>) = VariableAddress[u] :
# 2837| r2837_2(unsigned int) = Load[u] : &:r2837_1, m2830_10
# 2837| r2837_3(glval<int>) = VariableAddress[x] :
# 2837| r2837_4(int) = Load[x] : &:r2837_3, m2830_6
# 2837| r2837_5(bool) = CompareLT : r2837_2, r2837_4
# 2837| v2837_6(void) = ConditionalBranch : r2837_5
#-----| True -> Block 5
# 2840| Block 5
# 2840| r2840_1(glval<int>) = VariableAddress[shadowed] :
# 2840| r2840_2(glval<int>) = VariableAddress[x] :
# 2840| r2840_3(int) = Load[x] : &:r2840_2, m2830_6
# 2840| m2840_4(int) = Store[shadowed] : &:r2840_1, r2840_3
# 2841| r2841_1(int) = Constant[0] :
# 2841| v2841_2(void) = Convert : r2841_1
# 2843| v2843_1(void) = NoOp :
# 2830| v2830_13(void) = ReturnVoid :
# 2830| v2830_14(void) = AliasedUse : m2830_3
# 2830| v2830_15(void) = ExitFunction :
# 2846| void test_assert_in_template<int>(int, int, unsigned int)
# 2846| Block 0
# 2846| v2846_1(void) = EnterFunction :
# 2846| m2846_2(unknown) = AliasedDefinition :
# 2846| m2846_3(unknown) = InitializeNonLocal :
# 2846| m2846_4(unknown) = Chi : total:m2846_2, partial:m2846_3
# 2846| r2846_5(glval<int>) = VariableAddress[x] :
# 2846| m2846_6(int) = InitializeParameter[x] : &:r2846_5
# 2846| r2846_7(glval<int>) = VariableAddress[y] :
# 2846| m2846_8(int) = InitializeParameter[y] : &:r2846_7
# 2846| r2846_9(glval<unsigned int>) = VariableAddress[u] :
# 2846| m2846_10(unsigned int) = InitializeParameter[u] : &:r2846_9
# 2847| r2847_1(glval<int>) = VariableAddress[x] :
# 2847| r2847_2(int) = Load[x] : &:r2847_1, m2846_6
# 2847| r2847_3(int) = Constant[0] :
# 2847| r2847_4(bool) = CompareGT : r2847_2, r2847_3
# 2847| v2847_5(void) = ConditionalBranch : r2847_4
#-----| True -> Block 1
# 2848| Block 1
# 2848| r2848_1(int) = Constant[0] :
# 2848| r2848_2(glval<int>) = VariableAddress[x] :
# 2848| r2848_3(int) = Load[x] : &:r2848_2, m2846_6
# 2848| r2848_4(bool) = CompareLT : r2848_1, r2848_3
# 2848| v2848_5(void) = ConditionalBranch : r2848_4
#-----| True -> Block 2
# 2849| Block 2
# 2849| r2849_1(glval<int>) = VariableAddress[x] :
# 2849| r2849_2(int) = Load[x] : &:r2849_1, m2846_6
# 2849| r2849_3(glval<int>) = VariableAddress[y] :
# 2849| r2849_4(int) = Load[y] : &:r2849_3, m2846_8
# 2849| r2849_5(bool) = CompareLT : r2849_2, r2849_4
# 2849| v2849_6(void) = ConditionalBranch : r2849_5
#-----| True -> Block 3
# 2851| Block 3
# 2851| r2851_1(glval<int>) = VariableAddress[x] :
# 2851| r2851_2(int) = Load[x] : &:r2851_1, m2846_6
# 2851| r2851_3(int) = Constant[2] :
# 2851| r2851_4(bool) = CompareNE : r2851_2, r2851_3
# 2851| v2851_5(void) = ConditionalBranch : r2851_4
#-----| True -> Block 4
# 2853| Block 4
# 2853| r2853_1(glval<unsigned int>) = VariableAddress[u] :
# 2853| r2853_2(unsigned int) = Load[u] : &:r2853_1, m2846_10
# 2853| r2853_3(glval<int>) = VariableAddress[x] :
# 2853| r2853_4(int) = Load[x] : &:r2853_3, m2846_6
# 2853| r2853_5(bool) = CompareLT : r2853_2, r2853_4
# 2853| v2853_6(void) = ConditionalBranch : r2853_5
#-----| True -> Block 5
# 2856| Block 5
# 2856| r2856_1(glval<int>) = VariableAddress[shadowed] :
# 2856| r2856_2(glval<int>) = VariableAddress[x] :
# 2856| r2856_3(int) = Load[x] : &:r2856_2, m2846_6
# 2856| m2856_4(int) = Store[shadowed] : &:r2856_1, r2856_3
# 2857| r2857_1(glval<int>) = VariableAddress[shadowed] :
# 2857| r2857_2(int) = Load[shadowed] : &:r2857_1, m2856_4
# 2857| r2857_3(int) = Constant[0] :
# 2857| r2857_4(bool) = CompareGT : r2857_2, r2857_3
# 2857| v2857_5(void) = ConditionalBranch : r2857_4
#-----| True -> Block 6
# 2859| Block 6
# 2859| r2859_1(glval<int>) = VariableAddress[x] :
# 2859| r2859_2(int) = Load[x] : &:r2859_1, m2846_6
# 2859| r2859_3(int) = Constant[0] :
# 2859| r2859_4(bool) = CompareGT : r2859_2, r2859_3
# 2859| v2859_5(void) = ConditionalBranch : r2859_4
#-----| True -> Block 7
# 2860| Block 7
# 2860| v2860_1(void) = NoOp :
# 2846| v2846_11(void) = ReturnVoid :
# 2846| v2846_12(void) = AliasedUse : m2846_3
# 2846| v2846_13(void) = ExitFunction :
# 2846| void test_assert_in_template<short>(short, int, unsigned int)
# 2846| Block 0
# 2846| v2846_1(void) = EnterFunction :
# 2846| m2846_2(unknown) = AliasedDefinition :
# 2846| m2846_3(unknown) = InitializeNonLocal :
# 2846| m2846_4(unknown) = Chi : total:m2846_2, partial:m2846_3
# 2846| r2846_5(glval<short>) = VariableAddress[x] :
# 2846| m2846_6(short) = InitializeParameter[x] : &:r2846_5
# 2846| r2846_7(glval<int>) = VariableAddress[y] :
# 2846| m2846_8(int) = InitializeParameter[y] : &:r2846_7
# 2846| r2846_9(glval<unsigned int>) = VariableAddress[u] :
# 2846| m2846_10(unsigned int) = InitializeParameter[u] : &:r2846_9
# 2847| r2847_1(glval<short>) = VariableAddress[x] :
# 2847| r2847_2(short) = Load[x] : &:r2847_1, m2846_6
# 2847| r2847_3(int) = Constant[0] :
# 2847| r2847_4(bool) = CompareGT : r2847_2, r2847_3
# 2847| v2847_5(void) = ConditionalBranch : r2847_4
#-----| True -> Block 1
# 2848| Block 1
# 2848| r2848_1(int) = Constant[0] :
# 2848| r2848_2(glval<short>) = VariableAddress[x] :
# 2848| r2848_3(short) = Load[x] : &:r2848_2, m2846_6
# 2848| r2848_4(bool) = CompareLT : r2848_1, r2848_3
# 2848| v2848_5(void) = ConditionalBranch : r2848_4
#-----| True -> Block 2
# 2849| Block 2
# 2849| r2849_1(glval<short>) = VariableAddress[x] :
# 2849| r2849_2(short) = Load[x] : &:r2849_1, m2846_6
# 2849| r2849_3(glval<int>) = VariableAddress[y] :
# 2849| r2849_4(int) = Load[y] : &:r2849_3, m2846_8
# 2849| r2849_5(bool) = CompareLT : r2849_2, r2849_4
# 2849| v2849_6(void) = ConditionalBranch : r2849_5
#-----| True -> Block 3
# 2851| Block 3
# 2851| r2851_1(glval<short>) = VariableAddress[x] :
# 2851| r2851_2(short) = Load[x] : &:r2851_1, m2846_6
# 2851| r2851_3(int) = Constant[2] :
# 2851| r2851_4(bool) = CompareNE : r2851_2, r2851_3
# 2851| v2851_5(void) = ConditionalBranch : r2851_4
#-----| True -> Block 4
# 2853| Block 4
# 2853| r2853_1(glval<unsigned int>) = VariableAddress[u] :
# 2853| r2853_2(unsigned int) = Load[u] : &:r2853_1, m2846_10
# 2853| r2853_3(glval<short>) = VariableAddress[x] :
# 2853| r2853_4(short) = Load[x] : &:r2853_3, m2846_6
# 2853| r2853_5(bool) = CompareLT : r2853_2, r2853_4
# 2853| v2853_6(void) = ConditionalBranch : r2853_5
#-----| True -> Block 5
# 2856| Block 5
# 2856| r2856_1(glval<int>) = VariableAddress[shadowed] :
# 2856| r2856_2(glval<short>) = VariableAddress[x] :
# 2856| r2856_3(short) = Load[x] : &:r2856_2, m2846_6
# 2856| r2856_4(int) = Convert : r2856_3
# 2856| m2856_5(int) = Store[shadowed] : &:r2856_1, r2856_4
# 2857| r2857_1(glval<int>) = VariableAddress[shadowed] :
# 2857| r2857_2(int) = Load[shadowed] : &:r2857_1, m2856_5
# 2857| r2857_3(int) = Constant[0] :
# 2857| r2857_4(bool) = CompareGT : r2857_2, r2857_3
# 2857| v2857_5(void) = ConditionalBranch : r2857_4
#-----| True -> Block 6
# 2859| Block 6
# 2859| r2859_1(glval<short>) = VariableAddress[x] :
# 2859| r2859_2(short) = Load[x] : &:r2859_1, m2846_6
# 2859| r2859_3(int) = Constant[0] :
# 2859| r2859_4(bool) = CompareGT : r2859_2, r2859_3
# 2859| v2859_5(void) = ConditionalBranch : r2859_4
#-----| True -> Block 7
# 2860| Block 7
# 2860| v2860_1(void) = NoOp :
# 2846| v2846_11(void) = ReturnVoid :
# 2846| v2846_12(void) = AliasedUse : m2846_3
# 2846| v2846_13(void) = ExitFunction :
# 2867| void (unnamed namespace)::complex_assertions(int, bool, int)
# 2867| Block 0
# 2867| v2867_1(void) = EnterFunction :
# 2867| m2867_2(unknown) = AliasedDefinition :
# 2867| m2867_3(unknown) = InitializeNonLocal :
# 2867| m2867_4(unknown) = Chi : total:m2867_2, partial:m2867_3
# 2867| r2867_5(glval<int>) = VariableAddress[x] :
# 2867| m2867_6(int) = InitializeParameter[x] : &:r2867_5
# 2867| r2867_7(glval<bool>) = VariableAddress[b] :
# 2867| m2867_8(bool) = InitializeParameter[b] : &:r2867_7
# 2867| r2867_9(glval<int>) = VariableAddress[max] :
# 2867| m2867_10(int) = InitializeParameter[max] : &:r2867_9
# 2868| r2868_1(glval<int>) = VariableAddress[y] :
# 2868| r2868_2(int) = Constant[0] :
# 2868| v2868_3(void) = Convert : r2868_2
# 2868| r2868_4(glval<int>) = VariableAddress[x] :
# 2868| r2868_5(int) = Load[x] : &:r2868_4, m2867_6
# 2868| r2868_6(int) = CopyValue : r2868_5
# 2868| m2868_7(int) = Store[y] : &:r2868_1, r2868_6
# 2869| r2869_1(glval<int>) = VariableAddress[z] :
# 2869| r2869_2(glval<bool>) = VariableAddress[b] :
# 2869| r2869_3(bool) = Load[b] : &:r2869_2, m2867_8
# 2869| v2869_4(void) = ConditionalBranch : r2869_3
#-----| False -> Block 5
#-----| True -> Block 4
# 2867| Block 1
# 2867| v2867_11(void) = AliasedUse : m2867_3
# 2867| v2867_12(void) = ExitFunction :
# 2867| Block 2
# 2867| v2867_13(void) = Unwind :
#-----| Goto -> Block 1
# 2869| Block 3
# 2869| m2869_5(int) = Phi : from 4:m2869_11, from 5:m2869_14
# 2869| r2869_6(glval<int>) = VariableAddress[#temp2869:17] :
# 2869| r2869_7(int) = Load[#temp2869:17] : &:r2869_6, m2869_5
# 2869| m2869_8(int) = Store[z] : &:r2869_1, r2869_7
# 2872| r2872_1(glval<int>) = VariableAddress[#throw2872:13] :
# 2872| r2872_2(int) = Constant[41] :
# 2872| m2872_3(int) = Store[#throw2872:13] : &:r2872_1, r2872_2
# 2872| v2872_4(void) = ThrowValue : &:r2872_1, m2872_3
#-----| C++ Exception -> Block 6
# 2869| Block 4
# 2869| r2869_9(int) = Constant[0] :
# 2869| r2869_10(glval<int>) = VariableAddress[#temp2869:17] :
# 2869| m2869_11(int) = Store[#temp2869:17] : &:r2869_10, r2869_9
#-----| Goto -> Block 3
# 2869| Block 5
# 2869| r2869_12(int) = Constant[1] :
# 2869| r2869_13(glval<int>) = VariableAddress[#temp2869:17] :
# 2869| m2869_14(int) = Store[#temp2869:17] : &:r2869_13, r2869_12
#-----| Goto -> Block 3
# 2873| Block 6
# 2873| v2873_1(void) = CatchByType[int] :
#-----| C++ Exception -> Block 2
#-----| Goto -> Block 7
# 2873| Block 7
# 2873| r2873_2(glval<int>) = VariableAddress[c] :
# 2873| m2873_3(int) = InitializeParameter[c] : &:r2873_2
# 2874| r2874_1(glval<int>) = VariableAddress[c] :
# 2874| r2874_2(int) = Load[c] : &:r2874_1, m2873_3
# 2874| r2874_3(int) = Constant[42] :
# 2874| r2874_4(bool) = CompareLT : r2874_2, r2874_3
# 2874| v2874_5(void) = ConditionalBranch : r2874_4
#-----| True -> Block 8
# 2875| Block 8
# 2875| r2875_1(int) = Constant[0] :
# 2875| v2875_2(void) = Convert : r2875_1
# 2878| r2878_1(int) = Constant[0] :
# 2878| v2878_2(void) = Convert : r2878_1
# 2879| r2879_1(glval<int>) = VariableAddress[shadowed] :
# 2879| m2879_2(int) = Uninitialized[shadowed] : &:r2879_1
# 2882| r2882_1(glval<int>) = VariableAddress[#throw2882:13] :
# 2882| r2882_2(int) = Constant[41] :
# 2882| m2882_3(int) = Store[#throw2882:13] : &:r2882_1, r2882_2
# 2882| v2882_4(void) = ThrowValue : &:r2882_1, m2882_3
#-----| C++ Exception -> Block 9
# 2883| Block 9
# 2883| v2883_1(void) = CatchByType[int] :
#-----| C++ Exception -> Block 2
#-----| Goto -> Block 10
# 2883| Block 10
# 2883| r2883_2(glval<int>) = VariableAddress[shadowed] :
# 2883| m2883_3(int) = InitializeParameter[shadowed] : &:r2883_2
# 2884| r2884_1(int) = Constant[0] :
# 2884| v2884_2(void) = Convert : r2884_1
# 2886| v2886_1(void) = NoOp :
# 2867| v2867_14(void) = ReturnVoid :
#-----| Goto -> Block 1
ir23.cpp:
# 1| bool consteval_1()
# 1| Block 0

View File

@@ -0,0 +1,20 @@
import cpp
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.implementation.raw.internal.TranslatedAssertion
import utils.test.InlineExpectationsTest
module Test implements TestSig {
string getARelevantTag() { result = "var" }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(TranslatedAssertionVarAccess tava, Variable v |
v = tava.getVariable() and
location = tava.getLocation() and
tava.toString() = element and
tag = "var" and
value = v.getLocation().getStartLine().toString() + ":" + v.getName()
)
}
}
import MakeTest<Test>

View File

@@ -2823,4 +2823,67 @@ void vla_sizeof_test5(int len1, size_t len2) {
size_t z = sizeof((*&tmp1)[1]);
}
// Common definitions for assertions in release builds
#define assert(x) ((void)0)
#define __analysis_assume(x)
void test_assert_simple(int x, int y, unsigned u, int shadowed) {
assert(x > 0); // $ var=2830:x
assert(0 < x); // $ var=2830:x
assert(x < y); // $ var=2830:x var=2830:y
__analysis_assume(x != 2); // $ var=2830:x
assert(u < x); // $ var=2830:u var=2830:x
{
int shadowed = x;
assert(shadowed > 0); // no assertion generated since the variable is shadowed
}
}
template<typename T>
void test_assert_in_template(T x, int y, unsigned u) {
assert(x > 0); // $ var=2846:x
assert(0 < x); // $ var=2846:x
assert(x < y); // $ var=2846:x var=2846:y
__analysis_assume(x != 2); // $ var=2846:x
assert(u < x); // $ var=2846:u var=2846:x
{
int shadowed = x;
assert(shadowed > 0); // $ var=2856:shadowed
}
assert(x> 0); // $ var=2846:x
}
template void test_assert_in_template<int>(int, int, unsigned);
template void test_assert_in_template<short>(short, int, unsigned);
namespace {
int shadowed;
void complex_assertions(int x, bool b, int max) {
int y = (assert(x > 0), x); // no assertion generated
int z = b ? (assert(x != 0), 0) : 1; // no assertion generated
try {
throw 41;
} catch (int c) {
assert(c < 42); // $ var=2873:c
assert(shadowed < 42); // no assertion generated
}
assert(shadowed > 0); // no assertion generated
int shadowed;
try {
throw 41;
} catch (int shadowed) {
assert(shadowed < 42); // no assertion generated
}
}
}
// semmle-extractor-options: -std=c++20 --clang

View File

@@ -18880,6 +18880,326 @@ ir.cpp:
# 2821| v2821_9(void) = AliasedUse : ~m?
# 2821| v2821_10(void) = ExitFunction :
# 2830| void test_assert_simple(int, int, unsigned int, int)
# 2830| Block 0
# 2830| v2830_1(void) = EnterFunction :
# 2830| mu2830_2(unknown) = AliasedDefinition :
# 2830| mu2830_3(unknown) = InitializeNonLocal :
# 2830| r2830_4(glval<int>) = VariableAddress[x] :
# 2830| mu2830_5(int) = InitializeParameter[x] : &:r2830_4
# 2830| r2830_6(glval<int>) = VariableAddress[y] :
# 2830| mu2830_7(int) = InitializeParameter[y] : &:r2830_6
# 2830| r2830_8(glval<unsigned int>) = VariableAddress[u] :
# 2830| mu2830_9(unsigned int) = InitializeParameter[u] : &:r2830_8
# 2830| r2830_10(glval<int>) = VariableAddress[shadowed] :
# 2830| mu2830_11(int) = InitializeParameter[shadowed] : &:r2830_10
# 2831| r2831_1(glval<int>) = VariableAddress[x] :
# 2831| r2831_2(int) = Load[x] : &:r2831_1, ~m?
# 2831| r2831_3(int) = Constant[0] :
# 2831| r2831_4(bool) = CompareGT : r2831_2, r2831_3
# 2831| v2831_5(void) = ConditionalBranch : r2831_4
#-----| True -> Block 1
# 2832| Block 1
# 2832| r2832_1(int) = Constant[0] :
# 2832| r2832_2(glval<int>) = VariableAddress[x] :
# 2832| r2832_3(int) = Load[x] : &:r2832_2, ~m?
# 2832| r2832_4(bool) = CompareLT : r2832_1, r2832_3
# 2832| v2832_5(void) = ConditionalBranch : r2832_4
#-----| True -> Block 2
# 2833| Block 2
# 2833| r2833_1(glval<int>) = VariableAddress[x] :
# 2833| r2833_2(int) = Load[x] : &:r2833_1, ~m?
# 2833| r2833_3(glval<int>) = VariableAddress[y] :
# 2833| r2833_4(int) = Load[y] : &:r2833_3, ~m?
# 2833| r2833_5(bool) = CompareLT : r2833_2, r2833_4
# 2833| v2833_6(void) = ConditionalBranch : r2833_5
#-----| True -> Block 3
# 2835| Block 3
# 2835| r2835_1(glval<int>) = VariableAddress[x] :
# 2835| r2835_2(int) = Load[x] : &:r2835_1, ~m?
# 2835| r2835_3(int) = Constant[2] :
# 2835| r2835_4(bool) = CompareNE : r2835_2, r2835_3
# 2835| v2835_5(void) = ConditionalBranch : r2835_4
#-----| True -> Block 4
# 2837| Block 4
# 2837| r2837_1(glval<unsigned int>) = VariableAddress[u] :
# 2837| r2837_2(unsigned int) = Load[u] : &:r2837_1, ~m?
# 2837| r2837_3(glval<int>) = VariableAddress[x] :
# 2837| r2837_4(int) = Load[x] : &:r2837_3, ~m?
# 2837| r2837_5(bool) = CompareLT : r2837_2, r2837_4
# 2837| v2837_6(void) = ConditionalBranch : r2837_5
#-----| True -> Block 5
# 2840| Block 5
# 2840| r2840_1(glval<int>) = VariableAddress[shadowed] :
# 2840| r2840_2(glval<int>) = VariableAddress[x] :
# 2840| r2840_3(int) = Load[x] : &:r2840_2, ~m?
# 2840| mu2840_4(int) = Store[shadowed] : &:r2840_1, r2840_3
# 2841| r2841_1(int) = Constant[0] :
# 2841| v2841_2(void) = Convert : r2841_1
# 2843| v2843_1(void) = NoOp :
# 2830| v2830_12(void) = ReturnVoid :
# 2830| v2830_13(void) = AliasedUse : ~m?
# 2830| v2830_14(void) = ExitFunction :
# 2846| void test_assert_in_template<int>(int, int, unsigned int)
# 2846| Block 0
# 2846| v2846_1(void) = EnterFunction :
# 2846| mu2846_2(unknown) = AliasedDefinition :
# 2846| mu2846_3(unknown) = InitializeNonLocal :
# 2846| r2846_4(glval<int>) = VariableAddress[x] :
# 2846| mu2846_5(int) = InitializeParameter[x] : &:r2846_4
# 2846| r2846_6(glval<int>) = VariableAddress[y] :
# 2846| mu2846_7(int) = InitializeParameter[y] : &:r2846_6
# 2846| r2846_8(glval<unsigned int>) = VariableAddress[u] :
# 2846| mu2846_9(unsigned int) = InitializeParameter[u] : &:r2846_8
# 2847| r2847_1(glval<int>) = VariableAddress[x] :
# 2847| r2847_2(int) = Load[x] : &:r2847_1, ~m?
# 2847| r2847_3(int) = Constant[0] :
# 2847| r2847_4(bool) = CompareGT : r2847_2, r2847_3
# 2847| v2847_5(void) = ConditionalBranch : r2847_4
#-----| True -> Block 1
# 2848| Block 1
# 2848| r2848_1(int) = Constant[0] :
# 2848| r2848_2(glval<int>) = VariableAddress[x] :
# 2848| r2848_3(int) = Load[x] : &:r2848_2, ~m?
# 2848| r2848_4(bool) = CompareLT : r2848_1, r2848_3
# 2848| v2848_5(void) = ConditionalBranch : r2848_4
#-----| True -> Block 2
# 2849| Block 2
# 2849| r2849_1(glval<int>) = VariableAddress[x] :
# 2849| r2849_2(int) = Load[x] : &:r2849_1, ~m?
# 2849| r2849_3(glval<int>) = VariableAddress[y] :
# 2849| r2849_4(int) = Load[y] : &:r2849_3, ~m?
# 2849| r2849_5(bool) = CompareLT : r2849_2, r2849_4
# 2849| v2849_6(void) = ConditionalBranch : r2849_5
#-----| True -> Block 3
# 2851| Block 3
# 2851| r2851_1(glval<int>) = VariableAddress[x] :
# 2851| r2851_2(int) = Load[x] : &:r2851_1, ~m?
# 2851| r2851_3(int) = Constant[2] :
# 2851| r2851_4(bool) = CompareNE : r2851_2, r2851_3
# 2851| v2851_5(void) = ConditionalBranch : r2851_4
#-----| True -> Block 4
# 2853| Block 4
# 2853| r2853_1(glval<unsigned int>) = VariableAddress[u] :
# 2853| r2853_2(unsigned int) = Load[u] : &:r2853_1, ~m?
# 2853| r2853_3(glval<int>) = VariableAddress[x] :
# 2853| r2853_4(int) = Load[x] : &:r2853_3, ~m?
# 2853| r2853_5(bool) = CompareLT : r2853_2, r2853_4
# 2853| v2853_6(void) = ConditionalBranch : r2853_5
#-----| True -> Block 5
# 2856| Block 5
# 2856| r2856_1(glval<int>) = VariableAddress[shadowed] :
# 2856| r2856_2(glval<int>) = VariableAddress[x] :
# 2856| r2856_3(int) = Load[x] : &:r2856_2, ~m?
# 2856| mu2856_4(int) = Store[shadowed] : &:r2856_1, r2856_3
# 2857| r2857_1(glval<int>) = VariableAddress[shadowed] :
# 2857| r2857_2(int) = Load[shadowed] : &:r2857_1, ~m?
# 2857| r2857_3(int) = Constant[0] :
# 2857| r2857_4(bool) = CompareGT : r2857_2, r2857_3
# 2857| v2857_5(void) = ConditionalBranch : r2857_4
#-----| True -> Block 6
# 2859| Block 6
# 2859| r2859_1(glval<int>) = VariableAddress[x] :
# 2859| r2859_2(int) = Load[x] : &:r2859_1, ~m?
# 2859| r2859_3(int) = Constant[0] :
# 2859| r2859_4(bool) = CompareGT : r2859_2, r2859_3
# 2859| v2859_5(void) = ConditionalBranch : r2859_4
#-----| True -> Block 7
# 2860| Block 7
# 2860| v2860_1(void) = NoOp :
# 2846| v2846_10(void) = ReturnVoid :
# 2846| v2846_11(void) = AliasedUse : ~m?
# 2846| v2846_12(void) = ExitFunction :
# 2846| void test_assert_in_template<short>(short, int, unsigned int)
# 2846| Block 0
# 2846| v2846_1(void) = EnterFunction :
# 2846| mu2846_2(unknown) = AliasedDefinition :
# 2846| mu2846_3(unknown) = InitializeNonLocal :
# 2846| r2846_4(glval<short>) = VariableAddress[x] :
# 2846| mu2846_5(short) = InitializeParameter[x] : &:r2846_4
# 2846| r2846_6(glval<int>) = VariableAddress[y] :
# 2846| mu2846_7(int) = InitializeParameter[y] : &:r2846_6
# 2846| r2846_8(glval<unsigned int>) = VariableAddress[u] :
# 2846| mu2846_9(unsigned int) = InitializeParameter[u] : &:r2846_8
# 2847| r2847_1(glval<short>) = VariableAddress[x] :
# 2847| r2847_2(short) = Load[x] : &:r2847_1, ~m?
# 2847| r2847_3(int) = Constant[0] :
# 2847| r2847_4(bool) = CompareGT : r2847_2, r2847_3
# 2847| v2847_5(void) = ConditionalBranch : r2847_4
#-----| True -> Block 1
# 2848| Block 1
# 2848| r2848_1(int) = Constant[0] :
# 2848| r2848_2(glval<short>) = VariableAddress[x] :
# 2848| r2848_3(short) = Load[x] : &:r2848_2, ~m?
# 2848| r2848_4(bool) = CompareLT : r2848_1, r2848_3
# 2848| v2848_5(void) = ConditionalBranch : r2848_4
#-----| True -> Block 2
# 2849| Block 2
# 2849| r2849_1(glval<short>) = VariableAddress[x] :
# 2849| r2849_2(short) = Load[x] : &:r2849_1, ~m?
# 2849| r2849_3(glval<int>) = VariableAddress[y] :
# 2849| r2849_4(int) = Load[y] : &:r2849_3, ~m?
# 2849| r2849_5(bool) = CompareLT : r2849_2, r2849_4
# 2849| v2849_6(void) = ConditionalBranch : r2849_5
#-----| True -> Block 3
# 2851| Block 3
# 2851| r2851_1(glval<short>) = VariableAddress[x] :
# 2851| r2851_2(short) = Load[x] : &:r2851_1, ~m?
# 2851| r2851_3(int) = Constant[2] :
# 2851| r2851_4(bool) = CompareNE : r2851_2, r2851_3
# 2851| v2851_5(void) = ConditionalBranch : r2851_4
#-----| True -> Block 4
# 2853| Block 4
# 2853| r2853_1(glval<unsigned int>) = VariableAddress[u] :
# 2853| r2853_2(unsigned int) = Load[u] : &:r2853_1, ~m?
# 2853| r2853_3(glval<short>) = VariableAddress[x] :
# 2853| r2853_4(short) = Load[x] : &:r2853_3, ~m?
# 2853| r2853_5(bool) = CompareLT : r2853_2, r2853_4
# 2853| v2853_6(void) = ConditionalBranch : r2853_5
#-----| True -> Block 5
# 2856| Block 5
# 2856| r2856_1(glval<int>) = VariableAddress[shadowed] :
# 2856| r2856_2(glval<short>) = VariableAddress[x] :
# 2856| r2856_3(short) = Load[x] : &:r2856_2, ~m?
# 2856| r2856_4(int) = Convert : r2856_3
# 2856| mu2856_5(int) = Store[shadowed] : &:r2856_1, r2856_4
# 2857| r2857_1(glval<int>) = VariableAddress[shadowed] :
# 2857| r2857_2(int) = Load[shadowed] : &:r2857_1, ~m?
# 2857| r2857_3(int) = Constant[0] :
# 2857| r2857_4(bool) = CompareGT : r2857_2, r2857_3
# 2857| v2857_5(void) = ConditionalBranch : r2857_4
#-----| True -> Block 6
# 2859| Block 6
# 2859| r2859_1(glval<short>) = VariableAddress[x] :
# 2859| r2859_2(short) = Load[x] : &:r2859_1, ~m?
# 2859| r2859_3(int) = Constant[0] :
# 2859| r2859_4(bool) = CompareGT : r2859_2, r2859_3
# 2859| v2859_5(void) = ConditionalBranch : r2859_4
#-----| True -> Block 7
# 2860| Block 7
# 2860| v2860_1(void) = NoOp :
# 2846| v2846_10(void) = ReturnVoid :
# 2846| v2846_11(void) = AliasedUse : ~m?
# 2846| v2846_12(void) = ExitFunction :
# 2867| void (unnamed namespace)::complex_assertions(int, bool, int)
# 2867| Block 0
# 2867| v2867_1(void) = EnterFunction :
# 2867| mu2867_2(unknown) = AliasedDefinition :
# 2867| mu2867_3(unknown) = InitializeNonLocal :
# 2867| r2867_4(glval<int>) = VariableAddress[x] :
# 2867| mu2867_5(int) = InitializeParameter[x] : &:r2867_4
# 2867| r2867_6(glval<bool>) = VariableAddress[b] :
# 2867| mu2867_7(bool) = InitializeParameter[b] : &:r2867_6
# 2867| r2867_8(glval<int>) = VariableAddress[max] :
# 2867| mu2867_9(int) = InitializeParameter[max] : &:r2867_8
# 2868| r2868_1(glval<int>) = VariableAddress[y] :
# 2868| r2868_2(int) = Constant[0] :
# 2868| v2868_3(void) = Convert : r2868_2
# 2868| r2868_4(glval<int>) = VariableAddress[x] :
# 2868| r2868_5(int) = Load[x] : &:r2868_4, ~m?
# 2868| r2868_6(int) = CopyValue : r2868_5
# 2868| mu2868_7(int) = Store[y] : &:r2868_1, r2868_6
# 2869| r2869_1(glval<int>) = VariableAddress[z] :
# 2869| r2869_2(glval<bool>) = VariableAddress[b] :
# 2869| r2869_3(bool) = Load[b] : &:r2869_2, ~m?
# 2869| v2869_4(void) = ConditionalBranch : r2869_3
#-----| False -> Block 5
#-----| True -> Block 4
# 2867| Block 1
# 2867| v2867_10(void) = AliasedUse : ~m?
# 2867| v2867_11(void) = ExitFunction :
# 2867| Block 2
# 2867| v2867_12(void) = Unwind :
#-----| Goto -> Block 1
# 2869| Block 3
# 2869| r2869_5(glval<int>) = VariableAddress[#temp2869:17] :
# 2869| r2869_6(int) = Load[#temp2869:17] : &:r2869_5, ~m?
# 2869| mu2869_7(int) = Store[z] : &:r2869_1, r2869_6
# 2872| r2872_1(glval<int>) = VariableAddress[#throw2872:13] :
# 2872| r2872_2(int) = Constant[41] :
# 2872| mu2872_3(int) = Store[#throw2872:13] : &:r2872_1, r2872_2
# 2872| v2872_4(void) = ThrowValue : &:r2872_1, ~m?
#-----| C++ Exception -> Block 6
# 2869| Block 4
# 2869| r2869_8(int) = Constant[0] :
# 2869| r2869_9(glval<int>) = VariableAddress[#temp2869:17] :
# 2869| mu2869_10(int) = Store[#temp2869:17] : &:r2869_9, r2869_8
#-----| Goto -> Block 3
# 2869| Block 5
# 2869| r2869_11(int) = Constant[1] :
# 2869| r2869_12(glval<int>) = VariableAddress[#temp2869:17] :
# 2869| mu2869_13(int) = Store[#temp2869:17] : &:r2869_12, r2869_11
#-----| Goto -> Block 3
# 2873| Block 6
# 2873| v2873_1(void) = CatchByType[int] :
#-----| C++ Exception -> Block 2
#-----| Goto -> Block 7
# 2873| Block 7
# 2873| r2873_2(glval<int>) = VariableAddress[c] :
# 2873| mu2873_3(int) = InitializeParameter[c] : &:r2873_2
# 2874| r2874_1(glval<int>) = VariableAddress[c] :
# 2874| r2874_2(int) = Load[c] : &:r2874_1, ~m?
# 2874| r2874_3(int) = Constant[42] :
# 2874| r2874_4(bool) = CompareLT : r2874_2, r2874_3
# 2874| v2874_5(void) = ConditionalBranch : r2874_4
#-----| True -> Block 8
# 2875| Block 8
# 2875| r2875_1(int) = Constant[0] :
# 2875| v2875_2(void) = Convert : r2875_1
# 2878| r2878_1(int) = Constant[0] :
# 2878| v2878_2(void) = Convert : r2878_1
# 2879| r2879_1(glval<int>) = VariableAddress[shadowed] :
# 2879| mu2879_2(int) = Uninitialized[shadowed] : &:r2879_1
# 2882| r2882_1(glval<int>) = VariableAddress[#throw2882:13] :
# 2882| r2882_2(int) = Constant[41] :
# 2882| mu2882_3(int) = Store[#throw2882:13] : &:r2882_1, r2882_2
# 2882| v2882_4(void) = ThrowValue : &:r2882_1, ~m?
#-----| C++ Exception -> Block 9
# 2883| Block 9
# 2883| v2883_1(void) = CatchByType[int] :
#-----| C++ Exception -> Block 2
#-----| Goto -> Block 10
# 2883| Block 10
# 2883| r2883_2(glval<int>) = VariableAddress[shadowed] :
# 2883| mu2883_3(int) = InitializeParameter[shadowed] : &:r2883_2
# 2884| r2884_1(int) = Constant[0] :
# 2884| v2884_2(void) = Convert : r2884_1
# 2886| v2886_1(void) = NoOp :
# 2867| v2867_13(void) = ReturnVoid :
#-----| Goto -> Block 1
ir23.cpp:
# 1| bool consteval_1()
# 1| Block 0

View File

@@ -158,6 +158,10 @@ namespace Semmle.Autobuild.CSharp.Tests
bool IBuildActions.IsMacOs() => IsMacOs;
public bool IsLinux { get; set; }
bool IBuildActions.IsLinux() => IsLinux;
public bool IsRunningOnAppleSilicon { get; set; }
bool IBuildActions.IsRunningOnAppleSilicon() => IsRunningOnAppleSilicon;

View File

@@ -146,6 +146,10 @@ namespace Semmle.Autobuild.Cpp.Tests
bool IBuildActions.IsMacOs() => IsMacOs;
public bool IsLinux { get; set; }
bool IBuildActions.IsLinux() => IsLinux;
public bool IsRunningOnAppleSilicon { get; set; }
bool IBuildActions.IsRunningOnAppleSilicon() => IsRunningOnAppleSilicon;

View File

@@ -814,6 +814,43 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
private (HashSet<string> explicitFeeds, HashSet<string> allFeeds) GetAllFeeds()
{
var nugetConfigs = fileProvider.NugetConfigs;
// On systems with case-sensitive file systems (for simplicity, we assume that is Linux), the
// filenames of NuGet configuration files must be named correctly. For compatibility with projects
// that are typically built on Windows or macOS where this doesn't matter, we accept all variants
// of `nuget.config` ourselves. However, `dotnet` does not. If we detect that incorrectly-named
// files are present, we emit a diagnostic to warn the user.
if (SystemBuildActions.Instance.IsLinux())
{
string[] acceptedNugetConfigNames = ["nuget.config", "NuGet.config", "NuGet.Config"];
var invalidNugetConfigs = nugetConfigs
.Where(path => !acceptedNugetConfigNames.Contains(Path.GetFileName(path)));
if (invalidNugetConfigs.Count() > 0)
{
this.logger.LogWarning(string.Format(
"Found incorrectly named NuGet configuration files: {0}",
string.Join(", ", invalidNugetConfigs)
));
this.diagnosticsWriter.AddEntry(new DiagnosticMessage(
Language.CSharp,
"buildless/case-sensitive-nuget-config",
"Found NuGet configuration files which are not correctly named",
visibility: new DiagnosticMessage.TspVisibility(statusPage: true, cliSummaryTable: true, telemetry: true),
markdownMessage: string.Format(
"On platforms with case-sensitive file systems, NuGet only accepts files with one of the following names: {0}.\n\n" +
"CodeQL found the following files while performing an analysis on a platform with a case-sensitive file system:\n\n" +
"{1}\n\n" +
"To avoid unexpected results, rename these files to match the casing of one of the accepted filenames.",
string.Join(", ", acceptedNugetConfigNames),
string.Join("\n", invalidNugetConfigs.Select(path => string.Format("- `{0}`", path)))
),
severity: DiagnosticMessage.TspSeverity.Warning
));
}
}
// Find feeds that are explicitly configured in the NuGet configuration files that we found.
var explicitFeeds = nugetConfigs
.SelectMany(config => GetFeeds(() => dotnet.GetNugetFeeds(config)))
.ToHashSet();
@@ -849,6 +886,14 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
.Where(folder => folder != null)
.SelectMany(folder => GetFeeds(() => dotnet.GetNugetFeedsFromFolder(folder!)))
.ToHashSet();
// If we have discovered any explicit feeds, then we also expect these to be in the set of all feeds.
// Normally, it is a safe assumption to make that `GetNugetFeedsFromFolder` will include the feeds configured
// in a NuGet configuration file in the given directory. There is one exception: on a system with case-sensitive
// file systems, we may discover a configuration file such as `Nuget.Config` which is not recognised by `dotnet nuget`.
// In that case, our call to `GetNugetFeeds` will retrieve the feeds from that file (because it is accepted when
// provided explicitly as `--configfile` argument), but the call to `GetNugetFeedsFromFolder` will not.
allFeeds.UnionWith(explicitFeeds);
}
else
{

View File

@@ -119,6 +119,12 @@ namespace Semmle.Util
/// <returns>True if we are running on macOS.</returns>
bool IsMacOs();
/// <summary>
/// Gets a value indicating whether we are running on Linux.
/// </summary>
/// <returns>True if we are running on Linux.</returns>
bool IsLinux();
/// <summary>
/// Gets a value indicating whether we are running on Apple Silicon.
/// </summary>
@@ -246,6 +252,8 @@ namespace Semmle.Util
bool IBuildActions.IsMacOs() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
bool IBuildActions.IsLinux() => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
bool IBuildActions.IsRunningOnAppleSilicon()
{
var thisBuildActions = (IBuildActions)this;

View File

@@ -1,3 +1,7 @@
## 1.7.58
No user-facing changes.
## 1.7.57
No user-facing changes.

View File

@@ -0,0 +1,3 @@
## 1.7.58
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.57
lastReleaseVersion: 1.7.58

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