Compare commits

...

539 Commits

Author SHA1 Message Date
Michael B. Gale
fb67f93a86 Merge pull request #21330 from github/release-prep/2.24.2
Release preparation for version 2.24.2
2026-02-16 15:00:27 +00:00
github-actions[bot]
ef04f927fb Release preparation for version 2.24.2 2026-02-16 13:29:25 +00:00
Owen Mansel-Chan
7742a5667f Merge pull request #21326 from owen-mc/java/log-injection-regex-match
Java: Recognise `@Pattern` annotation as sanitizer for log injection
2026-02-16 12:14:28 +00:00
Owen Mansel-Chan
cf73d96c9d Update test results (remove SPURIOUS annotations) 2026-02-16 12:03:02 +00:00
Owen Mansel-Chan
597be6a1c0 Add change note 2026-02-16 12:01:15 +00:00
Owen Mansel-Chan
94f1d94a2b Rename MethodCall ma to mc 2026-02-16 12:01:14 +00:00
Owen Mansel-Chan
9fc95f5171 Expand log injection sanitizers to annotation regex matches 2026-02-16 12:01:13 +00:00
Owen Mansel-Chan
924bb92d91 Expand log injection sanitizer guards to non-annotation regex matches 2026-02-16 12:01:11 +00:00
Owen Mansel-Chan
60e58f8219 Refactor logInjectionGuard part 2 2026-02-16 12:01:10 +00:00
Owen Mansel-Chan
6c0c1d558e Refactor logInjectionGuard part 1 2026-02-16 12:01:08 +00:00
Owen Mansel-Chan
146fc7a8c0 Add failing log injection test for @Pattern validation 2026-02-16 12:01:07 +00:00
Jeroen Ketema
7d2b40c657 Merge pull request #21313 from MathiasVP/range-analysis-lower-bound-and-measure-enums
C++: Measure bounds for `Enum` constants and reduce `getBoundsLimit`
2026-02-16 11:50:38 +01:00
Mathias Vorreiter Pedersen
5ccd61ac97 C++: Respond to review comments. 2026-02-16 09:49:31 +00:00
Mathias Vorreiter Pedersen
bfbb2eef6c C++: Add a test showing that we infer a lower and upper bound for parameters of enum types. 2026-02-16 09:38:15 +00:00
Mathias Vorreiter Pedersen
84be8517bb Update cpp/ql/lib/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-16 09:30:56 +00:00
Tom Hvitved
149f3ed5b6 Merge pull request #21301 from hvitved/rust/type-inference-trait-call-perf
Rust: Speedup type inference for `Trait::function()` calls
2026-02-16 10:20:50 +01:00
Owen Mansel-Chan
47a9f87d9b Merge pull request #21310 from owen-mc/java/regex-execution
Java: Add RegexMatch concept and recognise `@Pattern` annotation as sanitizer
2026-02-16 09:11:47 +00:00
Simon Friis Vindum
6f609a5ed6 Merge pull request #21316 from paldepind/ruby/binary-of-at-start-of-line
Ruby: Add test cases for binary operator at start of line
2026-02-16 09:49:48 +01:00
Owen Mansel-Chan
16ddb5658f Small refactor for stylistic consistency 2026-02-15 14:39:23 +00:00
Owen Mansel-Chan
d6b71a346e Extend RegexMatch framework to allow for MatcherMatchesCall edge case 2026-02-15 14:39:21 +00:00
Owen Mansel-Chan
8f8f4c2d52 Fix Matcher.matches edge case 2026-02-14 00:28:37 +00:00
Owen Mansel-Chan
90befa0c00 Add failing test for Matcher.matches() edge case 2026-02-14 00:28:34 +00:00
Owen Mansel-Chan
ca4c988e97 Remove redundant variable 2026-02-13 22:58:09 +00:00
Owen Mansel-Chan
2e0f244376 Improve QLDoc on RegexMatch.getName() 2026-02-13 22:55:01 +00:00
Owen Mansel-Chan
c7099584b4 Put imports implementing abstract classes in private module 2026-02-13 22:51:53 +00:00
Owen Mansel-Chan
3c161f9c93 Make contract of RegexMatch clear 2026-02-13 22:47:44 +00:00
Owen Mansel-Chan
1fefa989d7 Rename RegexMatch and only include expressions 2026-02-13 22:45:48 +00:00
Owen Mansel-Chan
953ff9f0d0 PatternAnnotation.getString() should only be field reads 2026-02-13 22:41:20 +00:00
Owen Mansel-Chan
106254b220 Improve QLDocs 2026-02-13 22:40:36 +00:00
Owen Mansel-Chan
5bdf550317 Fix QLDocs 2026-02-12 16:57:14 +00:00
Owen Mansel-Chan
c539c2f4fd Add change note 2026-02-12 16:57:12 +00:00
Owen Mansel-Chan
bfe26c1989 Add @Pattern as RegexExecution => SSRF sanitizer 2026-02-12 16:57:11 +00:00
Owen Mansel-Chan
d0999e3abd Add failing test for @Pattern validation 2026-02-12 16:57:04 +00:00
Simon Friis Vindum
bf02e478fd Rust: Comment out tests with parse errors 2026-02-12 14:49:09 +01:00
Taus
7d17454a3b Merge pull request #21138 from github/tausbn/python-prepare-for-overlay-annotations
Prepare dataflow for local annotations
2026-02-12 14:23:45 +01:00
Taus
3e5c2ddeaf Merge pull request #21308 from github/smowton/admin/path-injection-use-autofix-qhelp
Python: use path-injection qhelp variant employed by autofix
2026-02-12 13:17:08 +01:00
Chris Smowton
5f970d9f2f Rewordings per copilot 2026-02-12 12:01:33 +00:00
Simon Friis Vindum
218585b52a Ruby: Add additonal tests with operators at the start of lines 2026-02-12 12:30:43 +01:00
Anders Schack-Mulligen
a945f15987 Merge pull request #21317 from aschackmull/java/deprecate-unreachableblocks
Java: Deprecate UnreachableBlocks.
2026-02-12 11:43:37 +01:00
Anders Schack-Mulligen
5c53677051 Java: Deprecate UnreachableBlocks. 2026-02-12 11:06:34 +01:00
Mathias Vorreiter Pedersen
2dc91a56eb C++: Lower the treshold for max number of bounds to 2^29. 2026-02-12 09:44:20 +00:00
Mathias Vorreiter Pedersen
6dd6bddff3 C++: Add more terms to make range analysis test timeout. 2026-02-12 09:44:17 +00:00
Mathias Vorreiter Pedersen
a4dd4f91d4 C++: Also compute type bounds for accesses of an enum type. 2026-02-12 09:44:14 +00:00
Mathias Vorreiter Pedersen
90a16cfaee Merge pull request #21314 from MathiasVP/remove-tc
C++: Remove redundant transitive closure
2026-02-12 09:21:56 +00:00
Simon Friis Vindum
a27d20dbcd Rust: Add test cases for binary operator at start of line 2026-02-12 09:31:59 +01:00
Michael Nebel
76ed386246 Merge pull request #21315 from github/workflow/coverage/update
Update CSV framework coverage reports
2026-02-12 08:29:25 +01:00
github-actions[bot]
fea07ebfcb Add changed framework coverage reports 2026-02-12 00:32:08 +00:00
Mathias Vorreiter Pedersen
9596b7b921 C++: No need to compute this TC. 2026-02-11 20:18:03 +00:00
Mathias Vorreiter Pedersen
b14ece72be C++: Add range analysis test demonstrating missing measuring bounds. 2026-02-11 16:58:18 +00:00
Owen Mansel-Chan
6a8204d28c "dataflow" -> "data flow" in QLDoc 2026-02-11 13:41:14 +00:00
Owen Mansel-Chan
1ee5728311 Add missing QLDoc 2026-02-11 13:40:20 +00:00
Owen Mansel-Chan
a22fd39230 Use RegexExecution in sanitizer definitions (expands scope) 2026-02-11 13:09:48 +00:00
Owen Mansel-Chan
fa3fba4a00 Use new regex-related classes (no functional change) 2026-02-11 13:09:46 +00:00
Owen Mansel-Chan
44eeee5757 Add and improve classes for regex-related methods 2026-02-11 13:09:45 +00:00
Owen Mansel-Chan
e6dbd525c3 Add RegexExecution in Concepts.qll 2026-02-11 13:09:42 +00:00
Simon Friis Vindum
522e4d64de Merge pull request #21273 from paldepind/rust/tp-assoc
Rust: Implement support for associated types accessed on type parameters
2026-02-11 13:39:55 +01:00
Chris Smowton
bed1ec8981 Enhance path validation recommendations
Expanded recommendations for validating user input when constructing file paths, including normalization and using allowlists.
2026-02-11 12:10:08 +00:00
Simon Friis Vindum
6c67475352 Rust: Minor tweaks in type inference 2026-02-11 12:32:54 +01:00
Simon Friis Vindum
287a8717a8 Rust: Apply suggestions from code review
Co-authored-by: Tom Hvitved <hvitved@github.com>
2026-02-11 12:19:22 +01:00
Philip Ginsbach-Chen
9ed22610a3 Merge pull request #21306 from github/ginsbach/avoid-nontrivially-shadowing-toString
Avoid non-trivially shadowing `string.toString()`
2026-02-11 11:03:07 +00:00
Tom Hvitved
36c3084435 Merge pull request #21305 from hvitved/rust/type-inference-speedup
Rust: Speedup `inferMethodCallTypeSelf`
2026-02-11 11:03:06 +01:00
Tom Hvitved
37af38eed5 Merge pull request #21282 from hvitved/rust/path-resolution/type-inference-expectations
Rust: Distinguish path resolution expectations from type inference expectations
2026-02-11 11:00:28 +01:00
Tom Hvitved
89e9a253eb Rust: Distinguish path resolution expectations from type inference expectations 2026-02-11 10:33:41 +01:00
Simon Friis Vindum
2fa71f0c17 Rust: Add examples with associated type accessed on associated type 2026-02-11 09:10:21 +01:00
Simon Friis Vindum
2b10c8aef3 Rust: Fix gramar in qldoc 2026-02-11 09:09:34 +01:00
Michael Nebel
0ac1bc4c57 Merge pull request #21299 from microsoft/lwsimpkins/csharp-mad-httputility-upstream
Update MaD for System.Web.HttpUtility
2026-02-11 08:47:29 +01:00
Anders Schack-Mulligen
cfa62ae434 Merge pull request #21304 from aschackmull/java/deprecation-followup
Java: Add delayed deprecation annotation.
2026-02-11 08:40:01 +01:00
Owen Mansel-Chan
766dc94444 Merge pull request #21150 from github/jketema/go-1.26
Go: Update to 1.26
2026-02-11 04:37:31 +00:00
Owen Mansel-Chan
542d4631d7 restore ~ in action.yml version 2026-02-10 22:32:36 +00:00
Owen Mansel-Chan
f01d5840b0 Update to 1.26.0 2026-02-10 22:32:33 +00:00
Owen Mansel-Chan
936c4cc79f Fix edge case in MaD validation
If the db contains no pointer types then we were getting spurious model
validation errors.
2026-02-10 22:32:31 +00:00
Owen Mansel-Chan
e1bddd9365 Model newly added functions 2026-02-10 22:32:30 +00:00
Owen Mansel-Chan
22e9c212d6 Add failing tests for newly added functions 2026-02-10 22:32:28 +00:00
Owen Mansel-Chan
26ef33212d Test builtins like standard library 2026-02-10 22:32:27 +00:00
Jeroen Ketema
700543b30b Go: Update supported versions to include 1.26 2026-02-10 22:31:11 +00:00
Jeroen Ketema
22e9b42808 Go: Add change note 2026-02-10 22:31:10 +00:00
Jeroen Ketema
50ed0af9da Go: Bump maxGoVersion to 1.26 2026-02-10 22:31:08 +00:00
Jeroen Ketema
e00e3a87ff Update Go version in tests to 1.26.0 2026-02-10 22:31:00 +00:00
Tom Hvitved
8955fd0bf4 Merge pull request #21303 from hvitved/rust/add-telemetry-tags
Rust: Add `telemtry` tags to queries
2026-02-10 20:13:40 +01:00
Philip Ginsbach
f60d759a65 Avoid non-trivially shadowing string.toString()
Prepare libraries for a possible deprecation warning on shadowing
string.toString().

These instanceof classes were using this.(Type).method() to call
supertype methods, but super.method() is clearer and equivalent
for instanceof supertypes.
2026-02-10 15:46:10 +00:00
Ian Lynagh
00acff293a Merge pull request #21281 from igfoo/igfoo/discarding
C++ overlay: Discarding elements
2026-02-10 15:14:58 +00:00
Tom Hvitved
49f24ca8ec Rust: Avoid using regexpCapture with multiple capture groups 2026-02-10 16:11:49 +01:00
Tom Hvitved
564a3bd444 Rust: Simplify inferMethodCallTypeSelf 2026-02-10 15:30:56 +01:00
Michael Nebel
ece85854cd Merge pull request #21285 from michaelnebel/csharp14/implicittypedlambdaparametermodifiers
C# 14: [TEST ONLY] Simple lambda parameters with modifiers.
2026-02-10 14:16:19 +01:00
Michael Nebel
c15ad31b07 Merge pull request #21220 from michaelnebel/csharp14/extension
C# 14: Support `extension` types.
2026-02-10 14:15:57 +01:00
Anders Schack-Mulligen
5116b0c1e5 Java: Add delayed deprecation annotation. 2026-02-10 14:02:48 +01:00
Michael Nebel
25b836b1b5 C#: Apply suggestions from code review
Co-authored-by: Tom Hvitved <hvitved@github.com>
2026-02-10 13:12:53 +01:00
Owen Mansel-Chan
f2d3bc03aa Merge pull request #21302 from github/mbg/go/bump-to-1.25.7
Go: Bump toolchain to `1.25.7`
2026-02-10 10:33:50 +00:00
Tom Hvitved
55e5bc4970 Rust: Add telemtry tags to queries 2026-02-10 11:25:42 +01:00
Michael B. Gale
518fb44a92 Go: Bump toolchain to 1.25.7 2026-02-10 10:01:38 +00:00
Tom Hvitved
5634395a32 Rust: Speedup type inference for Trait::function() calls 2026-02-10 10:50:59 +01:00
Michael B. Gale
eee4014e94 Merge pull request #21300 from github/dependabot/go_modules/go/extractor/extractor-dependencies-393b62c927
Bump the extractor-dependencies group in /go/extractor with 2 updates
2026-02-10 09:46:56 +00:00
Simon Friis Vindum
a033057d90 Rust: Fix a bad join 2026-02-10 09:54:01 +01:00
Simon Friis Vindum
624ee1898a Rust: Implement support for associated types accessed on type parameters 2026-02-10 09:53:56 +01:00
Simon Friis Vindum
0cd5366034 Rust: Add type inference test for associated type acces on a type parameter of an impl block 2026-02-10 09:51:56 +01:00
Simon Friis Vindum
78c262ca63 Merge pull request #21297 from hvitved/rust/type-inference-fix-bug
Rust: Fix bug in `inferMethodCallTypeSelf`
2026-02-10 09:51:12 +01:00
Tom Hvitved
c3ac20267a Merge pull request #21217 from hvitved/rust/type-inference-perf
Rust: Rework call disambiguation logic
2026-02-10 08:52:01 +01:00
dependabot[bot]
e172cb3f7a Bump the extractor-dependencies group in /go/extractor with 2 updates
Bumps the extractor-dependencies group in /go/extractor with 2 updates: [golang.org/x/mod](https://github.com/golang/mod) and [golang.org/x/tools](https://github.com/golang/tools).


Updates `golang.org/x/mod` from 0.32.0 to 0.33.0
- [Commits](https://github.com/golang/mod/compare/v0.32.0...v0.33.0)

Updates `golang.org/x/tools` from 0.41.0 to 0.42.0
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.41.0...v0.42.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-version: 0.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: extractor-dependencies
- dependency-name: golang.org/x/tools
  dependency-version: 0.42.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: extractor-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-10 03:15:54 +00:00
Lindsay Simpkins
677949e409 Fix typo in change note
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-09 17:16:10 -05:00
Lindsay Simpkins
fe10fb37e9 add changenote 2026-02-09 16:48:08 -05:00
Lindsay Simpkins
ba3fc0a769 update csharp MaD for System.Web.HttpUtility for tainted URIs 2026-02-09 16:48:05 -05:00
Tom Hvitved
6611978368 Update rust/ql/lib/codeql/rust/internal/typeinference/DerefChain.qll
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-09 19:38:49 +01:00
Tom Hvitved
16539b4667 Address review comments 2026-02-09 19:30:58 +01:00
Ian Lynagh
6235edaa21 C++: Update stats 2026-02-09 18:01:02 +00:00
Ian Lynagh
9a5128f915 C++: Add up/downgrade scripts 2026-02-09 18:01:01 +00:00
Ian Lynagh
c5f6820b5d C++ overlay: Add trap_filename, source_file_uses_trap, in_trap 2026-02-09 18:01:01 +00:00
yoff
5ad42f8bcc Merge pull request #20563 from microsoft/azure_python_sdk_url_summary_upstream
Azure python sdk url summary upstream
2026-02-09 18:34:36 +01:00
Michael Nebel
bee1718469 QL4QL: Allow Impl classes to implement getAPrimaryQLClass with non Impl suffix. 2026-02-09 16:53:43 +01:00
Michael Nebel
3e914f7ff1 C#: Add DB downgrade script. 2026-02-09 16:24:19 +01:00
Michael Nebel
42d2de848d C#: Add DB upgrade script. 2026-02-09 16:24:00 +01:00
Ian Lynagh
b5e3168032 Merge pull request #21286 from github/andersfugmann/kotlin_2.3.10-no-artifacts
Kotlin: Support Kotlin 2.3.10
2026-02-09 13:26:40 +00:00
Tom Hvitved
109d802607 Rust: Fix bug in inferMethodCallTypeSelf 2026-02-09 14:15:05 +01:00
Michael B. Gale
71e8730c63 Merge pull request #21263 from github/mbg/csharp/registry-diagnostic
C#: Add diagnostic for private registry usage
2026-02-09 12:58:43 +00:00
Michael Nebel
eff9f99f44 C#: Update test expected output. 2026-02-09 13:30:14 +01:00
Michael Nebel
d9fea156f6 C#: Update MaD models for extension members. 2026-02-09 13:28:11 +01:00
Michael Nebel
bcdbd6e283 C#: Use the fully qualified name for the extension type when printing extension types. 2026-02-09 13:27:32 +01:00
Michael Nebel
fe94b3b68b C#: Address review comments. 2026-02-09 11:46:53 +01:00
Owen Mansel-Chan
90401b3ad3 Merge pull request #21254 from owen-mc/go/astnode-get-enclosing-block
Go: Add `AstNode.getEnclosingBlock()`
2026-02-06 22:23:15 +00:00
Jon Janego
d0bd8459a1 Merge pull request #21291 from github/codeql-spark-run-21760759512
Update changelog documentation site
2026-02-06 12:28:56 -06:00
Jon Janego
1c43ceae95 Merge branch 'main' into codeql-spark-run-21760759512 2026-02-06 12:16:31 -06:00
Jon Janego
5bf2d9442e Fix formatting in changelog for Go path injection query 2026-02-06 12:14:03 -06:00
Jon Janego
c40d784a4d Update codeql-cli-2.23.1.rst 2026-02-06 12:13:34 -06:00
Jon Janego
bf6568b928 Fix formatting for Kotlin version support note 2026-02-06 12:12:55 -06:00
Jon Janego
79ad064a93 Fix formatting in Kotlin version support note 2026-02-06 12:12:16 -06:00
Jon Janego
552976d057 Update codeql-cli-2.19.1.rst 2026-02-06 12:11:49 -06:00
github-actions[bot]
353cd31ce6 update codeql documentation 2026-02-06 18:09:49 +00:00
Paolo Tranquilli
48db24d184 Merge pull request #21287 from github/redsun82/fix-rust-deps-patching
Bazel: fix Rust deps patching for semver build metadata
2026-02-06 17:17:24 +01:00
REDMOND\brodes
8459eec239 Moving the SsrfSink concept into Concepts.qll, and renaming to HttpClientRequestFromModel as suggested in PR review. 2026-02-06 09:26:49 -05:00
Anders Fugmann
c5179e40c6 Kotlin: Add change note for supporting 2.3.10 2026-02-06 14:59:34 +01:00
github-actions[bot]
38830ddc5c Bazel: fix Rust deps patching for semver build metadata
Handle crate versions containing `+` build metadata (e.g., `0.9.11+spec-1.1.0`).
Bazel repo names use `-` instead of `+`, so the generated labels need patching
to reference the correct repo name.

Also adds documentation for both patching issues handled by patch_defs.py.
2026-02-06 14:58:34 +01:00
Anders Fugmann
d5827b5cca Kotlin: Support Kotlin 2.3.10 2026-02-06 14:54:08 +01:00
Michael Nebel
6c355a1bf8 C#: Update test expected output. 2026-02-06 14:38:27 +01:00
Michael Nebel
e550d4937c C#: Update parameter modifiers test to include lambda expression from the new test file. 2026-02-06 14:37:50 +01:00
Michael Nebel
62a6b5985d C#: Add test cases for lambda parameter modifiers. 2026-02-06 14:37:11 +01:00
Mathias Vorreiter Pedersen
2c05624088 Merge pull request #21280 from MathiasVP/make-getChildCount-more-robust
C++: Make 'getChildCount' more robust by counting indices instead of elements
2026-02-06 12:19:20 +00:00
Ben Rodes
ac1987f264 Update python/ql/lib/change-notes/2025-09-30-azure_ssrf_models.md
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2026-02-05 15:44:44 -05:00
Mathias Vorreiter Pedersen
d57a42a7f7 C++: Make 'getChildCount' more robust by counting indexes instead of 'TranslatedDeclarationEntry's. 2026-02-05 20:23:45 +00:00
Tom Hvitved
32aaac27ec Rust: Add type inference regression test 2026-02-05 17:29:42 +01:00
Tom Hvitved
2dc7576232 Rust: Rework call disambiguation logic 2026-02-05 17:29:40 +01:00
Taus
5adc9f8ff0 Merge pull request #21274 from github/tausbn/python-fix-parsing-of-format-specifiers
Python: Fix syntax error when `=` is used as a format fill character
2026-02-05 16:37:42 +01:00
Michael Nebel
02e4a8b6f7 C#: Add change-note. 2026-02-05 15:52:43 +01:00
Michael Nebel
bd3e4d3d7e C#: Add MaD tests for extensions. 2026-02-05 15:38:29 +01:00
Michael Nebel
4b6a53b577 C#: Add extension data flow test. 2026-02-05 15:38:27 +01:00
Michael Nebel
6cbe000d51 C#: Add PrintAst test for extensions. 2026-02-05 15:38:25 +01:00
Michael Nebel
c040daab9c C#: Add extensions test. 2026-02-05 15:38:20 +01:00
Michael Nebel
849823eff6 C#: Add dispatch logic for calling extensions accessors as methods. 2026-02-05 15:38:16 +01:00
Michael Nebel
e831c80a23 C#: Replace extension parameter access with the corresponding synthetic parameter. 2026-02-05 15:38:14 +01:00
Michael Nebel
5e02a86542 C#: Add extension call classes. 2026-02-05 15:38:12 +01:00
Michael Nebel
b9f36f37b6 C#: Add extension callable and accessor classes. 2026-02-05 15:38:09 +01:00
Michael Nebel
9a4a6cfcb8 C#: Add ExtensionType to the QL library. 2026-02-05 15:38:07 +01:00
Michael Nebel
edfdc9812f C#: Extract extension types and members. Replacing invocations to static generated methods with invocation of extension type member. 2026-02-05 15:38:05 +01:00
Michael Nebel
ab505e3281 C#: Add class for making synthetic parameter entities. 2026-02-05 15:38:02 +01:00
Taus
8c27437628 Python: Bump extractor version and add change note 2026-02-05 13:50:54 +00:00
Taus
12ee93042b Python: Add tests 2026-02-05 13:47:24 +00:00
Taus
bac356c9a1 Python: Regenerate parser files 2026-02-05 13:46:59 +00:00
Taus
68c1a3d389 Python: Fix syntax error when = is used as a format fill character
An example (provided by @redsun82) is the string `f"{x:=^20}"`. Parsing
this (with unnamed nodes shown) illustrates the problem:

```
module [0, 0] - [2, 0]
  expression_statement [0, 0] - [0, 11]
    string [0, 0] - [0, 11]
      string_start [0, 0] - [0, 2]
      interpolation [0, 2] - [0, 10]
        "{" [0, 2] - [0, 3]
        expression: named_expression [0, 3] - [0, 9]
          name: identifier [0, 3] - [0, 4]
          ":=" [0, 4] - [0, 6]
          ERROR [0, 6] - [0, 7]
            "^" [0, 6] - [0, 7]
          value: integer [0, 7] - [0, 9]
        "}" [0, 9] - [0, 10]
      string_end [0, 10] - [0, 11]
```
Observe that we've managed to combine the format specifier token `:` and
the fill character `=` in a single token (which doesn't match the `:` we
expect in the grammar rule), and hence we get a syntax error.

If we change the `=` to some other character (e.g. a `-`), we instead
get

```
module [0, 0] - [2, 0]
  expression_statement [0, 0] - [0, 11]
    string [0, 0] - [0, 11]
      string_start [0, 0] - [0, 2]
      interpolation [0, 2] - [0, 10]
        "{" [0, 2] - [0, 3]
        expression: identifier [0, 3] - [0, 4]
        format_specifier: format_specifier [0, 4] - [0, 9]
          ":" [0, 4] - [0, 5]
        "}" [0, 9] - [0, 10]
      string_end [0, 10] - [0, 11]
```
and in particular no syntax error.

To fix this, we want to ensure that the `:` is lexed on its own, and the
`token(prec(1, ...))` construction can be used to do exactly this.

Finally, you may wonder why `=` is special here. I think what's going on
is that the lexer knows that `:=` is a token on its own (because it's
used in the walrus operator), and so it greedily consumes the following
`=` with this in mind.
2026-02-05 13:45:54 +00:00
Tom Hvitved
2764d697d2 Rust: Merge Input1 and Input2 modules 2026-02-05 14:29:46 +01:00
Tom Hvitved
c62d95ac9d Rust: More type inference tests 2026-02-05 14:29:41 +01:00
Paolo Tranquilli
05bef12ddd Merge pull request #21265 from github/redsun82/csharp-csrf-inheritance
C#: Fix CSRF query to check antiforgery attributes on base classes
2026-02-05 14:20:30 +01:00
Idriss Riouak
1df3adf021 Merge pull request #21244 from github/idrissrio/cpp/overlay/changes-json
C/C++ overlay: use files table instead of `overlayChangedFiles` for overlay discard
2026-02-05 13:15:07 +01:00
Tom Hvitved
025f73301b Rust: Move some overloading tests into a separate file 2026-02-05 12:49:53 +01:00
idrissrio
e26c199426 C/C++ overlay: use files table instead of overlayChangedFiles for overlay discard 2026-02-05 12:43:01 +01:00
Tom Hvitved
1203da1b66 Merge pull request #21253 from paldepind/rust/as-path-trait
Rust: Resolve `as` paths to trait
2026-02-05 12:38:16 +01:00
Paolo Tranquilli
f79bd3f4cf C#: accept location changes in test 2026-02-05 12:14:59 +01:00
Mathias Vorreiter Pedersen
476df7de73 Merge pull request #21260 from MathiasVP/add-windows-remote-flow-sources
C++: Add more Win32 and Azure SDK remote flow sources
2026-02-05 10:47:03 +00:00
Anders Schack-Mulligen
29e01748b7 Merge pull request #21267 from aschackmull/java/rename-misc
Java: Rename several AST predicates.
2026-02-05 11:15:29 +01:00
Anders Schack-Mulligen
11003e685d Java: Fix qldoc 2026-02-05 10:37:19 +01:00
Anders Schack-Mulligen
e4daeec2ca Merge pull request #21268 from aschackmull/java/view-cfg
Java: Add support for "View CFG" in VSCode.
2026-02-05 09:48:14 +01:00
Anders Schack-Mulligen
81977f11a1 Cfg: qldoc + overlay fixups. 2026-02-05 08:59:28 +01:00
Anders Schack-Mulligen
32fe12a6dd Java: Delay deprecation a bit. 2026-02-05 08:51:27 +01:00
Anders Schack-Mulligen
83adf793e4 Cfg: Fix compilation. 2026-02-04 15:28:37 +01:00
REDMOND\brodes
0a88425170 Python: Altering SSRF MaD to use 'request-forgery' tag. Update to test cases expected results, off by one line. Changed to using ModelOutput::sinkNode. 2026-02-04 09:04:22 -05:00
Ben Rodes
cd73dcfb04 Merge branch 'main' into azure_python_sdk_url_summary_upstream 2026-02-04 08:55:38 -05:00
Simon Friis Vindum
52dc58172d Merge branch 'main' into rust/as-path-trait 2026-02-04 14:47:57 +01:00
Owen Mansel-Chan
544931f73f Merge pull request #21266 from owen-mc/python/pretty-print-models-in-test
Python: Pretty print models in test
2026-02-04 13:46:51 +00:00
Anders Schack-Mulligen
2d02908e7f Java: Add change note. 2026-02-04 14:43:32 +01:00
Anders Schack-Mulligen
4fcf3fbff8 Java: Make loop classes extend LoopStmt and use getBody instead of getStmt. 2026-02-04 14:43:31 +01:00
Anders Schack-Mulligen
6f40ac15b4 Java: Rename ReturnStmt.getResult to getExpr. 2026-02-04 14:43:31 +01:00
Simon Friis Vindum
55ea55a44f Merge pull request #21247 from paldepind/rust/self-types
Rust: Resolve `Self` paths in type definitions
2026-02-04 13:41:53 +01:00
Anders Schack-Mulligen
36fa0a22f9 Java: Rename getTrueExpr/getFalseExpr on ConditionalExpr to getThen/getElse. 2026-02-04 13:38:11 +01:00
Michael Nebel
60bb9a9b06 C#: Move some populate methods and location writing methods. 2026-02-04 13:24:21 +01:00
Michael Nebel
c68cd58f70 C#: Add parameter marker interface, allow a type to a parent for parameter and make it possible to specify a parameter position offset. 2026-02-04 13:19:29 +01:00
Michael Nebel
dca10f8740 C#: Add extended_type to the DB scheme. 2026-02-04 12:51:30 +01:00
Owen Mansel-Chan
3f08ff88a4 Pretty print models in test
Otherwise the tests breaks when unrelated changes are made because the
model numbers change
2026-02-04 10:52:44 +00:00
Anders Schack-Mulligen
5e6e64b2b7 Java: Rename UnaryExpr.getExpr to getOperand. 2026-02-04 10:50:49 +01:00
Paolo Tranquilli
4973523404 C#: Fix CSRF query to check antiforgery attributes on base classes
Fixes https://github.com/github/codeql/discussions/21255
2026-02-04 09:42:20 +01:00
Taus
62fb38d834 Python: Rename otherArgs to implicitArgumentNode
Co-authored-by: yoff <yoff@github.com>
2026-02-03 15:32:46 +00:00
Michael B. Gale
571f21ba49 C#: Emit diagnostic if private registries are configured 2026-02-03 15:28:47 +00:00
Anders Schack-Mulligen
2d61fc5309 Java: Add support for "View CFG". 2026-02-03 15:49:27 +01:00
Michael B. Gale
8e39ed079e Merge pull request #21252 from github/mbg/go/private-registry-diagnostic
Go: Add diagnostic for private registry usage
2026-02-03 14:36:19 +00:00
Anders Schack-Mulligen
389cd5d648 Cfg: Extract CFG pretty-printing code. 2026-02-03 15:33:55 +01:00
Mathias Vorreiter Pedersen
092d25451f C++: Fix Copilot comments. 2026-02-03 11:45:30 +00:00
Mathias Vorreiter Pedersen
32b86eca50 C++: Add change note. 2026-02-03 11:40:31 +00:00
Mathias Vorreiter Pedersen
40a58135c2 C++: Accept test changes. 2026-02-03 11:30:55 +00:00
Mathias Vorreiter Pedersen
7ef96e3f3c C++: Add taint-inheriting reads from the Winhttp structs. 2026-02-03 11:30:31 +00:00
Mathias Vorreiter Pedersen
5531ef9bc1 C++: Accept test changes. 2026-02-03 11:17:23 +00:00
Mathias Vorreiter Pedersen
cbc2dbc14d C++: Add flow sources and summary models. 2026-02-03 11:14:16 +00:00
Mathias Vorreiter Pedersen
208cf716dc C++: Add tests with tests for remote flow sources from the Win32 API and from the Azure SDK. 2026-02-03 11:13:45 +00:00
Simon Friis Vindum
d72d8b63ed Rust: Fix inconsistency by skipping Self in use globs 2026-02-03 11:54:28 +01:00
Simon Friis Vindum
1791c1f1f9 Rust: Add test with path resolution inconsistency 2026-02-03 11:51:55 +01:00
Michael B. Gale
d5c4a19efa Apply suggestions from code review
Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2026-02-03 10:34:14 +00:00
Tom Hvitved
6fbf727309 Merge pull request #21251 from hvitved/rust/fix-bad-join
Rust: Fix bad join
2026-02-02 19:12:30 +01:00
Owen Mansel-Chan
e00390d23a Merge pull request #21224 from owen-mc/go/use-shared-basic-block-lib
Go: Use shared basic block lib
2026-02-02 16:31:06 +00:00
Michael B. Gale
d079671ec8 Align testItems with what getEnvVars does 2026-02-02 16:17:22 +00:00
Michael B. Gale
cbbc057dd3 Fix singular/plural wording and add test 2026-02-02 16:15:36 +00:00
Simon Friis Vindum
9fc2a54712 Rust: Accept changes to expected files for consistency checks 2026-02-02 17:12:25 +01:00
Simon Friis Vindum
d0e30d19c4 Rust: Resolve as paths to trait 2026-02-02 16:47:43 +01:00
Simon Friis Vindum
8de37fec17 Rust: Add tests with as paths 2026-02-02 16:43:21 +01:00
Henry Mercer
e712e62f14 Merge pull request #21250 from github/post-release-prep/codeql-cli-2.24.1
Post-release preparation for codeql-cli-2.24.1
2026-02-02 07:31:39 -08:00
Michael B. Gale
30b30d65c8 Emit the new diagnostic 2026-02-02 14:47:25 +00:00
Michael B. Gale
6d67e419ff Move private registry sources out of util package 2026-02-02 14:45:06 +00:00
Michael B. Gale
29930fa6bf Track active proxy configurations 2026-02-02 14:40:08 +00:00
Michael B. Gale
a57c6cde30 Add EmitPrivateRegistryUsed 2026-02-02 14:39:27 +00:00
Tom Hvitved
b16f1d3778 Rust: Fix bad join
Before
```
Evaluated relational algebra for predicate _PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6_PathResolution::ImplOrTraitItemNode.ge__#shared@0d3de6d9 with tuple counts:
         395360270  ~2%    {5} r1 = JOIN Type::TAssociatedTypeTypeParameter#6da9e52a WITH `PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6` CARTESIAN PRODUCT OUTPUT Rhs.0, Lhs.0, Lhs.1, Lhs.2, Rhs.1
        1274237644  ~0%    {6}    | JOIN WITH `PathResolution::ItemNode.getASuccessor/1#8f430f71` ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.3, Lhs.4, Rhs.1, Rhs.2
        1274237644  ~0%    {6}    | JOIN WITH PathResolution::TraitItemNode#8d4ce62d ON FIRST 1 OUTPUT Lhs.0, Lhs.4, Lhs.1, Lhs.2, Lhs.3, Lhs.5
           6984871  ~0%    {5}    | JOIN WITH `PathResolution::ImplOrTraitItemNode.getAssocItem/1#f77bb9ed` ON FIRST 3 OUTPUT Lhs.2, Lhs.0, Lhs.3, Lhs.4, Lhs.5
           6984871  ~0%    {4}    | JOIN WITH TypeAlias::Generated::TypeAlias#1ca97780 ON FIRST 1 OUTPUT Lhs.4, Lhs.1, Lhs.2, Lhs.3
           6076675  ~0%    {4}    | JOIN WITH `TypeAlias::Generated::TypeAlias.getTypeRepr/0#dispred#5fd7e521` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3
                           return r1
```

After
```
Evaluated relational algebra for predicate _PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6_PathResolution::ImplOrTraitItemNode.ge__#shared@760e0499 with tuple counts:
          443292  ~2%    {3} r1 = SCAN `PathResolution::ImplOrTraitItemNode.getAssocItem/1#f77bb9ed` OUTPUT In.0, In.2, In.1
            1258  ~1%    {3}    | JOIN WITH Type::TAssociatedTypeTypeParameter#6da9e52a ON FIRST 2 OUTPUT Lhs.2, Lhs.0, Rhs.2
        13656944  ~3%    {4}    | JOIN WITH `PathResolution::ItemNode.getASuccessor/1#8f430f71_102#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Rhs.2
         6984871  ~0%    {4}    | JOIN WITH `PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6` ON FIRST 1 OUTPUT Lhs.3, Lhs.1, Lhs.2, Rhs.1
         6076675  ~0%    {4}    | JOIN WITH `TypeAlias::Generated::TypeAlias.getTypeRepr/0#dispred#5fd7e521` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3
                         return r1
```
2026-02-02 15:26:32 +01:00
github-actions[bot]
73d06f26cb Post-release preparation for codeql-cli-2.24.1 2026-02-02 14:04:26 +00:00
Ben Rodes
7ddfa80399 Merge branch 'main' into azure_python_sdk_url_summary_upstream 2026-02-02 09:00:35 -05:00
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
Simon Friis Vindum
99b498b891 Rust: Resolve Self paths in type definitions 2026-02-02 13:51:59 +01:00
Simon Friis Vindum
95afe615b5 Rust: Add path resolution tests 2026-02-02 13:51:57 +01:00
Simon Friis Vindum
8b03608a4f Merge pull request #21188 from paldepind/rust/self-path-assoc
Rust: Implement type inference for associated types for concrete types
2026-02-02 13:50:43 +01: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
Simon Friis Vindum
0567864a83 Rust: Make module private
Co-authored-by: Tom Hvitved <hvitved@github.com>
2026-02-02 12:57:26 +01:00
Simon Friis Vindum
18576838d4 Rust: Minor tweaks and improvements 2026-02-02 12:07:18 +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
8aa1bff9a5 Add AstNode.getEnclosingBlock() 2026-02-01 23:06:26 +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
Taus
958c798c3f Python: Accept dataflow test changes
New nodes means new results. Luckily we rarely have a test that selects
_all_ dataflow nodes.
2026-01-30 12:50:25 +00:00
Taus
fb6175d10b Python: Fix consistency test failures
As we now have many more capturing closure arguments, we must once again
exclude the ones that don't actually have `argumentOf` defined.
2026-01-30 12:50:25 +00:00
Taus
3f718123a6 Python: Make capturing closure arguments synthetic and non-global
Uses the same trick as for `ExtractedArgumentNode`, wherein we postpone
the global restriction on the charpred to instead be in the `argumentOf`
predicate (which is global anyway).

In addition to this, we also converted `CapturedVariablesArgumentNode`
into a proper synthetic node, and added an explicit post-update node for
it. These nodes just act as wrappers for the function part of call
nodes. Thus, to make them work with the variable capture machinery, we
simply map them to the closure node for the corresponding control-flow
or post-update node.
2026-01-30 12:50:25 +00:00
Taus
6113d4be9e Python: Fix test issues
Fixes the test failures that arose from making `ExtractedArgumentNode`
local.

For the consistency checks, we now explicitly exclude the
`ExtractedArgumentNode`s (now much more plentiful due to the
overapproximation) that don't have a corresponding `getCallArg` tuple.

For various queries/tests using `instanceof ArgumentNode`, we instead us
`isArgumentNode`, which explicitly filters out the ones for which
`isArgumentOf` doesn't hold (which, again, is the case for most of the
nodes in the overapproximation).
2026-01-30 12:50:25 +00:00
Taus
7fccc23dbe Python: Make ExtractedArgumentNode local
Explicitly adds a bunch of nodes that were previously (using a global
analysis) identified as `ExtractedArgumentNode`s. These are then
subsequently filtered out in `argumentOf` (which is global) by putting
the call to `getCallArg` there instead of in the charpred.
2026-01-30 12:50:25 +00:00
Taus
ac5a74448f Python: Fix tests
With `ModuleVariableNode`s now appearing for _all_ global variables (not
just the ones that actually seem to be used), some of the tests changed
a bit. Mostly this was in the form of new flow (because of new nodes
that popped into existence). For some inline expectation tests, I opted
to instead exclude these results, as there was no suitable location to
annotate. For the normal tests, I just accepted the output (after having
vetted it carefully, of course).
2026-01-30 12:50:25 +00:00
Taus
30ce4069c7 Python: Remove global restriction on ModuleVariableNode
This may result in more nodes, but it should still be bounded by the
number of global variables in the source code.
2026-01-30 12:50:24 +00:00
Taus
4543c66d26 Python: Prepare LocalSourceNode for locality
Removes the dependence on the (global) `ModuleVariableNode.getARead()`,
by adding a local version (that doesn't include `import *` reads)
instead.
2026-01-30 12:50:24 +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
Owen Mansel-Chan
2f29c905c3 Fix typo in change note
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-28 22:39:08 +00:00
Owen Mansel-Chan
e1cf0a15ed Add change note 2026-01-28 22:12:31 +00:00
Owen Mansel-Chan
52c510bfea Use shared getScope instead of getRoot 2026-01-28 22:12:30 +00:00
Owen Mansel-Chan
b2f878229d Use shared getASuccessor and getAPredecessor 2026-01-28 22:12:23 +00:00
Owen Mansel-Chan
3dd6b3fb69 Use shared basic blocks library 2026-01-28 22:11:59 +00:00
Owen Mansel-Chan
c316d51d41 Add ConditionGuardNode.getOutcome 2026-01-28 21:46:26 +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
Simon Friis Vindum
2cb0e81da0 Rust: Remove duplicated inclusion of getAdditionalPathTypeAt 2026-01-27 16:17:52 +01:00
Simon Friis Vindum
aae5333325 Rust: Add test with type inference inconsistency 2026-01-27 16:17:51 +01:00
Simon Friis Vindum
fa59a8ae24 Rust: Implement TypeMention for paths that access associated types on concrete types 2026-01-27 16:17:49 +01:00
Simon Friis Vindum
4526afc29f Rust: Paths to associated types resolve to the associated type if implementation is unclear 2026-01-27 16:17:48 +01: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
Owen Mansel-Chan
5bfeede364 Add dependency on shared controlflow library 2026-01-27 09:43:19 +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
Simon Friis Vindum
330505c524 Rust: Add tests for associated types 2026-01-26 15:03:07 +01: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
01cc19cffc Rust: Add trait visibility test using Self 2026-01-26 12:31:16 +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
REDMOND\brodes
26b8a394b3 Adjusting acryonym for SSRF for casing standards. 2025-09-30 14:09:06 -04:00
REDMOND\brodes
a660eaba95 Adding docs. 2025-09-30 14:07:32 -04:00
REDMOND\brodes
acddb2c272 Moved change log to correct location. 2025-09-30 14:02:43 -04:00
Ben Rodes
d790c6df57 Update python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-30 14:00:25 -04:00
Ben Rodes
fab96d9539 Update python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-30 14:00:16 -04:00
Ben Rodes
5ca9ff2082 Update python/ql/lib/semmle/python/frameworks/SSRFSink.qll
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-30 14:00:05 -04:00
REDMOND\brodes
341f553866 Added change logs. 2025-09-30 13:55:31 -04:00
REDMOND\brodes
704e2966cb Adding azure sdk test cases and updated test expected file. 2025-09-30 13:32:56 -04:00
REDMOND\brodes
d27d4fdb27 Updating comments. 2025-09-30 13:31:48 -04:00
REDMOND\brodes
47fac883b8 Azure SDK models for SSRF analysis.
(cherry picked from commit 0274962612c02af09729526a3c44a545c1e69be8)
2025-09-30 11:58:26 -04:00
1043 changed files with 188884 additions and 101789 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,14 +250,15 @@ 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")
go_sdk.download(version = "1.25.0")
go_sdk.download(version = "1.26.0")
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//go/extractor:go.mod")
use_repo(go_deps, "org_golang_x_mod", "org_golang_x_tools")
use_repo(go_deps, "com_github_stretchr_testify", "org_golang_x_mod", "org_golang_x_tools")
ripunzip_archive = use_repo_rule("//misc/ripunzip:ripunzip.bzl", "ripunzip_archive")

View File

@@ -1,3 +1,13 @@
## 0.4.28
No user-facing changes.
## 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

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

View File

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

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.28
library: true
warnOnImplicitThis: true
dependencies:

View File

@@ -1,3 +1,11 @@
## 0.6.20
No user-facing changes.
## 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

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

View File

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

View File

@@ -1,5 +1,5 @@
name: codeql/actions-queries
version: 0.6.18
version: 0.6.20
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,5 @@
description: Add trap_filename, source_file_uses_trap and in_trap relations
compatibility: full
trap_filename.rel: delete
source_file_uses_trap.rel: delete
in_trap.rel: delete

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,27 @@
## 7.1.1
### Minor Analysis Improvements
* Added remote flow source models for the `winhttp.h` windows header and the Azure SDK core library for C/C++.
## 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

@@ -0,0 +1,5 @@
## 7.1.1
### Minor Analysis Improvements
* Added remote flow source models for the `winhttp.h` windows header and the Azure SDK core library for C/C++.

View File

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

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

@@ -24,6 +24,13 @@ extensions:
- ["", "", False, "MapViewOfFileNuma2", "", "", "ReturnValue[*]", "local", "manual"]
# ntifs.h
- ["", "", False, "NtReadFile", "", "", "Argument[*5]", "local", "manual"]
# winhttp.h
- ["", "", False, "WinHttpReadData", "", "", "Argument[*1]", "remote", "manual"]
- ["", "", False, "WinHttpReadDataEx", "", "", "Argument[*1]", "remote", "manual"]
- ["", "", False, "WinHttpQueryHeaders", "", "", "Argument[*3]", "remote", "manual"]
- ["", "", False, "WinHttpQueryHeadersEx", "", "", "Argument[*5]", "remote", "manual"]
- ["", "", False, "WinHttpQueryHeadersEx", "", "", "Argument[*6]", "remote", "manual"]
- ["", "", False, "WinHttpQueryHeadersEx", "", "", "Argument[**8]", "remote", "manual"]
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
@@ -46,4 +53,6 @@ extensions:
- ["", "", False, "RtlMoveMemory", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
- ["", "", False, "RtlMoveVolatileMemory", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
# winternl.h
- ["", "", False, "RtlInitUnicodeString", "", "", "Argument[*1]", "Argument[*0].Field[*Buffer]", "value", "manual"]
- ["", "", False, "RtlInitUnicodeString", "", "", "Argument[*1]", "Argument[*0].Field[*Buffer]", "value", "manual"]
# winhttp.h
- ["", "", False, "WinHttpCrackUrl", "", "", "Argument[*0]", "Argument[*3]", "taint", "manual"]

View File

@@ -0,0 +1,41 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: sourceModel
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
- ["Azure::Core::Http", "RawResponse", True, "GetHeaders", "", "", "ReturnValue[*]", "remote", "manual"]
- ["Azure::Core::Http", "RawResponse", True, "GetBody", "", "", "ReturnValue[*]", "remote", "manual"]
- ["Azure::Core::Http", "RawResponse", True, "ExtractBodyStream", "", "", "ReturnValue[*]", "remote", "manual"]
- ["Azure::Core::Http", "Request", True, "GetHeaders", "", "", "ReturnValue", "remote", "manual"]
- ["Azure::Core::Http", "Request", True, "GetHeader", "", "", "ReturnValue", "remote", "manual"]
- ["Azure::Core::Http", "Request", True, "GetBodyStream", "", "", "ReturnValue[*]", "remote", "manual"]
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["Azure::Core", "Url", True, "Url", "", "", "Argument[*0]", "Argument[-1]", "taint", "manual"]
- ["Azure::Core", "Url", True, "SetScheme", "", "", "Argument[*0]", "Argument[-1]", "taint", "manual"]
- ["Azure::Core", "Url", True, "SetHost", "", "", "Argument[*0]", "Argument[-1]", "taint", "manual"]
- ["Azure::Core", "Url", True, "SetPort", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["Azure::Core", "Url", True, "SetPath", "", "", "Argument[*0]", "Argument[-1]", "taint", "manual"]
- ["Azure::Core", "Url", True, "SetQueryParameters", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["Azure::Core", "Url", True, "AppendPath", "", "", "Argument[*0]", "Argument[-1]", "taint", "manual"]
- ["Azure::Core", "Url", True, "AppendQueryParameter", "", "", "Argument[*1]", "Argument[-1]", "taint", "manual"]
- ["Azure::Core", "Url", True, "GetHost", "", "", "Argument[-1]", "ReturnValue[*]", "taint", "manual"]
- ["Azure::Core", "Url", True, "GetPath", "", "", "Argument[-1]", "ReturnValue[*]", "taint", "manual"]
- ["Azure::Core", "Url", True, "GetPort", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["Azure::Core", "Url", True, "GetQueryParameters", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["Azure::Core", "Url", True, "GetScheme", "", "", "Argument[-1]", "ReturnValue[*]", "taint", "manual"]
- ["Azure::Core", "Url", True, "GetRelativeUrl", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["Azure::Core", "Url", True, "GetAbsoluteUrl", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
- ["Azure::Core", "Url", True, "Decode", "", "", "Argument[*0]", "ReturnValue", "taint", "manual"]
- ["Azure::Core", "Url", True, "Encode", "", "", "Argument[*0]", "ReturnValue", "taint", "manual"]
- ["Azure::Core::IO", "BodyStream", True, "Read", "", "", "Argument[-1]", "Argument[*0]", "taint", "manual"]
- ["Azure::Core::IO", "BodyStream", True, "ReadToCount", "", "", "Argument[-1]", "Argument[*0]", "taint", "manual"]
- ["Azure::Core::IO", "BodyStream", True, "ReadToEnd", "", "", "Argument[-1]", "ReturnValue.Element", "taint", "manual"]
- ["Azure", "Nullable", True, "Nullable", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
- ["Azure", "Nullable", True, "operator=", "", "", "Argument[*0]", "Argument[-1]", "value", "manual"]
- ["Azure", "Nullable", True, "Value", "", "", "Argument[-1]", "ReturnValue[*]", "taint", "manual"]
- ["Azure", "Nullable", True, "operator->", "", "", "Argument[-1]", "ReturnValue[*]", "taint", "manual"]
- ["Azure", "Nullable", True, "operator*", "", "", "Argument[-1]", "ReturnValue[*]", "taint", "manual"]

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 7.0.0
version: 7.1.1
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,19 +62,29 @@ private string getMultiLocationFilePath(@element e) {
* overlay variant.
*/
overlay[local]
private predicate holdsInBase() { not isOverlay() }
private predicate isBase() { not isOverlay() }
/**
* Holds if `path` was extracted in the overlay database.
*/
overlay[local]
private predicate overlayHasFile(string path) {
isOverlay() and
files(_, path) and
path != ""
}
/**
* Discards an element from the base variant if:
* - It has a single location in a changed file, or
* - All of its locations are in changed files.
* - It has a single location in a file extracted in the overlay, or
* - All of its locations are in files extracted in the overlay.
*/
overlay[discard_entity]
private predicate discardElement(@element e) {
holdsInBase() and
isBase() and
(
overlayChangedFiles(getSingleLocationFilePath(e))
overlayHasFile(getSingleLocationFilePath(e))
or
forex(string path | path = getMultiLocationFilePath(e) | overlayChangedFiles(path))
forex(string path | path = getMultiLocationFilePath(e) | overlayHasFile(path))
)
}

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
)
}
@@ -1720,9 +1726,7 @@ private module Cached {
SsaImpl::ssaFlow(n, succ) and
bb1 = n.getBasicBlock() and
bb2 = succ.getBasicBlock() and
bb1 != bb2 and
bb2.dominates(bb1) and
bb1.getASuccessor+() = bb2
bb2.strictlyDominates(bb1)
)
}
@@ -2417,6 +2421,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 +2455,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 +2465,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 +2502,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 +2554,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 +2575,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 +2615,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 +2664,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 +2676,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 +2707,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
}
@@ -381,7 +390,7 @@ class TranslatedDeclStmt extends TranslatedStmt {
override TranslatedElement getLastChild() { result = this.getChild(this.getChildCount() - 1) }
private int getChildCount() { result = count(this.getDeclarationEntry(_)) }
private int getChildCount() { result = count(int i | exists(this.getDeclarationEntry(i))) }
IRDeclarationEntry getIRDeclarationEntry(int index) {
result.hasIndex(index) and
@@ -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

@@ -57,3 +57,4 @@ private import implementations.CAtlFile
private import implementations.CAtlFileMapping
private import implementations.CAtlTemporaryFile
private import implementations.CRegKey
private import implementations.WinHttp

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

@@ -0,0 +1,50 @@
private import cpp
private import semmle.code.cpp.ir.dataflow.FlowSteps
private import semmle.code.cpp.dataflow.new.DataFlow
/** The `WINHTTP_HEADER_NAME` class from `winhttp.h`. */
class WinHttpHeaderName extends Class {
WinHttpHeaderName() { this.hasGlobalName("_WINHTTP_HEADER_NAME") }
}
/** The `WINHTTP_EXTENDED_HEADER` class from `winhttp.h`. */
class WinHttpExtendedHeader extends Class {
WinHttpExtendedHeader() { this.hasGlobalName("_WINHTTP_EXTENDED_HEADER") }
}
private class WinHttpHeaderNameInheritingContent extends TaintInheritingContent,
DataFlow::FieldContent
{
WinHttpHeaderNameInheritingContent() {
this.getIndirectionIndex() = 2 and
(
this.getAField().getDeclaringType() instanceof WinHttpHeaderName
or
// The extended header looks like:
// struct WINHTTP_EXTENDED_HEADER {
// union { [...] };
// union { [...] };
// };
// So the first declaring type is the anonymous unions, and the declaring
// type of those anonymous unions is the `WINHTTP_EXTENDED_HEADER` struct.
this.getAField().getDeclaringType().getDeclaringType() instanceof WinHttpExtendedHeader
)
}
}
/** The `URL_COMPONENTS` class from `winhttp.h`. */
class WinHttpUrlComponents extends Class {
WinHttpUrlComponents() { this.hasGlobalName("_WINHTTP_URL_COMPONENTS") }
}
private class WinHttpUrlComponentsInheritingContent extends TaintInheritingContent,
DataFlow::FieldContent
{
WinHttpUrlComponentsInheritingContent() {
exists(Field f | f = this.getField() and f.getDeclaringType() instanceof WinHttpUrlComponents |
if f.getType().getUnspecifiedType() instanceof PointerType
then this.getIndirectionIndex() = 2
else this.getIndirectionIndex() = 1
)
}
}

View File

@@ -404,7 +404,7 @@ predicate cmpWithLinearBound(
* For example, if `t` is a signed 32-bit type then holds if `lb` is
* `-2^31` and `ub` is `2^31 - 1`.
*/
private predicate typeBounds(ArithmeticType t, float lb, float ub) {
private predicate typeBounds0(ArithmeticType t, float lb, float ub) {
exists(IntegralType integralType, float limit |
integralType = t and limit = 2.pow(8 * integralType.getSize())
|
@@ -423,6 +423,42 @@ private predicate typeBounds(ArithmeticType t, float lb, float ub) {
t instanceof FloatingPointType and lb = -(1.0 / 0.0) and ub = 1.0 / 0.0
}
/**
* Gets the underlying type for an enumeration `e`.
*
* If the enumeration does not have an explicit type we approximate it using
* the following rules:
* - The result type is always `signed`, and
* - if the largest value fits in an `int` the result is `int`. Otherwise, the
* result is `long`.
*/
private IntegralType getUnderlyingTypeForEnum(Enum e) {
result = e.getExplicitUnderlyingType()
or
not e.hasExplicitUnderlyingType() and
result.isSigned() and
exists(IntType intType |
if max(e.getAnEnumConstant().getValue().toFloat()) >= 2.pow(8 * intType.getSize() - 1)
then result instanceof LongType
else result = intType
)
}
/**
* Holds if `lb` and `ub` are the lower and upper bounds of the unspecified
* type `t`.
*
* For example, if `t` is a signed 32-bit type then holds if `lb` is
* `-2^31` and `ub` is `2^31 - 1`.
*
* Unlike `typeBounds0`, this predicate also handles `Enum` types.
*/
private predicate typeBounds(Type t, float lb, float ub) {
typeBounds0(t, lb, ub)
or
typeBounds0(getUnderlyingTypeForEnum(t), lb, ub)
}
private Type stripReference(Type t) {
if t instanceof ReferenceType then result = t.(ReferenceType).getBaseType() else result = t
}

View File

@@ -512,8 +512,8 @@ private module BoundsEstimate {
*/
float getBoundsLimit() {
// This limit is arbitrary, but low enough that it prevents timeouts on
// specific observed customer databases (and the in the tests).
result = 2.0.pow(40)
// specific observed customer databases (and in the tests).
result = 2.0.pow(29)
}
/** Gets the maximum number of bounds possible for `t` when widening is used. */

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

@@ -236,6 +236,34 @@ extractor_version(
string frontend_version: string ref
)
/**
* Gives the TRAP filename that `trap` is associated with.
* For debugging only.
*/
trap_filename(
int trap: @trap,
string filename: string ref
);
/**
* In `build-mode: none` overlay mode, indicates that `source_file`
* (`/path/to/foo.c`) uses the TRAP file `trap_file`; i.e. it is the
* TRAP file corresponding to `foo.c`, something it transitively
* includes, or a template instantiation it transitively uses.
*/
source_file_uses_trap(
string source_file: string ref,
int trap_file: @trap ref
);
/**
* Holds if there is a definition of `element` in TRAP file `trap_file`.
*/
in_trap(
int element: @element ref,
int trap_file: @trap ref
);
pch_uses(
int pch: @pch ref,
int compilation: @compilation ref,
@@ -2353,6 +2381,7 @@ case @preprocdirect.kind of
| 14 = @ppd_ms_import
| 15 = @ppd_elifdef
| 16 = @ppd_elifndef
| 17 = @ppd_embed
| 18 = @ppd_warning
;
@@ -2379,6 +2408,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 +2423,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 +2435,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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Add trap_filename, source_file_uses_trap and in_trap relations
compatibility: full

View File

@@ -1,3 +1,11 @@
## 1.5.11
No user-facing changes.
## 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

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

View File

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

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.5.9
version: 1.5.11
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

@@ -0,0 +1,297 @@
using uint16_t = unsigned short;
using int64_t = long long;
using size_t = unsigned long;
using uint8_t = unsigned char;
using int32_t = int;
using uint32_t = unsigned int;
namespace std
{
class string
{
public:
string();
string(const char *);
~string();
};
template <typename K, typename V>
class map
{
public:
map();
~map();
V& operator[](const K& key);
};
template <typename T>
class vector
{
public:
vector();
~vector();
T& operator[](size_t);
};
template<typename T>
class unique_ptr {
public:
unique_ptr();
~unique_ptr();
T* get();
};
}
namespace Azure
{
template <typename T>
class Nullable
{
public:
Nullable();
Nullable(const T);
Nullable(const Nullable &);
~Nullable();
Nullable (Nullable &&);
Nullable & operator= (const Nullable &);
bool HasValue() const;
const T & Value () const;
T& Value ();
const T * operator-> () const;
T * operator-> ();
const T & operator* () const;
T & operator* ();
};
namespace Core
{
class Url
{
public:
Url();
Url(const std::string &);
void AppendPath(const std::string &encodedPath);
void AppendQueryParameter(const std::string &encodedKey,
const std::string &encodedValue);
static std::string Url::Decode(const std::string &value);
static std::string Url::Encode(const std::string &value,
const std::string &doNotEncodeSymbols = "");
std::string Url::GetAbsoluteUrl() const;
const std::string &GetHost() const;
const std::string &GetPath() const;
uint16_t GetPort() const;
std::map<std::string, std::string> GetQueryParameters() const;
std::string Url::GetRelativeUrl() const;
const std::string &GetScheme() const;
void RemoveQueryParameter(const std::string &encodedKey);
void SetHost(const std::string &encodedHost);
void SetPath(const std::string &encodedPath);
void SetPort(uint16_t port);
void SetQueryParameters(std::map<std::string, std::string> queryParameters);
void SetScheme(const std::string &scheme);
};
class Context
{
public:
Context();
};
namespace IO
{
class BodyStream
{
public:
virtual ~BodyStream();
virtual int64_t Length() const = 0;
virtual void Rewind();
size_t Read(uint8_t *buffer, size_t count, Azure::Core::Context const &context = Azure::Core::Context());
size_t ReadToCount(uint8_t *buffer, size_t count, Azure::Core::Context const &context = Azure::Core::Context());
std::vector<uint8_t> ReadToEnd(Azure::Core::Context const &context = Azure::Core::Context());
};
}
enum class HttpStatusCode {
None = 0,
Continue = 100,
SwitchingProtocols = 101,
Processing = 102,
EarlyHints = 103,
OK = 200,
Created = 201,
Accepted = 202,
NonAuthoritativeInformation = 203,
NoContent = 204,
ResetContent = 205,
PartialContent = 206,
MultiStatus = 207,
AlreadyReported = 208,
IMUsed = 226,
MultipleChoices = 300,
MovedPermanently = 301,
Found = 302,
SeeOther = 303,
NotModified = 304,
UseProxy = 305,
TemporaryRedirect = 307,
PermanentRedirect = 308,
BadRequest = 400,
Unauthorized = 401,
PaymentRequired = 402,
Forbidden = 403,
NotFound = 404,
MethodNotAllowed = 405,
NotAcceptable = 406,
ProxyAuthenticationRequired = 407,
RequestTimeout = 408,
Conflict = 409,
Gone = 410,
LengthRequired = 411,
PreconditionFailed = 412,
PayloadTooLarge = 413,
URITooLong = 414,
UnsupportedMediaType = 415,
RangeNotSatisfiable = 416,
ExpectationFailed = 417,
MisdirectedRequest = 421,
UnprocessableEntity = 422,
Locked = 423,
FailedDependency = 424,
TooEarly = 425,
UpgradeRequired = 426,
PreconditionRequired = 428,
TooManyRequests = 429,
RequestHeaderFieldsTooLarge = 431,
UnavailableForLegalReasons = 451,
InternalServerError = 500,
NotImplemented = 501,
BadGateway = 502,
ServiceUnavailable = 503,
GatewayTimeout = 504,
HTTPVersionNotSupported = 505,
VariantAlsoNegotiates = 506,
InsufficientStorage = 507,
LoopDetected = 508,
NotExtended = 510,
NetworkAuthenticationRequired = 511
};
namespace Http
{
class HttpMethod
{
public:
HttpMethod(std::string value);
bool operator==(const HttpMethod &other) const;
bool operator!=(const HttpMethod &other) const;
const std::string &ToString() const;
};
extern const HttpMethod Get;
extern const HttpMethod Head;
extern const HttpMethod Post;
extern const HttpMethod Put;
extern const HttpMethod Delete;
extern const HttpMethod Patch;
extern const HttpMethod Options;
class Request
{
public:
explicit Request(HttpMethod httpMethod,
Url url);
explicit Request(HttpMethod httpMethod,
Url url,
bool shouldBufferResponse);
explicit Request(HttpMethod httpMethod,
Url url,
IO::BodyStream *bodyStream);
explicit Request(HttpMethod httpMethod,
Url url,
IO::BodyStream *bodyStream,
bool shouldBufferResponse);
std::map<std::string, std::string> GetHeaders () const;
Azure::Nullable<std::string> GetHeader(std::string const &name);
IO::BodyStream * GetBodyStream();
Azure::Core::IO::BodyStream const* GetBodyStream () const;
};
class RawResponse {
public:
RawResponse (int32_t majorVersion, int32_t minorVersion, HttpStatusCode statusCode, std::string const &reasonPhrase);
RawResponse (RawResponse const &response);
RawResponse (RawResponse &&response);
~RawResponse ();
void SetHeader (std::string const &name, std::string const &value);
void SetBodyStream (std::unique_ptr< Azure::Core::IO::BodyStream > stream);
void SetBody (std::vector< uint8_t > body);
uint32_t GetMajorVersion () const;
uint32_t GetMinorVersion () const;
HttpStatusCode GetStatusCode () const;
std::string const & GetReasonPhrase () const;
std::map<std::string, std::string>& GetHeaders () const;
std::unique_ptr<Azure::Core::IO::BodyStream> ExtractBodyStream ();
std::vector<uint8_t> & GetBody ();
std::vector<uint8_t> const& GetBody() const;
};
}
}
}
void sink(char);
void sink(std::string);
void sink(std::vector<uint8_t>);
void sink(Azure::Nullable<std::string>);
void test_BodyStream() {
Azure::Core::Http::Request request(Azure::Core::Http::Get, Azure::Core::Url("http://example.com"));
Azure::Core::IO::BodyStream * resp = request.GetBodyStream();
{
unsigned char buffer[1024];
resp->Read(buffer, sizeof(buffer));
sink(*buffer); // $ ir
}
{
unsigned char buffer[1024];
resp->ReadToCount(buffer, sizeof(buffer));
sink(*buffer); // $ ir
}
{
std::vector<unsigned char> vec = resp->ReadToEnd();
sink(vec); // $ ir
}
}
void test_RawResponse(Azure::Core::Http::RawResponse& resp) {
{
std::map<std::string, std::string> body = resp.GetHeaders();
sink(body["Content-Type"]); // $ ir
}
{
std::vector<uint8_t> body = resp.GetBody();
sink(body); // $ ir
}
{
std::unique_ptr<Azure::Core::IO::BodyStream> bodyStream = resp.ExtractBodyStream();
sink(bodyStream.get()->ReadToEnd()); // $ ir
}
}
void test_GetHeader() {
Azure::Core::Http::Request request(Azure::Core::Http::Get, Azure::Core::Url("http://example.com"));
{
auto headerValue = request.GetHeader("Content-Type").Value();
sink(headerValue); // $ ir
}
{
std::map<std::string, std::string> headers = request.GetHeaders();
std::string contentType = headers["Content-Type"];
sink(contentType); // $ ir
}
}

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