Compare commits

..

298 Commits

Author SHA1 Message Date
idrissrio
545d541588 Accept new JDK 27 results 2026-07-08 16:48:22 +02:00
idrissrio
bf7c48972b Java: Update supported language versions to include Java 27 2026-07-08 16:44:31 +02:00
idrissrio
371e8c27f7 Java: Add change note for JDK 27 2026-07-08 16:44:29 +02:00
Owen Mansel-Chan
25cd352de7 Merge pull request #22123 from owen-mc/csharp/convert-qlref-tests-to-inline-expectations
C#: Convert qlref tests to inline expectations
2026-07-08 14:47:04 +01:00
Geoffrey White
8bb12d1507 Merge pull request #22005 from github/dependabot/pip/misc/codegen/pip-02f7ad5a4b
Bump the pip group across 2 directories with 2 updates
2026-07-08 14:37:05 +01:00
Owen Mansel-Chan
aba008dcd7 Remove comments "// BAD: but flagged by cs/constant-condition" 2026-07-08 14:00:57 +01:00
Owen Mansel-Chan
7b96f66d34 Also run cs/constant-condition on test for cs/comparison-of-identical-expressions 2026-07-08 14:00:55 +01:00
Taus
3c3f740a25 Merge pull request #22120 from asgerf/unified/local-scoping
Unified: implement local scoping
2026-07-08 14:33:14 +02:00
Owen Mansel-Chan
85d800f317 Apply suggestions from code review
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2026-07-08 13:02:20 +01:00
Owen Mansel-Chan
134e30260d Merge pull request #22119 from owen-mc/java/fix-tainted-path-pattern-sanitization
Java: fix `@Pattern` sanitization for `java/path-injection`
2026-07-08 11:37:15 +01:00
Owen Mansel-Chan
a16e19a3b1 Merge pull request #22127 from owen-mc/cpp/convert-qlref-inline-expectations
C++: Convert qlref tests to inline expectations
2026-07-08 11:36:35 +01:00
Owen Mansel-Chan
69ed2da241 Merge pull request #22134 from github/workflow/coverage/update
Update CSV framework coverage reports
2026-07-08 11:19:06 +01:00
github-actions[bot]
bc966f62e2 Add changed framework coverage reports 2026-07-08 00:38:59 +00:00
Owen Mansel-Chan
b6d588c1a8 Revert inline expectations for blazor integration tests with BMN 2026-07-08 00:56:43 +01:00
Owen Mansel-Chan
5ba1fe315d Accept updated .expected output 2026-07-08 00:56:16 +01:00
Owen Mansel-Chan
8363d2d66d Merge pull request #22132 from joshimar/java/spring-webclient-uri-ssrf-sink
Java: Model Spring reactive `WebClient.uri` as a request forgery sink
2026-07-08 00:40:33 +01:00
Luis Azanza
b8f8370c33 Update java/ql/lib/change-notes/2026-06-30-spring-webclient-uri-ssrf.md
Update change note to be more technically accurate

Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2026-07-07 16:21:09 -07:00
Luis Azanza
6ff2a4c0d6 Apply suggestion from @owen-mc
Removing Apple Inc notice per feedback provided by GitHub

Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
2026-07-07 16:10:05 -07:00
Luis Azanza
1db31327a7 Java: Model Spring reactive WebClient.uri as a request forgery sink 2026-07-07 13:30:48 -07:00
Owen Mansel-Chan
19745e13b5 Fix some lines with // $ ... // $ MISSING:
Note that when a line is marked `// BAD [NOT DETECTED]` but actually has
an alert, I assume that the `[NOT DETECTED]` is outdated and should be
deleted.
2026-07-07 20:48:39 +01:00
Owen Mansel-Chan
9d9590623d Address review comments 2026-07-07 20:48:36 +01:00
Geoffrey White
117a0bb87e Copilot fix for missing module pygments - regenerating the lockfile fully. 2026-07-07 16:02:36 +01:00
Owen Mansel-Chan
f67b7299f9 Update query example (synced file) 2026-07-07 14:09:50 +01:00
Owen Mansel-Chan
366d70bfee Convert qlref tests to inline expectations 2026-07-07 14:09:48 +01:00
Owen Mansel-Chan
a812e4aa99 Refactor creating barriers with annotations 2026-07-07 12:44:19 +01:00
Owen Mansel-Chan
fa16728522 Fix comments in one test 2026-07-07 12:06:43 +01:00
Owen Mansel-Chan
76d8ae8694 Add MISSING: tag 2026-07-07 10:59:21 +01:00
Owen Mansel-Chan
843ac7c6b0 Add SPURIOUS: tags 2026-07-07 10:54:11 +01:00
Owen Mansel-Chan
a2c5d4c818 C++: Convert qlref tests to inline expectations 2026-07-07 09:49:50 +01:00
Owen Mansel-Chan
8f026b1dc2 Allow inline expectation comments in more file formats 2026-07-06 13:43:31 +01:00
Asger F
bfb3ead314 Apply suggestions from code review
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-03 14:29:54 +02:00
Owen Mansel-Chan
e5bd62dbd3 Add change note 2026-07-03 11:34:11 +01:00
Owen Mansel-Chan
76b4f4f223 Fix @Pattern sanitizer for TaintedPath 2026-07-03 11:34:06 +01:00
Owen Mansel-Chan
077b531e41 Add failing TaintedPath test for @Pattern sanitizer 2026-07-03 11:34:03 +01:00
Asger F
c23c3d9e79 unified: Translate bare names in patterns correctly
- Context is fully reset when stepping into an expr/stmt/body.
- Binding modifier is rolled into outer_modifiers.
2026-07-03 11:59:58 +02:00
Asger F
036ed04eee unified: Support OrPattern bindings 2026-07-03 11:59:57 +02:00
Asger F
891e244116 unified: Add WhileStmt as a Conditional 2026-07-03 11:59:55 +02:00
Asger F
c8eb2071d8 unified: Add tests with 'while let' 2026-07-03 11:59:53 +02:00
Asger F
e7bff859e8 unified: More fixes in test cases 2026-07-03 11:59:51 +02:00
Asger F
6ea146f65b unified: Fix broken block syntax
The original test was not valid Swift syntax
2026-07-03 11:59:50 +02:00
Asger F
a86c7ba422 unified: Flatten GuardIfStmt into the enclosing block 2026-07-03 11:59:47 +02:00
Asger F
d0cd4ac536 Shared: remove unused getLhs() predicate 2026-07-03 11:54:26 +02:00
Owen Mansel-Chan
c3a0b65c0c Merge pull request #22115 from owen-mc/java/update-mad-docs
Java: Add section in models docs about specifying java types
2026-07-03 09:16:29 +01:00
Owen Mansel-Chan
268e9eadac Add section on specifying java types 2026-07-02 22:09:51 +01:00
Geoffrey White
ab1bc853fc Merge pull request #22053 from geoffw0/arith
Rust: Fix FPs in rust/hard-coded-cryptographic-value
2026-07-02 17:37:38 +01:00
Michael B. Gale
f4d8358454 Merge pull request #22110 from github/post-release-prep/codeql-cli-2.26.0
Post-release preparation for codeql-cli-2.26.0
2026-07-02 15:32:22 +01:00
Nora Dimitrijević
0a02b16c43 Merge pull request #22095 from d10c/d10c/drop-bracket-style-links
Remove [[ link syntax from C# XSS sink
2026-07-02 15:45:30 +02:00
Owen Mansel-Chan
4aef485d3c Merge pull request #22106 from github/workflow/coverage/update
Update CSV framework coverage reports
2026-07-02 14:08:20 +01:00
github-actions[bot]
5e50fc8471 Post-release preparation for codeql-cli-2.26.0 2026-07-02 12:26:43 +00:00
Michael B. Gale
e4a7b4ff51 Merge pull request #22109 from github/release-prep/2.26.0
Release preparation for version 2.26.0
2026-07-02 13:02:15 +01:00
Michael B. Gale
66ddf3b4c6 Remove unnecessary changenote for the hotfix 2026-07-02 12:58:05 +01:00
github-actions[bot]
1af9609eed Release preparation for version 2.26.0 2026-07-02 11:43:30 +00:00
Mathias Vorreiter Pedersen
4f4cdf434b Merge pull request #22061 from MathiasVP/mad-write-through-model
Shared: Support flow summaries from `ReturnValue`s
2026-07-02 12:38:44 +01:00
Michael B. Gale
79eeaa2028 Merge pull request #22108 from hvitved/python-hot-fix
Python: release hotfix
2026-07-02 12:31:20 +01:00
Geoffrey White
1f4ae86a84 Apply suggestions from code review
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2026-07-02 11:26:26 +01:00
Tom Hvitved
797f58b5d5 Merge pull request #22052 from hvitved/rust/type-constraint-base-type-match-gen
Type inference: Generalize `typeConstraintBaseTypeMatch`
2026-07-02 11:57:28 +02:00
Tom Hvitved
2308981665 Python: Update inline test expectations 2026-07-02 11:54:36 +02:00
Tom Hvitved
32181cd7e8 Python: Improve some flow summaries 2026-07-02 11:54:28 +02:00
Geoffrey White
9aaf3f15eb Merge pull request #22105 from geoffw0/rubyinline3
Ruby: Address testFailures in inline expectations tests (part 3)
2026-07-02 08:29:39 +01:00
github-actions[bot]
d8b89d2581 Add changed framework coverage reports 2026-07-02 00:54:34 +00:00
Michael B. Gale
f4d6f582c8 Merge pull request #22096 from github/revert-22059-release-prep/2.26.0
Revert "Release preparation for version 2.26.0"
2026-07-01 22:11:34 +01:00
Asger F
36b31a855c unified: Add debug query for local scoping graph 2026-07-01 21:51:41 +02:00
Asger F
bced7bb6d2 unified: Add local name binding and tests
As documented in the test, 'guard if' statements are still not properly supported.
2026-07-01 21:51:21 +02:00
Asger F
970e991b2c unified: Add a few more AST helper classes 2026-07-01 21:50:04 +02:00
Asger F
982f6a5e8a unified: Move Comments.ql into AstExtra.qll
Also move into 'internal' and expose through a Public module
2026-07-01 21:49:48 +02:00
Tom Hvitved
6c3c5ea8af Merge pull request #22101 from hvitved/python/flow-summaries-improvements
Python: Improve some flow summaries
2026-07-01 19:36:13 +02:00
Geoffrey White
226efb3ad7 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-01 16:52:38 +01:00
Geoffrey White
73ec4b8d02 Ruby: Fix one last inline expectations testFailure. 2026-07-01 16:44:12 +01:00
Owen Mansel-Chan
cb4a1d0929 Merge pull request #22103 from owen-mc/java/fix-mad-file-names
Java: Fix misnamed MaD models files
2026-07-01 14:04:44 +01:00
Jeroen Ketema
d664d17a11 Merge pull request #22087 from jketema/subst
Add Windows integration tests showing that `subst` is handled inconsistently
2026-07-01 14:48:22 +02:00
Owen Mansel-Chan
7263c00b00 Fix misnamed MaD models files 2026-07-01 13:13:01 +01:00
Geoffrey White
e9766086cd Merge pull request #22079 from geoffw0/kotlininline
Kotlin: Address inline expectations testFailures.
2026-07-01 12:39:11 +01:00
Jeroen Ketema
d551ab3afb Fix expected file 2026-07-01 13:24:05 +02:00
Tom Hvitved
2bf6031c0f Python: Update inline test expectations 2026-07-01 13:10:41 +02:00
Jeroen Ketema
daf97f7139 Add Windows integration tests showing that subst is handled inconsistently 2026-07-01 12:51:05 +02:00
Tom Hvitved
a5444b573a Python: Improve some flow summaries 2026-07-01 12:05:53 +02:00
Mathias Vorreiter Pedersen
3410f39b3c Merge pull request #22089 from MathiasVP/remove-mad-support-for-variables
C++: Remove support for global variables as sources and sinks in MaD
2026-07-01 10:31:59 +01:00
Owen Mansel-Chan
cf51664d69 Merge pull request #22099 from github/workflow/coverage/update
Update CSV framework coverage reports
2026-07-01 10:03:46 +01:00
github-actions[bot]
3cbb8ba87e Add changed framework coverage reports 2026-07-01 00:58:10 +00:00
Taus
b12c67f231 Merge pull request #22092 from github/tausbn/python-hotfix-disable-instance-field-step
Python: hotfix - disable instanceFieldStep to avoid type-tracker blowup
2026-06-30 21:53:06 +02:00
Mario Campos
41f2e7b6f6 Revert "Release preparation for version 2.26.0" 2026-06-30 13:21:27 -05:00
Asger F
11e75c12a8 Merge pull request #22090 from asgerf/unified/inline-test-expectations
unified: Add inline expectation test library
2026-06-30 19:55:15 +02:00
Mathias Vorreiter Pedersen
dbbcc1741c C++: Delete now-unsupported MaD rows. 2026-06-30 17:48:31 +01:00
Mathias Vorreiter Pedersen
f37b3e77ff Merge branch 'main' into remove-mad-support-for-variables 2026-06-30 17:38:37 +01:00
Geoffrey White
b5ec9c25c0 Update rust/ql/lib/codeql/rust/security/HardcodedCryptographicValueExtensions.qll
Co-authored-by: Tom Hvitved <hvitved@github.com>
2026-06-30 16:16:45 +01:00
Geoffrey White
9e37ae02fd Rust: Repair results for const accesses with no definition in the database. 2026-06-30 15:55:28 +01:00
Geoffrey White
c81d31f2e3 Rust: Flag const sources at the definition, not the use (clearer source). 2026-06-30 15:46:12 +01:00
Taus
f251a572e1 Python: hotfix - disable instanceFieldStep to avoid type-tracker blowup
The `instanceFieldStep` disjunct of `TypeTrackingInput::levelStepCall`
that was added in 7.2.0 uses `classInstanceTracker(cls)` -- which is
itself a type-tracker -- inside `levelStepCall`. That creates a
structural mutual recursion between the main type-tracker fixpoint and
`classInstanceTracker`, causing the type-tracker delta to blow up to
~100M tuples per iteration on some OOP-heavy Python codebases.
Verified on the python/mypy database: SSRF query wall time goes from
~12s before the offending commit to >40 minutes after it.

This hotfix temporarily drops the `instanceFieldStep` disjunct and
keeps only `inheritedFieldStep`, which does not pull on the call
graph and is well-behaved (verified at ~12s on mypy). The
`instanceFieldStep` helper predicate itself is kept in place, and
the `levelStepCall` body has a commented-out call to it so the
change is trivial to re-enable once the recursion issue is properly
addressed.
2026-06-30 14:41:12 +00:00
Nora Dimitrijević
43cfa2f8bd C#: Remove [[ style links from XSS sink explanation
Remove the makeUrl predicate and the [[""|""]]] link syntax from
AspxCodeSink.explanation(), replacing with plain text.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-30 16:14:12 +02:00
Geoffrey White
ca4f751f9b Rust: Add more tests for constants. 2026-06-30 15:13:10 +01:00
Mathias Vorreiter Pedersen
b7b731bab7 Merge branch 'main' into mad-write-through-model 2026-06-30 15:12:02 +01:00
Mathias Vorreiter Pedersen
c045da01a1 Merge pull request #22088 from MathiasVP/cpp-support-fully-qualified-field-names-in-mad
C++: Support fully qualified field names in MaD
2026-06-30 15:02:16 +01:00
Asger F
a9617f18a1 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-30 15:48:15 +02:00
Asger F
8a46f03308 Merge pull request #22083 from asgerf/unified/suites
Unified: add default_queries and standard qls files and a dummy query
2026-06-30 15:37:53 +02:00
Asger F
fc94d1c035 unified: Add a dummy query
This is just to test DCA
2026-06-30 15:26:22 +02:00
Michael Nebel
a93501a1eb Merge pull request #22033 from michaelnebel/csharp/usefeedmanager
C#: Use the feed manager in the `NugetExeWrapper`.
2026-06-30 15:03:25 +02:00
Mathias Vorreiter Pedersen
06f54d1bbb C++: Add a TODO comment to remove support for unqualified field names. 2026-06-30 13:55:26 +01:00
Mathias Vorreiter Pedersen
396bea6e6a Update cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowSummaryImpl.qll
Co-authored-by: Tom Hvitved <hvitved@github.com>
2026-06-30 13:44:14 +01:00
Asger F
a43c5cee61 unified: Add inline expectation test library 2026-06-30 14:29:04 +02:00
Mathias Vorreiter Pedersen
0e05ea5153 C++: Remove whitespace. 2026-06-30 12:41:29 +01:00
Mathias Vorreiter Pedersen
8657c8b26e C++: Add change note. 2026-06-30 12:39:34 +01:00
Mathias Vorreiter Pedersen
449a3ac870 C++: Delete tests which are no longer relevant. 2026-06-30 12:39:31 +01:00
Mathias Vorreiter Pedersen
fc954c3e1a C++: Remove support for marking variables as sources and sinks in MaD. 2026-06-30 12:30:40 +01:00
Mathias Vorreiter Pedersen
81ed5c59d7 C++: Add change note. 2026-06-30 11:54:58 +01:00
Asger F
8d564d31e6 unified: Add default_queries 2026-06-30 12:34:45 +02:00
Asger F
cbcf85a953 unified: Add standard query suites
The suites include 'Unified' in their name. It sounds a bit off but
it might cause confusion if we don't include some kind of language name
in there.
2026-06-30 12:34:43 +02:00
Geoffrey White
c0871defe9 Merge pull request #22077 from geoffw0/javainline
Java: Address testFailures in inline expectations tests
2026-06-30 10:49:24 +01:00
Asger F
be39051c29 Merge pull request #22086 from asgerf/asgerf-unified-corpus-test-split
Unified: Split up corpus tests and their generated outputs
2026-06-30 11:49:10 +02:00
Owen Mansel-Chan
8447b76c12 Merge pull request #22006 from owen-mc/go/more-slog-models
Go: more models for `log.slog`
2026-06-30 10:39:48 +01:00
Owen Mansel-Chan
3d8991a4db Update change note 2026-06-30 09:35:23 +01:00
Owen Mansel-Chan
4a7afb7aeb Add data flow consistency test output 2026-06-30 09:35:19 +01:00
Tom Hvitved
37d2224b9d Merge pull request #22082 from hvitved/shared/final-tree-sitter-classes
Shared: Generate `final` tree-sitter classes
2026-06-30 09:09:42 +02:00
Owen Mansel-Chan
0a737c97f3 Expand log.slog models and add more tests 2026-06-30 08:01:06 +01:00
Asger F
28f0be5c67 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-30 07:17:23 +02:00
Geoffrey White
f353a17431 Merge pull request #22081 from geoffw0/rubyinline2
Ruby: Address testFailures in inline expectations tests (part 2)
2026-06-29 19:37:28 +01:00
Mathias Vorreiter Pedersen
caaed72288 C++: Hide summary nodes that should be hidden and accept test changes. 2026-06-29 18:30:03 +01:00
Mathias Vorreiter Pedersen
08c383df6a C++: Accept test changes. 2026-06-29 18:20:10 +01:00
Mathias Vorreiter Pedersen
2625c304bf C++: Support fully qualified field names in MaD. 2026-06-29 18:02:20 +01:00
Mathias Vorreiter Pedersen
49bde567dd C++: Add tests with qualified names in MaD. 2026-06-29 18:02:17 +01:00
Geoffrey White
d519f79703 Update ruby/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll
Co-authored-by: Tom Hvitved <hvitved@github.com>
2026-06-29 15:37:45 +01:00
Asger F
12bd3e2860 unified: Bulk migrate all corpus tests to the new system 2026-06-29 15:01:22 +02:00
Asger F
3e1ca82cbf unified: Split corpus tests into source code and generated output
The corpus tests interleaved hand-written content (test cases) with
generated content (printed ASTs).

This made merge conflicts hard to resolve because you can't just
regnerate the printed ASTs without potentially throwing away new test
cases that came from either branch (or depending on whether the merge
conflict markers appeared, the corpus test could be ruined completely).

The old design did have one nice advantage: Reviewers could see the
printed ASTs alongside the source code from which it was generated.

To preserve this feature, the source code for the test case is itself
included in the generated output file.
2026-06-29 15:01:20 +02:00
Taus
f1cc1e5c47 Merge pull request #22084 from github/tausbn/yeast-miscellaneous-cleanup
yeast: Miscellaneous cleanup
2026-06-29 14:14:24 +02:00
Tom Hvitved
bfc37e547f Shared: Generalize typeConstraintBaseTypeMatch 2026-06-29 13:57:03 +02:00
Tom Hvitved
f14a5678be Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-29 13:32:14 +02:00
copilot-swe-agent[bot]
041a8e6adc Fix source_text call in @@raw_lhs documentation example 2026-06-29 11:26:07 +00:00
Taus
fb424020af yeast: Delete the Cursor trait, inline its methods on AstCursor
The trait had a single implementor (`AstCursor`), three type parameters
of which one (`T`) was never used in any method signature, and one
external consumer that needed `use yeast::Cursor;` in scope just to
call methods on the cursor. The abstraction was overhead without a
second implementor to justify it.

Move the six trait methods to an inherent `impl AstCursor` block;
delete `shared/yeast/src/cursor.rs`, the `pub mod cursor;` and
`pub use cursor::Cursor;` lines in `lib.rs`, and the `use yeast::Cursor;`
in `tree-sitter-extractor`'s `traverse_yeast`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-29 10:34:36 +00:00
Taus
bda8e7dae1 yeast-macros: Remove unused .map and .reduce_left chain syntax
The `{expr}.map(p -> tpl)` and `{expr}.reduce_left(first -> init, acc,
elem -> fold)` post-fix chains on `{expr}` placeholders had no
remaining users in the codebase: `.map` was never used, and the
4 `.reduce_left` sites in `swift.rs` were rewritten to plain
`Iterator::reduce` via an `and_chain` helper in an earlier commit.

Removes the entire `parse_chain_suffix` function (~90 lines) and the
`has_chain` detection / dispatch branches at the two call sites
(field-position in `parse_direct_node_inner` and body-position in
`parse_direct_list`). The remaining `{expr}` path is the
trait-dispatched one introduced by the splice-syntax cleanup, which
handles single ids and iterables uniformly via `IntoFieldIds`.

Also strips the chain syntax from the `tree!` macro doc comment.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-29 10:34:36 +00:00
Taus
37c8111c18 yeast-macros: Add error message to defensive expect_ident in parse_ctx_or_implicit
The empty error string passed to `expect_ident` was dead code (the
preceding lookahead has already confirmed the token is an ident),
but it would have been a confusing message if it ever fired. Replace
with an explicit "unreachable" string that makes the intent
clearer to readers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-29 10:34:36 +00:00
Taus
807bb51df7 yeast: Unify Node::kind() and Node::kind_name()
Both accessors returned the same private `kind_name: &'static str`
field; `kind_name()` is widely used (mainly by dump.rs and schema
diagnostics) and `kind()` had only 2 internal callers in lib.rs and
a handful in tests. Pick the more descriptive name and update the
callers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-29 10:34:36 +00:00
Taus
b6abfe6e5c yeast: Remove dead prepend_field / prepend_field_child
`BuildCtx::prepend_field` and the underlying `Ast::prepend_field_child`
existed to support the create-then-mutate pattern in swift.rs (build
an output node, then prepend modifiers to its `modifier:` field). The
SwiftContext-based refactor on the previous branches eliminated all
such call sites: every emitted declaration now carries its modifiers
from birth, so the in-place prepend operation has no users.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-29 10:34:35 +00:00
Taus
b3dc7009a4 yeast: Remove dead BuildCtx::translate_opt
`translate_opt` was a convenience for the manual_rule! body code,
collapsing `Option<I>` to `Option<Id>` via `translate`. Since the
`@@` raw-capture migration replaced manual_rule! with rule!, no
callers remain — the auto-translate prefix handles `Option<Id>`
captures directly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-29 10:34:35 +00:00
Taus
e59f646870 yeast: Remove dead Captures methods
`Captures::map_captures`, `Captures::map_captures_to`, and
`Captures::try_map_all_captures` had no callers. The last one was
subsumed by `try_map_captures_except` (which takes a skip list and
degenerates to the old behaviour when the list is empty).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-29 10:34:35 +00:00
Taus
cc3c232631 yeast: Replace {..expr} splice syntax with trait-dispatched {expr}
In the initial implementation of yeast, the splice syntax was needed do
distinguish between splicing multiple nodes or just a single node.
However, this was always an ugly "wart" in the syntax, since the user
shouldn't have to worry about these things.

To fix this, we add an `IntoFieldIds` trait that dispatches on the
value's type: `Id` pushes a single id, and a blanket impl for
`IntoIterator<Item: Into<Id>>` handles `Vec<Id>`, `Option<Id>`, and
arbitrary iterator chains.

With this, we no longer need to use the special splice syntax, and hence
we can get rid of it.
2026-06-29 10:34:35 +00:00
Taus
9a5cc3c5e3 yeast: Make Id a newtype, delete NodeRef
Previously, the `Id` type  was a bare usize alias. The `NodeRef` newtype
existed solely to carry the AST-aware `YeastDisplay` /
`YeastSourceRange` impls (so that `#{captured_node}` rendered source
text rather than the numeric id) without colliding with the impls for
raw integer types.

This commit promotes `Id` itself to a (transparent) newtype struct and
moves the AST-aware trait impls directly onto it. With `Id` and `usize`
now being different types, the integer-display impl (for `usize`) and
the source-text impl (for `Id`) coexist without conflict, and `NodeRef`
becomes redundant (and so we remove it).
2026-06-29 10:33:32 +00:00
Taus
3983e4db29 Merge pull request #22070 from github/tausbn/yeast-add-raw-capture-syntax
yeast: Extend `rule!` macro with support for raw captures
2026-06-29 12:28:53 +02:00
Geoffrey White
72f1a0d89b Ruby: Clean up the CodeQL a little more. 2026-06-29 11:22:02 +01:00
Geoffrey White
96e88a1f9a Ruby: Inline AnyComment class into ExpectationComment. 2026-06-29 11:21:42 +01:00
Geoffrey White
3058198c0d Merge pull request #22078 from geoffw0/rubyinline
Ruby: Address testFailures in inline expectations tests (part 1)
2026-06-29 11:06:10 +01:00
Tom Hvitved
d985c48e84 Unified: Regenerate Ast.qll 2026-06-29 12:06:09 +02:00
Tom Hvitved
330bb17d69 QL4QL: Regenerate TreeSitter.qll 2026-06-29 12:05:42 +02:00
Tom Hvitved
818a25b64e Ruby: Regenerate TreeSitter.qll 2026-06-29 12:05:41 +02:00
Tom Hvitved
4237a76251 Shared: Generate final tree-sitter classes 2026-06-29 12:05:39 +02:00
Asger F
2ef06c9f96 Merge pull request #22080 from asgerf/unified/commonast-followups
unified: Add or_pattern and fix 'if case let' translation
2026-06-29 12:05:08 +02:00
Geoffrey White
727f7d2afa Fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-29 10:58:45 +01:00
Geoffrey White
8fc2f7c92e Kotlin: Update .expected to exactly match reality. 2026-06-29 10:57:05 +01:00
Geoffrey White
3c5f70de11 Ruby: And another missing tag. 2026-06-29 10:37:21 +01:00
Asger F
1842382e23 unified: regenerate QL 2026-06-29 11:06:14 +02:00
Asger F
db449dca6a unified: Fix handling of 'if case let' 2026-06-29 11:03:20 +02:00
Asger F
7216d12b9a unified: Avoid singleton or_pattern in Swift switch case mapping 2026-06-29 11:03:20 +02:00
Asger F
c4b4fde0d7 unified: Make switch_case pattern optional; add or_pattern disjunction node 2026-06-29 11:03:00 +02:00
Geoffrey White
35cd0f829f Kotlin: Address inline expectations testFailures. 2026-06-29 09:56:48 +01:00
Tom Hvitved
299c8cd914 Rust: Add more type inference tests 2026-06-29 09:44:02 +02:00
Geoffrey White
c0c8958db1 Ruby: Implement inline expectation comments for .erb files. 2026-06-26 19:14:03 +01:00
Geoffrey White
0ee40417ea Ruby: Add inline expectation comment to .erb file. 2026-06-26 19:14:01 +01:00
Geoffrey White
46382cbc8e Ruby: Address more inline expectation testFailures. 2026-06-26 17:56:37 +01:00
Mario Campos
da3d0cf977 Merge pull request #22062 from github/mario-campos/mirror-maven-central/gradle
Replace `jcenter()` and `mavenCentral()` with Maven Central mirror URL
2026-06-26 11:35:10 -05:00
Geoffrey White
93439db87b Ruby: Address inline expectation testFailures. 2026-06-26 17:11:56 +01:00
Geoffrey White
897d16929b Java: Add missing $ Source annotations. 2026-06-26 16:22:05 +01:00
Geoffrey White
6f997ae15c Java: Label spurious results. 2026-06-26 16:22:03 +01:00
Geoffrey White
300e48e48e Java: Move $ Source annotations that were incorrectly placed. 2026-06-26 16:21:49 +01:00
Geoffrey White
f840f6104a Java: Make some $ Source annotations query specific. 2026-06-26 16:21:46 +01:00
Taus
70ca7af04c Address PR review comments
- unified/swift: Mark `binding_kind` as a raw `@@` capture in the
  property_declaration rule. It is only used to read its source text
  (`ctx.ast.source_text`), never as a translated node. With `@` the
  auto-translate prefix would route the unnamed `let`/`var` token
  through the catch-all `_ @node => {node}` fallback for a no-op
  roundtrip; `@@` makes the intent explicit and removes that reliance.

- shared/yeast/tests: Reword a stale comment in test_raw_capture_marker.
  The text claimed a "second assertion" exists in this test, but the
  explicit-translation check actually lives in the companion
  test_raw_capture_marker_explicit_translate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-26 13:30:01 +00:00
Mathias Vorreiter Pedersen
7861e9e596 Java: Fix a library test. 2026-06-26 14:18:23 +01:00
Taus
664f0125b9 yeast: Remove now-unused manual_rule!
The `manual_rule!` macro is now fully subsumed by `rule!` + `@@name`, so
this commit simply gets rid of the now no longer needed code.
2026-06-26 12:07:22 +00:00
Taus
1b7f589000 unified/swift: Migrate manual_rule! sites to rule! + @@
With `@@name` available, there's no longer a need to use `manual_rule!`.
Every place where it is used, we can instead just mark the relevant raw
captures as such. This results in quite a lot of cleanup! (Also, to me
at least, it makes these rules a lot easier to reason about.)

A first iteration of this approach resulted in a lot of
`.map(Into::into)` being needed, because `SwiftContext` stores `Id`s,
but captures produce `NodeRef`s. To avoid this, I swapped it around so
that the context stores `NodeRef`s. This does require adding `.into()`
in a few places, but it makes the rest of the code a lot more ergonomic.
2026-06-26 12:07:22 +00:00
Taus
eb7f8cc43d yeast: Add @@name raw-capture syntax to rule!
The `@@name` capture marker in `rule!` queries skips the
auto-translate prefix for that specific capture, letting the body see
the original capture (and thus delay its translation using
`ctx.translate` until it becomes convenient).

Regular `@name` captures continue to be auto-translated as before.
Specifically these are translated _eagerly_, before the main body of the
rewrite rule is run.

I settled on `@@` as the syntax because it did not add new symbols that
the user has to keep track of (it's still a kind of capture), but it's
still visually distinct enough that the user should be able to tell that
there's something special going on. In principle one could accidentally
write one form of capture where the other was intended, but in practice
this would result in code that did not compile (because the types would
not match).
2026-06-26 12:07:21 +00:00
Asger F
2767b8dbbf Merge pull request #22069 from asgerf/unified/build
unified: Make build work in Bazel again
2026-06-26 13:51:45 +02:00
Asger F
b1f60acf2c Merge pull request #22067 from asgerf/unified/printast
Unified: Generate PrintAst helper and implement PrintAst query
2026-06-26 13:51:16 +02:00
Asger F
2b2613de4e unified: Make build work in Bazel again 2026-06-26 13:09:12 +02:00
Geoffrey White
95e030f4e3 Rust: Detect constant accesses and perform very limited constant propagation. 2026-06-26 11:57:16 +01:00
Geoffrey White
8155ff7a4f Rust: Add a few more test cases for constants / constant propagation. 2026-06-26 11:34:06 +01:00
Asger F
14acc7fcab unified: Fixup generated QL
The previous commit was generated from a wrong checkout
2026-06-26 12:04:51 +02:00
Owen Mansel-Chan
37ce885b0c Merge pull request #22064 from owen-mc/go/fix-test-failures
Go: fix tests with non-empty `testFailures`
2026-06-26 10:45:14 +01:00
Mathias Vorreiter Pedersen
caef09bf8e Shared: Fix grammar. 2026-06-26 10:43:18 +01:00
Taus
52acaec03d Merge pull request #22054 from github/tausbn/yeast-context-reification 2026-06-26 11:01:19 +02:00
Asger F
d6e8555f8b Shared: auto-format tree sitter extractor 2026-06-26 10:48:11 +02:00
Asger F
b5ef15c70f QL4QL: Regenerate raw AST 2026-06-26 10:29:17 +02:00
Asger F
5735ac330d Ruby: Regenerate raw AST 2026-06-26 10:29:08 +02:00
Asger F
5348c7d07c unified: Add PrintAst query 2026-06-26 10:28:55 +02:00
Asger F
f89f304e50 unified: Regenerate AST 2026-06-26 10:28:55 +02:00
Asger F
ff7dc297d5 Shared: Generate PrintAst helper in tree sitter extractor
Auto-generating a helper for implementing the PrintAST query on top of the generated AST.
2026-06-26 10:28:06 +02:00
Asger F
cacdc467de Merge pull request #22036 from forks-felickz/felickz/js-angular-hostlistener-postmessage
JavaScript: Recognize Angular @HostListener('window:message') as a postMessage handler
2026-06-26 10:09:42 +02:00
Owen Mansel-Chan
7b800b1dd6 Merge pull request #22065 from github/dependabot/go_modules/go/extractor/extractor-dependencies-9f88df4328
Bump golang.org/x/tools from 0.46.0 to 0.47.0 in /go/extractor in the extractor-dependencies group
2026-06-26 06:59:52 +01:00
Mario Campos
1b6ff24642 Fix buildless-fetches.expected for buildless-sibling-projects 2026-06-25 22:57:35 -05:00
dependabot[bot]
3d1b6b64ed Bump golang.org/x/tools
Bumps the extractor-dependencies group in /go/extractor with 1 update: [golang.org/x/tools](https://github.com/golang/tools).


Updates `golang.org/x/tools` from 0.46.0 to 0.47.0
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.46.0...v0.47.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-26 03:03:16 +00:00
Owen Mansel-Chan
ac618e1cb2 Expand FileNameSource for stored xss 2026-06-25 22:50:21 +01:00
Mario Campos
221a54d22e Add Maven Central mirror settings for Maven test project buildless-sibling-projects 2026-06-25 21:44:20 +00:00
yoff
5fcaac7cb2 Merge pull request #21869 from yoff/python/support-flask-subclasses
Python: Support Flask subclasses
2026-06-25 23:42:21 +02:00
Mario Campos
cc215858e4 Fix expected URL fetches for buildless-sibling-projects 2026-06-25 21:12:33 +00:00
Mario Campos
56a1b12c9e Delete extra blank line
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-25 15:01:20 -05:00
Mario Campos
688213056c Replace deprecated jcenter() with Maven Central mirror URL for dependency resolution in Gradle build scripts 2026-06-25 19:02:43 +00:00
Mario Campos
1c37688ec1 Replace mavenCentral() with Maven Central mirror URL for dependency resolution in Gradle build scripts 2026-06-25 19:02:37 +00:00
Mario Campos
336df3ccf4 Merge pull request #22060 from github/post-release-prep/codeql-cli-2.26.0
Post-release preparation for codeql-cli-2.26.0
2026-06-25 12:43:54 -05:00
Owen Mansel-Chan
587f9c24ed Fix inline test expectations comments 2026-06-25 18:11:03 +01:00
Mathias Vorreiter Pedersen
84a3435c12 Shared: Remove useless existential. 2026-06-25 17:42:10 +01:00
github-actions[bot]
456e33773b Post-release preparation for codeql-cli-2.26.0 2026-06-25 16:24:06 +00:00
Mario Campos
7c73de0e3c Merge pull request #22059 from github/release-prep/2.26.0
Release preparation for version 2.26.0
2026-06-25 10:31:50 -05:00
Taus
af7ae8c4cb Apply rustfmt
Format the touched Rust crates (shared/tree-sitter-extractor,
shared/yeast, shared/yeast-macros, unified/extractor) so the
tree-sitter-extractor CI fmt check passes. No functional changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-25 17:28:24 +02:00
Taus
1c4552edb0 unified/swift: Use tree! instead of ctx.node
Cleans up a few places where we were constructing trees piece by piece
rather than using the `tree!` macro.

In the process, Copilot noticed an issue that should probably be
addressed: the labeled_statement rule can never fire, since there are no
such nodes in the input. This is possibly a simple as making
_labeled_statement (which _does_ exist) named, but I haven't attempted
this.

Finally, a small change to yeast makes it so that the contents of a {}
interpolation can be a Rust block (previously it could only be a single
expression). This avoids the need to double-wrap instances where you
want to interpolate a single node produced as the final value of some
block.
2026-06-25 17:28:24 +02:00
Taus
5136d872ae unified/swift: Replace reduce_left with Rust helpers
(Both reduce_left and map are still supported, but we could remove them
at this point.)

I think this way of writing things makes the intent a lot clearer -- it
avoids extending the yeast rule language with complicated constructs,
pushing the complexity (such as it is) into Rust instead.
2026-06-25 17:28:24 +02:00
Taus
474bcd4dd1 unified/swift: Propagate property_declaration modifiers via context
Gets rid of the final uses of mutation (via prepend_field). The approach
is the same as in the preceding commits: we set the appropriate fields
on the context when processing the outer node, and then access these
fields on the inner nodes.

The repeated use of `modifier` fields is a _bit_ clunky, but since we're
likely moving to an out-of-band modifier mechanism at some point, I
think it's good enough for now.
2026-06-25 17:28:24 +02:00
Taus
199489a225 unified/swift: Propagate enum_entry outer modifiers via context
Same as in the preceding commit, we added a test beforehand for testing
this syntax, and verified that it was unchanged by the cleanup in this
commit.
2026-06-25 17:28:24 +02:00
Taus
ae4ccc651c unified/swift: Translate protocol properties using context
Avoids more "mutation after creation" via prepend_field.

Also adds a test to the corpus for exercising this syntax. Although it's
not evident, the test output was unchanged by this refactoring.
2026-06-25 17:28:24 +02:00
Taus
0d845c2ea9 unified/swift: Propagate parameter default values via context
Extends the context with a field for keeping track of the default value.

In the process, we also rename the context to SwiftContext as it now
doesn't only concern itself with properties.
2026-06-25 17:28:24 +02:00
Taus
6d138c2bd4 yeast: Simplify Swift rules using the new machinery
Propagates in name and type information for various property
declarations, using the context mechanism. This avoids mutating
already-translated nodes in-place, and is generally much easier to read.
2026-06-25 17:28:24 +02:00
Taus
85c39c04e0 yeast: Hide desugaring behind Desugarer trait
This was necessary since otherwise the generic type of the
user-specified context (which should only be a concern for yeast) starts
to bleed out into the shared extractor. Instead, we type-erase it by
putting it inside the aforementioned trait.
2026-06-25 17:28:24 +02:00
Taus
1ee142d8bd yeast: Add macro for fine-grained rules
Adds `manual_rule!` which provides a more low-level interface for
defining rewrites. (I'm not entirely sold on the name, so any
suggestions would be welcome.)

Notably, the captures bound in the body of such rules have _not_ been
translated yet -- they still come from the _input_ tree. It is the
user's duty to call ctx.translate on these (which has the effect of
recursively invoking the translation) before substituting them into the
output.

For _truly_ low-level access, the user can still construct a Rule
directly, but this is now somewhat cumbersome as the closure contained
therein takes quite a few parameters. Still, the possibility remains.
2026-06-25 17:28:24 +02:00
Taus
a523c7f47f yeast: Pass raw captures to Rule::new rules
This enables users to specify how and when these captures get
translated. In conjunction with the context mechanism, this can be used
to e.g. translate some piece of information (e.g. the type of
something), record it in the context, and then recursively translate
some other capture that relies on this information. This allows
information to be cleanly passed into descendants (which can be written
using context accesses in the `rule!` macro form).

As a consequence of this change, we now need to pass around a
TranslatorHandle to perform the manual translation. For Repeating rules,
it doesn't really make sense to translate things, so in this case we
simply signal an error.

Also, the implementation of the `rule!` macro changes slightly (without
changing semantics): it now essentially delegates to `Rule::new`,
receiving raw captures, but then immediately applies the translation to
those captures (which, for the majority of cases, is likely the desired
behaviour).
2026-06-25 17:28:24 +02:00
Taus
5f73754b95 yeast: Make transforms return Result
This will enable us to actually capture and log errors in complicated
rules (e.g. ones written in Rust) rather than just panicking.
2026-06-25 17:28:24 +02:00
Taus
e0fa6cf785 yeast: Reify the context and allow user-defined data in it
Renames what was previously called `__yeast_ctx` into just `ctx`, and
adds a new field `user_ctx` to this context. Said field can contain a
struct of any user type (necessitating making various parts of the
implementation generic in said type).

Through some Deref magic, field accesses are delegated to the inner
struct (assuming they are not already defined on `ctx`), which should
hopefully make the interface a bit more ergonomic.
2026-06-25 17:28:24 +02:00
github-actions[bot]
237c5639e2 Release preparation for version 2.26.0 2026-06-25 15:27:00 +00:00
Asger F
73ad826d44 Merge pull request #22016 from asgerf/commonast-rebased5
Unified/swift: new AST spec and Swift mappings
2026-06-25 16:59:29 +02:00
Michael B. Gale
cc83856c5e Merge pull request #22058 from github/codeql-cli-2.25.6
Mergeback #21947 into `main`
2026-06-25 15:57:19 +01:00
Geoffrey White
0fbab225ce Merge pull request #22056 from geoffw0/codequal
Rust: Remove some redundant imports / casts
2026-06-25 15:52:15 +01:00
Geoffrey White
3403cffe51 Rust: More-or-less the Copilot suggestion. 2026-06-25 15:22:15 +01:00
Geoffrey White
4aa53b6be9 Update rust/ql/lib/codeql/rust/security/HardcodedCryptographicValueExtensions.qll
Co-authored-by: Tom Hvitved <hvitved@github.com>
2026-06-25 15:16:38 +01:00
Geoffrey White
ca09327384 Rust: Remove more pointless imports. 2026-06-25 14:51:13 +01:00
Jeroen Ketema
969ab78225 Merge pull request #22048 from github/jketema/kotlin1-pytest
Kotlin: Update tests to use new `kotlin_2_3_20` fixture
2026-06-25 15:01:33 +02:00
Paolo Tranquilli
b67644c127 Merge pull request #21986 from JarLob/userpermissions
Actions: Fix dominates() false positive in reusable workflows
2026-06-25 14:44:17 +02:00
Geoffrey White
20b4cbe72e Rust: Remove pointless imports of codeql.util.Unit. 2026-06-25 12:51:43 +01:00
Tom Hvitved
b582844f96 Merge pull request #22049 from hvitved/csharp/dead-store-cleanup
C#: Remove redundant code from `DeadStoreOfLocal.ql`
2026-06-25 13:51:21 +02:00
Geoffrey White
b9a132dac6 Rust: Remove redundant cast. 2026-06-25 12:51:18 +01:00
Geoffrey White
351d4954d7 Rust: Change note. 2026-06-25 12:26:40 +01:00
Geoffrey White
4bda03fe8d Rust: Make arithmetic operations a barrier for rust/hard-coded-cryptographic-value (including string concatenation). 2026-06-25 12:19:08 +01:00
Asger F
89cd6770ae Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-25 13:18:27 +02:00
Jeroen Ketema
9b2e6077f1 Kotlin: Address review comments 2026-06-25 12:58:27 +02:00
Michael Nebel
18913ce4b8 C#: Add change-note. 2026-06-25 11:50:49 +02:00
Michael Nebel
a45ef5845a C#: Address review comments. 2026-06-25 11:50:47 +02:00
Michael Nebel
d32c4d838d C#: Make the NuGetExeWrapper respect the CheckFeeds flag, private registries configuration and provide sources via the command line instead of creating a file. 2026-06-25 11:50:44 +02:00
Michael Nebel
8042fba94a C#: Inject the feed manager into the NugetExeWrapper. 2026-06-25 11:50:42 +02:00
Michael Nebel
bbad4f6069 C#: Take a the feed logic out of the try/catch for NuGet downloading. 2026-06-25 11:50:40 +02:00
Tom Hvitved
929fa1e977 C#: Remove redundant code from DeadStoreOfLocal.ql 2026-06-25 08:50:40 +02:00
Jeroen Ketema
f6b3d1eade Kotlin: Remove unneeded pytest imports 2026-06-24 23:34:39 +02:00
Jeroen Ketema
402c0f89bc Kotlin: Update tests to use new kotlin_2_3_20 fixture 2026-06-24 22:50:32 +02:00
Jaroslav Lobačevski
7fc4b4856e Fix formatting 2026-06-24 17:17:16 +00:00
Paolo Tranquilli
4b8cb3ffac Fix false negative for branching nested reusable workflows
The previous fix required all outermost callers of a reusable workflow to
be protected, which collapsed distinct safe/unsafe inner paths that share
the same outermost caller. Track protection per caller chain instead: a
node inside a reusable workflow is only considered protected if there is
no unprotected caller path up to an outer workflow.

Adds a branching nested regression test where one inner job is protected
by a permission check and a sibling inner job is not.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-24 18:22:01 +02:00
Geoffrey White
0c72a2b982 Add test cases involving string appends. 2026-06-24 17:09:27 +01:00
Mathias Vorreiter Pedersen
933338f627 C++: Accept test changes. 2026-06-23 20:33:34 +01:00
Mathias Vorreiter Pedersen
662f522032 C++: Properly instantiate the new reverse flow feature. 2026-06-23 20:33:31 +01:00
Mathias Vorreiter Pedersen
a4e3761dea Swift: Fixes after changes to the flow summary API. 2026-06-23 20:33:29 +01:00
Mathias Vorreiter Pedersen
8129107ebf Rust: Fixes after changes to the flow summary API. 2026-06-23 20:33:26 +01:00
Mathias Vorreiter Pedersen
09c7329488 Ruby: Fixes after changes to the flow summary API. 2026-06-23 20:33:24 +01:00
Mathias Vorreiter Pedersen
f9e1305da3 Python: Fixes after changes to the flow summary API. 2026-06-23 20:33:22 +01:00
Mathias Vorreiter Pedersen
be56df7ad1 JS: Fixes after changes to the flow summary API. 2026-06-23 20:33:19 +01:00
Mathias Vorreiter Pedersen
9865b66308 Java: Fixes after changes to the flow summary API. 2026-06-23 20:33:17 +01:00
Mathias Vorreiter Pedersen
e8fee23093 Go: Fixes after changes to the flow summary API. 2026-06-23 20:33:14 +01:00
Mathias Vorreiter Pedersen
bf50e377c5 C#: Fixes after changes to the flow summary API. 2026-06-23 20:33:10 +01:00
Mathias Vorreiter Pedersen
076b01cbfc C++: Fixes after changes to the flow summary API. 2026-06-23 20:33:08 +01:00
Mathias Vorreiter Pedersen
bb2ec1240a Shared: Support "reverse flow" summaries. That is, summaries starting from the return value of a call. 2026-06-23 20:33:04 +01:00
Mathias Vorreiter Pedersen
03c3ef9528 C++: Add tests with missing reverse flow. 2026-06-23 19:48:21 +01:00
Jaroslav Lobačevski
31f6e713c5 Fix "The variable event is only used in one side of disjunct." 2026-06-23 12:06:01 +00:00
Jaroslav Lobačevski
e2347a5c7d Fix for independent checks 2026-06-23 11:52:11 +00:00
Chad Bentz
d1d9df7729 Address review: restrict @HostListener handler to window/document message targets
Drop the plain 'message' event name from the @HostListener matcher. The
postMessage 'message' event is dispatched on window and does not bubble, so an
element-level @HostListener('message') does not receive cross-window messages.
Keeping only 'window:message' and 'document:message' makes the model more
precise and matches the accompanying comment and change note.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-22 21:35:21 -04:00
Chad Bentz
9bffcf81b5 JavaScript: Recognize Angular @HostListener('window:message') as a postMessage handler
Angular registers window message handlers via the
@HostListener('window:message', ['\']) decorator rather than
window.addEventListener('message', ...). The PostMessageEventHandler class
only modeled the addEventListener and window.onmessage forms, so the decorated
handler's event parameter was never treated as a message source. As a result,
js/missing-origin-check produced no alert and the event was not a client-side
remote flow source for downstream queries (e.g. client-side URL redirection).

Extend PostMessageEventHandler to also recognize methods decorated with
@HostListener for 'window:message', 'document:message', or 'message'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-22 21:21:15 -04:00
Asger F
66c1f037f5 Add TODO 2026-06-19 12:19:51 +02:00
Asger F
2675070291 unified/swift: Clean up translation of patterns
Patterns have an unusual parse tree, but now the matching should
at least be a bit easier to follow.

The TODO regarding not being able to pass down context to handle
var/let is still relevant, and can't be solved in the mapping alone.
2026-06-19 11:35:06 +02:00
Asger F
c01264d05c Coerce pattern_element.key to be an identifier 2026-06-19 10:31:34 +02:00
Asger F
63e1cc90e9 Test: add corpus test for switch case patterns with labeled arguments
Adds a test case 'Switch with labeled case pattern arguments' covering:
- case .implicit(isAcknowledged: false) — labeled bool literal
- case .thread(threadRowId: _, let rowId) — labeled wildcard + binding

The current output contains type errors: pattern_element::key is being
produced as name_expr instead of identifier. These will be fixed in the
following commit.
2026-06-19 10:27:20 +02:00
Asger F
2182265120 unified/swift: Better source range for inferred_type_expr 2026-06-18 14:57:55 +02:00
Asger F
0b666d47db Preserve the dot token in case patterns 2026-06-18 14:55:54 +02:00
Asger F
142ac47166 Refactor: map switch case patterns to constructor_pattern instead of tuple_pattern
Changed the desugaring rules to properly map case patterns with binding (e.g.,
'case .circle(let r):') to constructor_pattern nodes instead of tuple_pattern.

New rules added:
- tuple_pattern_item → pattern_element (preserves optional name/key)
- pattern.kind: binding_pattern → name_pattern (extracts bound identifier)
- pattern.kind: case_pattern → constructor_pattern (creates proper constructor
  with bound arguments as pattern_elements)

This provides a more semantically correct AST representation:
- Constructor name: name_expr identifier 'circle'
- Elements: pattern_element containing name_pattern identifier 'r'

Instead of the previous tuple_pattern string representation.

Updated control-flow.txt corpus outputs.
2026-06-18 14:54:59 +02:00
Asger F
2470c1388a Fix: preserve switch case patterns in desugared output
The switch_entry rule was capturing switch_pattern wrapper nodes instead of
drilling into them to extract the actual pattern nodes. This caused patterns
from switch cases to be lost during desugaring.

Changed the pattern match from:
  (switch_entry pattern: (switch_pattern)* @pats ...)
to:
  (switch_entry pattern: (switch_pattern pattern: @pats)* ...)

This now correctly extracts the pattern field from each switch_pattern node,
ensuring that patterns from cases like 'case 1:' and 'case .circle(let r):'
are preserved in the switch_case AST nodes.

Updated control-flow.txt corpus outputs to reflect the new behavior.
2026-06-18 14:37:42 +02:00
Asger F
fa98557dd9 Update QL test output 2026-06-18 14:26:49 +02:00
Asger F
1e167dfa6b unified/swift: add type and declaration-family mappings 2026-06-18 14:26:47 +02:00
Asger F
f362707493 unified/swift: Imports 2026-06-18 14:26:45 +02:00
Asger F
15208b70aa Unified: Add import_declaration.scoped_import_kind 2026-06-18 14:26:43 +02:00
Asger F
3522f35ab2 unified/swift: add collections, optionals/errors 2026-06-18 14:26:42 +02:00
Asger F
938396a751 unified/swift: add control-flow and loop mappings 2026-06-18 14:26:40 +02:00
Asger F
790d4f11be unified/swift: add closure and capture mappings 2026-06-18 14:26:38 +02:00
Asger F
8f747a355c unified/swift: add function and parameter mappings 2026-06-18 14:26:37 +02:00
Asger F
d17fd2d964 unified/swift: add variable/property/accessor and enum mappings 2026-06-18 14:26:35 +02:00
Asger F
4e9c3fb436 unified/swift: add literals, names, and operator expression mappings 2026-06-18 14:26:33 +02:00
Asger F
0e9d17b59c unified/swift: add top-level normalization and fallback scaffold 2026-06-18 14:26:31 +02:00
Asger F
6c74cd31e4 Yeast: use child locations instead of rule target
Previously, when a node was synthesized it would always take the
location from the node that matched the current rule. This resulted
in overly broad locations however.

For (foo #{bar}) we now take the location of the 'bar' node.

For non-leaf nodes we merge all its child node locations.
2026-06-18 14:26:30 +02:00
Asger F
166406acbb Unified: Elaborate a bit more on AGENTS.md 2026-06-18 14:26:28 +02:00
Asger F
b40cb5dedd Regenerate QL 2026-06-18 14:26:26 +02:00
Asger F
6dd7dedc19 Rewrite AST 2026-06-18 14:26:22 +02:00
Jaroslav Lobačevski
7f16853715 Remove trailing white space 2026-06-18 12:11:18 +00:00
Jaroslav Lobačevski
2d6feb1255 Fix false negatives when one of the jobs had proper checks and the other didn't 2026-06-18 12:02:56 +00:00
dependabot[bot]
880011ce13 Bump the pip group across 2 directories with 2 updates
Bumps the pip group with 1 update in the /misc/codegen directory: [pytest](https://github.com/pytest-dev/pytest).
Bumps the pip group with 1 update in the /python/ql/test/query-tests/Security/CWE-943-NoSqlInjection/PoC directory: [pymongo](https://github.com/mongodb/mongo-python-driver).


Updates `pytest` from 8.3.5 to 9.0.3
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.5...9.0.3)

Updates `pymongo` from 3.9 to 4.6.3
- [Release notes](https://github.com/mongodb/mongo-python-driver/releases)
- [Changelog](https://github.com/mongodb/mongo-python-driver/blob/master/doc/changelog.rst)
- [Commits](https://github.com/mongodb/mongo-python-driver/compare/3.9.0...4.6.3)

---
updated-dependencies:
- dependency-name: pytest
  dependency-version: 9.0.3
  dependency-type: direct:production
  dependency-group: pip
- dependency-name: pymongo
  dependency-version: 4.6.3
  dependency-type: direct:production
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-18 10:24:33 +00:00
Asger F
1d8e682e5f Reset mappings 2026-06-15 10:49:37 +02:00
Asger F
0baa126473 Add ability to prepend fields in Yeast 2026-06-15 10:49:35 +02:00
Asger F
d11b428292 yeast-macros: desugar 'field: @cap' to 'field: _ @cap'
When a field pattern has a bare capture with no preceding pattern
atom (i.e. `foo: @bar`), implicitly use a true wildcard (`_`,
match_unnamed: true) as the node pattern, making it equivalent to
`foo: _ @bar`.

This is a convenience shorthand: in practice every `field: _ @cap`
in the Swift rules can now be written more concisely as `field: @cap`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-15 10:49:33 +02:00
Asger F
ddc9516e92 Yeast: better support for rewriting unnamed nodes
- Ensure the full wildcard _ supports quantifiers
- Also rewrite unnamed nodes in one-shot phases
2026-06-15 10:49:31 +02:00
Asger F
00068948c1 yeast-macros: add .reduce_left(first -> init, acc, elem -> fold) chain
A left fold over an iterable where the first element seeds the accumulator:
- first -> init  : converts the first element to the initial accumulator
- acc, elem -> fold : fold step; acc = current accumulator, elem = next element
- Empty iterable produces nothing (0-element splice)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-15 10:49:29 +02:00
Asger F
28c879f58c yeast-macros: add .map(p -> tpl) chain syntax for tree templates
After a {expr} or {..expr} placeholder, an optional chain of
.<builtin>() calls may follow. Currently the only builtin is:

  .map(param -> template)

which applies the template to each element of the iterable and
collects the resulting node IDs. A chain auto-splices into the
enclosing field/child position.

Example:
  path: {parts}.map(p -> (identifier #{p}))

The framework is extensible: additional builtins can be added by
matching on the method name in parse_chain_suffix.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-15 10:49:27 +02:00
Jaroslav Lobačevski
d51a9a3e1a Support nested reusable workflows 2026-06-15 06:52:13 +00:00
Jaroslav Lobačevski
048884bb78 Remove redundant cast 2026-06-15 06:12:45 +00:00
Jaroslav Lobačevski
2eed6c1736 Fix dominates() false positive in reusable workflows 2026-06-15 05:42:59 +00:00
Jon Janego
2a8f295a65 Merge pull request #21947 from github/copilot/codeql-cli-2256
Fix changelog copy errors in change-notes and CHANGELOG.md files (codeql-cli-2.25.6)
2026-06-04 14:29:33 -05:00
copilot-swe-agent[bot]
b8501f1ec5 Fix changelog copy errors in change-notes and CHANGELOG.md files (codeql-cli-2.25.6) 2026-06-04 18:35:06 +00:00
copilot-swe-agent[bot]
3214253adb Initial plan 2026-06-04 18:29:50 +00:00
yoff
f7c4e61956 Apply suggestions from code review
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-02 15:12:41 +02:00
yoff
575ece6ae2 Python: Add change note 2026-06-02 13:50:31 +02:00
yoff
f6ed5c19be Python: fix sub class test 2026-06-02 13:50:31 +02:00
yoff
4298b70f1c Python: add test for sub class 2026-06-02 13:49:25 +02:00
yoff
e88b8c53f3 Python: Add test for instances 2026-06-02 13:49:24 +02:00
1922 changed files with 29651 additions and 19561 deletions

View File

@@ -1,3 +1,10 @@
## 0.4.38
### Bug Fixes
* GitHub Actions queries now better account for permission checks on jobs that call reusable workflows.
* The query `actions/pr-on-self-hosted-runner` was updated to the latest standard runner labels reducing false positive results.
## 0.4.37
### Minor Analysis Improvements

View File

@@ -1,4 +0,0 @@
---
category: fix
---
* The query `actions/pr-on-self-hosted-runner` was updated to the latest standard runner labels reducing false positive results.

View File

@@ -0,0 +1,6 @@
## 0.4.38
### Bug Fixes
* GitHub Actions queries now better account for permission checks on jobs that call reusable workflows.
* The query `actions/pr-on-self-hosted-runner` was updated to the latest standard runner labels reducing false positive results.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.37
lastReleaseVersion: 0.4.38

View File

@@ -42,6 +42,15 @@ string actor_not_attacker_event() {
]
}
/**
* Gets the outer caller of `ej`, i.e. the `ExternalJob` that calls the
* reusable workflow containing `ej`. Used with transitive closure to
* walk up nested reusable workflow chains.
*/
private ExternalJob getAnOuterCaller(ExternalJob ej) {
result = ej.getEnclosingWorkflow().(ReusableWorkflow).getACaller()
}
/** An If node that contains an actor, user or label check */
abstract class ControlCheck extends AstNode {
ControlCheck() {
@@ -53,43 +62,170 @@ abstract class ControlCheck extends AstNode {
predicate protects(AstNode node, Event event, string category) {
// The check dominates the step it should protect
this.dominates(node) and
this.dominates(node, event) and
// The check is effective against the event and category
this.protectsCategoryAndEvent(category, event.getName()) and
// The check can be triggered by the event
this.getATriggerEvent() = event
this.getATriggerEvent() = event and
// For reusable workflows, there must be no unprotected caller chain for this event.
(
not node.getEnclosingWorkflow() instanceof ReusableWorkflow
or
this.dominatesSameWorkflow(node, event)
or
not exists(ExternalJob directCaller |
directCaller = node.getEnclosingWorkflow().(ReusableWorkflow).getACaller() and
unprotectedCallerChain(directCaller, event, category)
)
)
}
predicate dominates(AstNode node) {
/**
* Holds if this control check must execute and pass before `node` can run.
*/
predicate dominates(AstNode node, Event event) {
this.dominatesSameWorkflow(node, event)
or
// When the node is inside a reusable workflow,
// this check dominates via at least one caller chain.
this.dominatesViaCaller(node, event, _)
}
/**
* Holds if this control check dominates `node` within the same workflow.
*/
predicate dominatesSameWorkflow(AstNode node, Event event) {
this.getATriggerEvent() = event and
(
// Step-level: the check is an `if:` on the step containing `node`,
// or on the enclosing job, or on a needed job/step.
this instanceof If and
(
node.getEnclosingStep().getIf() = this or
node.getEnclosingJob().getIf() = this or
node.getEnclosingJob().getANeededJob().(LocalJob).getAStep().getIf() = this or
node.getEnclosingJob().getANeededJob().(LocalJob).getIf() = this
)
or
// Job-level: the check is an environment on the enclosing job or a needed job.
this instanceof Environment and
(
node.getEnclosingJob().getEnvironment() = this
or
node.getEnclosingJob().getANeededJob().getEnvironment() = this
)
or
// Step-level: the check is a Run/UsesStep that precedes `node`'s step
// in the same job, or is a step in a needed job.
(
this instanceof Run or
this instanceof UsesStep
) and
(
this.(Step).getAFollowingStep() = node.getEnclosingStep()
or
node.getEnclosingJob().getANeededJob().(LocalJob).getAStep() = this
)
)
}
/**
* Holds if this control check dominates `node` in a reusable workflow
* via the caller chain starting at `directCaller`.
*/
predicate dominatesViaCaller(AstNode node, Event event, ExternalJob directCaller) {
directCaller = node.getEnclosingWorkflow().(ReusableWorkflow).getACaller() and
directCaller.getATriggerEvent() = event and
exists(ExternalJob caller |
caller = getAnOuterCaller*(directCaller) and
this.dominatesCaller(caller)
)
}
/**
* Holds if this control check directly dominates `caller`.
*/
predicate dominatesCaller(ExternalJob caller) {
this instanceof If and
(
node.getEnclosingStep().getIf() = this or
node.getEnclosingJob().getIf() = this or
node.getEnclosingJob().getANeededJob().(LocalJob).getAStep().getIf() = this or
node.getEnclosingJob().getANeededJob().(LocalJob).getIf() = this
caller.getIf() = this or
caller.getANeededJob().(LocalJob).getIf() = this or
caller.getANeededJob().(LocalJob).getAStep().getIf() = this
)
or
this instanceof Environment and
(
node.getEnclosingJob().getEnvironment() = this
or
node.getEnclosingJob().getANeededJob().getEnvironment() = this
caller.getEnvironment() = this or
caller.getANeededJob().getEnvironment() = this
)
or
(
this instanceof Run or
this instanceof UsesStep
) and
(
this.(Step).getAFollowingStep() = node.getEnclosingStep()
or
node.getEnclosingJob().getANeededJob().(LocalJob).getAStep() = this.(Step)
)
(this instanceof Run or this instanceof UsesStep) and
caller.getANeededJob().(LocalJob).getAStep() = this
}
abstract predicate protectsCategoryAndEvent(string category, string event);
}
/**
* Holds if this control check directly protects `caller`.
*/
bindingset[caller, event, category]
private predicate protectedCaller(ExternalJob caller, Event event, string category) {
exists(ControlCheck check |
check.protectsCategoryAndEvent(category, event.getName()) and
check.getATriggerEvent() = event and
check.dominatesCaller(caller)
)
}
cached
private newtype TCallerState =
MkCallerState(ExternalJob caller, Event event, string category) {
caller.getATriggerEvent() = event and
category = any_category()
}
private class CallerState extends TCallerState, MkCallerState {
ExternalJob caller;
Event event;
string category;
CallerState() { this = MkCallerState(caller, event, category) }
ExternalJob getCaller() { result = caller }
Event getEvent() { result = event }
string getCategory() { result = category }
/**
* Gets an outer caller state if this caller is not protected.
*/
CallerState getUnprotectedOuterState() {
not protectedCaller(this.getCaller(), this.getEvent(), this.getCategory()) and
result = MkCallerState(getAnOuterCaller(this.getCaller()), this.getEvent(), this.getCategory())
}
predicate isUnprotectedOutermost() {
not protectedCaller(this.getCaller(), this.getEvent(), this.getCategory()) and
not exists(getAnOuterCaller(this.getCaller()))
}
string toString() { result = caller + " / " + event + " / " + category }
}
/**
* Holds if there is a caller path from `caller` to an outer workflow that has no protection.
*/
bindingset[caller, event, category]
private predicate unprotectedCallerChain(ExternalJob caller, Event event, string category) {
exists(CallerState start, CallerState outermost |
start = MkCallerState(caller, event, category) and
outermost = start.getUnprotectedOuterState*() and
outermost.isUnprotectedOutermost()
)
}
abstract class AssociationCheck extends ControlCheck {
// Checks if the actor is a MEMBER/OWNER the repo
// - they are effective against pull requests and workflow_run (since these are triggered by pull_requests) since they can control who is making the PR

View File

@@ -1,5 +1,5 @@
name: codeql/actions-all
version: 0.4.38-dev
version: 0.4.39-dev
library: true
warnOnImplicitThis: true
dependencies:

View File

@@ -1,3 +1,9 @@
## 0.6.30
### Query Metadata Changes
* The name, description, and alert message of `actions/untrusted-checkout/medium` have been corrected to describe a non-privileged context.
## 0.6.29
### Query Metadata Changes

View File

@@ -18,7 +18,7 @@ from LocalJob job, LabelCheck check, MutableRefCheckoutStep checkout, Event even
where
job.isPrivileged() and
job.getAStep() = checkout and
check.dominates(checkout) and
check.dominates(checkout, event) and
(
job.getATriggerEvent() = event and
event.getName() = "pull_request_target" and

View File

@@ -34,8 +34,8 @@ where
check instanceof AssociationCheck or
check instanceof PermissionCheck
) and
check.dominates(checkout) and
date_check.dominates(checkout)
check.dominates(checkout, event) and
date_check.dominates(checkout, event)
)
or
// not issue_comment triggered workflows

View File

@@ -1,4 +1,5 @@
---
category: queryMetadata
---
## 0.6.30
### Query Metadata Changes
* The name, description, and alert message of `actions/untrusted-checkout/medium` have been corrected to describe a non-privileged context.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.6.29
lastReleaseVersion: 0.6.30

View File

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

View File

@@ -0,0 +1,17 @@
on:
workflow_call:
inputs:
COMMIT_SHA:
type: string
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.COMMIT_SHA }}
- run: |
npm install
npm run lint

View File

@@ -0,0 +1,13 @@
on:
workflow_call:
inputs:
COMMIT_SHA:
type: string
jobs:
build:
uses: TestOrg/TestRepo/.github/workflows/build.yml@main
with:
COMMIT_SHA: ${{ inputs.COMMIT_SHA }}

View File

@@ -0,0 +1,33 @@
on:
workflow_call:
inputs:
COMMIT_SHA:
type: string
jobs:
is-collaborator:
runs-on: ubuntu-latest
steps:
- name: Get User Permission
id: checkAccess
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
with:
require: write
username: ${{ github.actor }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check User Permission
if: steps.checkAccess.outputs.require-result == 'false'
run: |
echo "${{ github.actor }} does not have permissions on this repo."
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
exit 1
build_safe:
needs: is-collaborator
uses: TestOrg/TestRepo/.github/workflows/build_nested.yml@main
with:
COMMIT_SHA: ${{ inputs.COMMIT_SHA }}
build_unsafe:
uses: TestOrg/TestRepo/.github/workflows/build_nested.yml@main
with:
COMMIT_SHA: ${{ inputs.COMMIT_SHA }}

View File

@@ -0,0 +1,31 @@
on:
pull_request_target:
jobs:
is-collaborator:
runs-on: ubuntu-latest
steps:
- name: Get User Permission
id: checkAccess
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
with:
require: write
username: ${{ github.actor }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check User Permission
if: steps.checkAccess.outputs.require-result == 'false'
run: |
echo "${{ github.actor }} does not have permissions on this repo."
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
exit 1
build:
runs-on: ubuntu-latest
#needs: is-collaborator Mistake, doesn't wait for the collaborator - no security check
steps:
- name: Checkout repo
uses: actions/checkout@4
with:
ref: ${{ github.event.pull_request.head.sha }} # should alert
fetch-depth: 2
- run: yarn test

View File

@@ -0,0 +1,26 @@
on:
pull_request_target:
jobs:
is-collaborator:
runs-on: ubuntu-latest
steps:
- name: Get User Permission
id: checkAccess
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
with:
require: write
username: ${{ github.actor }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check User Permission
if: steps.checkAccess.outputs.require-result == 'false'
run: |
echo "${{ github.actor }} does not have permissions on this repo."
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
exit 1
build:
needs: is-collaborator
uses: TestOrg/TestRepo/.github/workflows/build.yml@main
with:
COMMIT_SHA: ${{ github.event.pull_request.head.sha }} # shouldn't alert since permission check

View File

@@ -0,0 +1,31 @@
on:
pull_request_target:
jobs:
is-collaborator:
runs-on: ubuntu-latest
steps:
- name: Get User Permission
id: checkAccess
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
with:
require: write
username: ${{ github.actor }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check User Permission
if: steps.checkAccess.outputs.require-result == 'false'
run: |
echo "${{ github.actor }} does not have permissions on this repo."
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
exit 1
build_unsafe:
# needs: is-collaborator
uses: TestOrg/TestRepo/.github/workflows/build.yml@main
with:
COMMIT_SHA: ${{ github.event.pull_request.head.sha }} # should alert since no permission check
build_safe:
needs: is-collaborator
uses: TestOrg/TestRepo/.github/workflows/build.yml@main
with:
COMMIT_SHA: ${{ github.event.pull_request.head.sha }} # shouldn't alert since permission check

View File

@@ -0,0 +1,8 @@
on:
pull_request_target:
jobs:
build:
uses: TestOrg/TestRepo/.github/workflows/build_nested_branching.yml@main
with:
COMMIT_SHA: ${{ github.event.pull_request.head.sha }}

View File

@@ -0,0 +1,26 @@
on:
pull_request_target:
jobs:
is-collaborator:
runs-on: ubuntu-latest
steps:
- name: Get User Permission
id: checkAccess
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
with:
require: write
username: ${{ github.actor }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check User Permission
if: steps.checkAccess.outputs.require-result == 'false'
run: |
echo "${{ github.actor }} does not have permissions on this repo."
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
exit 1
build:
needs: is-collaborator
uses: TestOrg/TestRepo/.github/workflows/build_nested.yml@main
with:
COMMIT_SHA: ${{ github.event.pull_request.head.sha }} # shouldn't alert since permission check

View File

@@ -0,0 +1,26 @@
on:
pull_request_target:
jobs:
is-collaborator:
runs-on: ubuntu-latest
steps:
- name: Get User Permission
id: checkAccess
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
with:
require: write
username: ${{ github.actor }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check User Permission
if: steps.checkAccess.outputs.require-result == 'false'
run: |
echo "${{ github.actor }} does not have permissions on this repo."
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
exit 1
build:
# needs: is-collaborator
uses: TestOrg/TestRepo/.github/workflows/build_nested.yml@main
with:
COMMIT_SHA: ${{ github.event.pull_request.head.sha }}

View File

@@ -0,0 +1,41 @@
on:
pull_request_target:
jobs:
is-collaborator:
runs-on: ubuntu-latest
steps:
- name: Get User Permission
id: checkAccess
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
with:
require: write
username: ${{ github.actor }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check User Permission
if: steps.checkAccess.outputs.require-result == 'false'
run: |
echo "${{ github.actor }} does not have permissions on this repo."
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
exit 1
build:
runs-on: ubuntu-latest
needs: is-collaborator
steps:
- name: Checkout repo
uses: actions/checkout@4
with:
ref: ${{ github.event.pull_request.head.sha }} # shouldn't alert since permission check
fetch-depth: 2
- run: yarn test
build_unsafe:
runs-on: ubuntu-latest
# needs: is-collaborator
steps:
- name: Checkout repo
uses: actions/checkout@4
with:
ref: ${{ github.event.pull_request.head.sha }} # should alert since no permission check
fetch-depth: 2
- run: yarn test

View File

@@ -0,0 +1,48 @@
on:
pull_request_target:
jobs:
is-collaborator-a:
runs-on: ubuntu-latest
steps:
- name: Get User Permission
id: checkAccess
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
with:
require: write
username: ${{ github.actor }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check User Permission
if: steps.checkAccess.outputs.require-result == 'false'
run: |
echo "${{ github.actor }} does not have permissions on this repo."
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
exit 1
caller-a:
needs: is-collaborator-a
uses: TestOrg/TestRepo/.github/workflows/build.yml@main
with:
COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
is-collaborator-b:
runs-on: ubuntu-latest
steps:
- name: Get User Permission
id: checkAccess
uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
with:
require: write
username: ${{ github.actor }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check User Permission
if: steps.checkAccess.outputs.require-result == 'false'
run: |
echo "${{ github.actor }} does not have permissions on this repo."
echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
exit 1
caller-b:
needs: is-collaborator-b
uses: TestOrg/TestRepo/.github/workflows/build.yml@main
with:
COMMIT_SHA: ${{ github.event.pull_request.head.sha }}

View File

@@ -93,6 +93,8 @@ edges
| .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:20:9:25:6 | Uses Step |
| .github/workflows/dependabot3.yml:20:9:25:6 | Uses Step | .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone |
| .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | .github/workflows/dependabot3.yml:48:9:52:57 | Run Step |
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:14:9:17:7 | Run Step |
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/build_nested_branching.yml:11:9:19:6 | Uses Step: checkAccess | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build_nested_branching.yml:19:9:25:2 | Run Step |
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/formal.yml:14:9:19:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/formal.yml:19:9:25:6 | Run Step |
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/formal.yml:19:9:25:6 | Run Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/formal.yml:25:9:70:20 | Run Step |
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step |
@@ -334,6 +336,17 @@ edges
| .github/workflows/untrusted_checkout_6.yml:11:9:14:6 | Uses Step | .github/workflows/untrusted_checkout_6.yml:14:9:17:6 | Uses Step |
| .github/workflows/untrusted_checkout_6.yml:14:9:17:6 | Uses Step | .github/workflows/untrusted_checkout_6.yml:17:9:21:6 | Uses Step |
| .github/workflows/untrusted_checkout_6.yml:17:9:21:6 | Uses Step | .github/workflows/untrusted_checkout_6.yml:21:9:23:23 | Run Step |
| .github/workflows/untrusted_checkout_no_needs.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_no_needs.yml:16:9:22:2 | Run Step |
| .github/workflows/untrusted_checkout_no_needs.yml:26:9:31:6 | Uses Step | .github/workflows/untrusted_checkout_no_needs.yml:31:9:31:23 | Run Step |
| .github/workflows/untrusted_checkout_permission_check_reusable2.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_permission_check_reusable2.yml:16:9:22:2 | Run Step |
| .github/workflows/untrusted_checkout_permission_check_reusable.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_permission_check_reusable.yml:16:9:22:2 | Run Step |
| .github/workflows/untrusted_checkout_permission_check_reusable_level2.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_permission_check_reusable_level2.yml:16:9:22:2 | Run Step |
| .github/workflows/untrusted_checkout_permission_check_reusable_no_needs.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_permission_check_reusable_no_needs.yml:16:9:22:2 | Run Step |
| .github/workflows/untrusted_checkout_permissions_check.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_permissions_check.yml:16:9:22:2 | Run Step |
| .github/workflows/untrusted_checkout_permissions_check.yml:26:9:31:6 | Uses Step | .github/workflows/untrusted_checkout_permissions_check.yml:31:9:32:2 | Run Step |
| .github/workflows/untrusted_checkout_permissions_check.yml:36:9:41:6 | Uses Step | .github/workflows/untrusted_checkout_permissions_check.yml:41:9:41:22 | Run Step |
| .github/workflows/untrusted_checkout_two_callers_both_protected.yml:8:9:16:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_two_callers_both_protected.yml:16:9:22:2 | Run Step |
| .github/workflows/untrusted_checkout_two_callers_both_protected.yml:30:9:38:6 | Uses Step: checkAccess | .github/workflows/untrusted_checkout_two_callers_both_protected.yml:38:9:44:2 | Run Step |
| .github/workflows/workflow_run_untrusted_checkout.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout.yml:16:9:18:31 | Uses Step |
| .github/workflows/workflow_run_untrusted_checkout_2.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout_2.yml:16:9:18:31 | Uses Step |
| .github/workflows/workflow_run_untrusted_checkout_3.yml:13:9:16:6 | Uses Step | .github/workflows/workflow_run_untrusted_checkout_3.yml:16:9:18:31 | Uses Step |
@@ -344,6 +357,9 @@ edges
| .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:79:9:84:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:67:9:74:6 | Uses Step | .github/workflows/auto_ci.yml:84:9:93:6 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/auto_ci.yml:6:3:6:21 | pull_request_target | pull_request_target |
| .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:15:9:20:6 | Uses Step | .github/workflows/dependabot3.yml:25:9:48:6 | Run Step: set-milestone | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/dependabot3.yml:3:5:3:23 | pull_request_target | pull_request_target |
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:14:9:17:7 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout_permission_check_reusable2.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:14:9:17:7 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout_permission_check_reusable_branching_nested.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:11:9:14:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/build.yml:14:9:17:7 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout_permission_check_reusable_no_needs.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:23:9:26:6 | Uses Step | .github/workflows/external/TestOrg/TestRepo/.github/workflows/reusable.yml:26:9:29:7 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/reusable_caller1.yaml:4:3:4:21 | pull_request_target | pull_request_target |
| .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | .github/workflows/gitcheckout.yml:10:11:18:8 | Run Step | .github/workflows/gitcheckout.yml:21:11:23:22 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/gitcheckout.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/label_trusted_checkout2.yml:12:7:16:4 | Uses Step | .github/workflows/label_trusted_checkout2.yml:12:7:16:4 | Uses Step | .github/workflows/label_trusted_checkout2.yml:17:7:21:4 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/label_trusted_checkout2.yml:2:3:2:21 | pull_request_target | pull_request_target |
@@ -377,3 +393,5 @@ edges
| .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:29:7:35:4 | Uses Step | .github/workflows/untrusted_checkout4.yml:47:7:51:46 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout4.yml:2:3:2:15 | issue_comment | issue_comment |
| .github/workflows/untrusted_checkout.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout.yml:8:9:11:6 | Uses Step | .github/workflows/untrusted_checkout.yml:15:9:18:2 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/untrusted_checkout.yml:23:9:26:6 | Uses Step | .github/workflows/untrusted_checkout.yml:23:9:26:6 | Uses Step | .github/workflows/untrusted_checkout.yml:30:9:32:23 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/untrusted_checkout_no_needs.yml:26:9:31:6 | Uses Step | .github/workflows/untrusted_checkout_no_needs.yml:26:9:31:6 | Uses Step | .github/workflows/untrusted_checkout_no_needs.yml:31:9:31:23 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout_no_needs.yml:2:3:2:21 | pull_request_target | pull_request_target |
| .github/workflows/untrusted_checkout_permissions_check.yml:36:9:41:6 | Uses Step | .github/workflows/untrusted_checkout_permissions_check.yml:36:9:41:6 | Uses Step | .github/workflows/untrusted_checkout_permissions_check.yml:41:9:41:22 | Run Step | Checkout of untrusted code in a privileged workflow with later potential execution (event trigger: $@). | .github/workflows/untrusted_checkout_permissions_check.yml:2:3:2:21 | pull_request_target | pull_request_target |

View File

@@ -1,3 +1,20 @@
## 11.0.0
### Breaking Changes
* Removed the deprecated `overrideReturnsNull` predicate from `Options.qll`. Use `CustomOptions.overrideReturnsNull` instead.
* Removed the deprecated `returnsNull` predicate from `Options.qll`. Use `CustomOptions.returnsNull` instead.
* Removed the deprecated `exits` predicate from `Options.qll`. Use `CustomOptions.exits` instead.
* Removed the deprecated `exprExits` predicate from `Options.qll`. Use `CustomOptions.exprExits` instead.
* Removed the deprecated `alwaysCheckReturnValue` predicate from `Options.qll`. Use `CustomOptions.alwaysCheckReturnValue` instead.
* Removed the deprecated `okToIgnoreReturnValue` predicate from `Options.qll`. Use `CustomOptions.okToIgnoreReturnValue` instead.
* Removed the deprecated `semmle.code.cpp.Member`. Import `semmle.code.cpp.Element` and/or `semmle.code.cpp.Type` directly.
* Removed the deprecated `UnknownDefaultLocation` class. Use `UnknownLocation` instead.
* Removed the deprecated `UnknownExprLocation` class. Use `UnknownLocation` instead.
* Removed the deprecated `UnknownStmtLocation` class. Use `UnknownLocation` instead.
* Removed the deprecated `TemplateParameter` class. Use `TypeTemplateParameter` instead.
* Support for class resolution across link targets has been removed for databases which were created with CodeQL versions before 1.23.0.
## 10.2.0
### Deprecated APIs

View File

@@ -0,0 +1,4 @@
---
category: deprecated
---
* Models-as-data flow summaries now use fully qualified field names (for example, `MyNamespace::MyStruct::myField`) instead of unqualified field names such as `myField`. We recommend updating existing flow summaries to use fully qualified field names. Unqualified field names are still supported, but that support will be removed in a future release.

View File

@@ -0,0 +1,4 @@
---
category: breaking
---
* Removed support for using variables as sources and sinks in models-as-data. Users of this feature should convert such sources and sinks to models defined using the QL language.

View File

@@ -1,6 +1,7 @@
---
category: breaking
---
## 11.0.0
### Breaking Changes
* Removed the deprecated `overrideReturnsNull` predicate from `Options.qll`. Use `CustomOptions.overrideReturnsNull` instead.
* Removed the deprecated `returnsNull` predicate from `Options.qll`. Use `CustomOptions.returnsNull` instead.
* Removed the deprecated `exits` predicate from `Options.qll`. Use `CustomOptions.exits` instead.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 10.2.0
lastReleaseVersion: 11.0.0

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 10.2.1-dev
version: 11.0.1-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -931,31 +931,6 @@ private Element interpretElement0(
signature = "" and
elementSpec(namespace, type, subtypes, name, signature, _)
)
or
// Member variables
elementSpec(namespace, type, subtypes, name, signature, _) and
signature = "" and
exists(Class namedClass, Class classWithMember, MemberVariable member |
member.getName() = name and
member = classWithMember.getAMember() and
namedClass.hasQualifiedName(namespace, type) and
result = member
|
// field declared in the named type or a subtype of it (or an extension of any)
subtypes = true and
classWithMember = namedClass.getADerivedClass*()
or
// field declared directly in the named type (or an extension of it)
subtypes = false and
classWithMember = namedClass
)
or
// Global or namespace variables
elementSpec(namespace, type, subtypes, name, signature, _) and
signature = "" and
type = "" and
subtypes = false and
result = any(GlobalOrNamespaceVariable v | v.hasQualifiedName(namespace, name))
}
cached

View File

@@ -6,6 +6,7 @@ private import cpp as Cpp
private import codeql.dataflow.internal.FlowSummaryImpl
private import codeql.dataflow.internal.AccessPathSyntax as AccessPath
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific as DataFlowImplSpecific
private import semmle.code.cpp.dataflow.ExternalFlow
@@ -20,8 +21,22 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
class SinkBase = Void;
class FlowSummaryCallBase = CallInstruction;
predicate callableFromSource(SummarizedCallableBase c) { exists(c.getBlock()) }
FlowSummaryCallBase getASourceCall(SummarizedCallableBase sc) {
result.getStaticCallTarget() = sc
}
DataFlowCallable getSummarizedCallableAsDataFlowCallable(SummarizedCallableBase c) {
result.asSummarizedCallable() = c
}
DataFlowCallable getSourceCallEnclosingCallable(FlowSummaryCallBase call) {
result.asSourceCallable() = call.getEnclosingFunction()
}
ArgumentPosition callbackSelfParameterPosition() { result = TDirectPosition(-1) }
ReturnKind getStandardReturnValueKind() { result = getReturnValueKind("") }
@@ -30,6 +45,10 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
arg = repeatStars(result.(NormalReturnKind).getIndirectionIndex())
}
ParameterPosition getFlowSummaryParameterPosition(ReturnKind rk) {
result = TFlowSummaryPosition(rk)
}
string encodeParameterPosition(ParameterPosition pos) { result = pos.toString() }
string encodeArgumentPosition(ArgumentPosition pos) { result = pos.toString() }
@@ -40,12 +59,24 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
arg = repeatStars(rk.(NormalReturnKind).getIndirectionIndex())
}
bindingset[namespace, type, base]
private string formatQualifiedName(string namespace, string type, string base) {
if namespace = ""
then result = type + "::" + base
else result = namespace + "::" + type + "::" + base
}
string encodeContent(ContentSet cs, string arg) {
exists(FieldContent c |
exists(FieldContent c, string namespace, string type, string base |
cs.isSingleton(c) and
// FieldContent indices have 0 for the address, 1 for content, so we need to subtract one.
result = "Field" and
arg = repeatStars(c.getIndirectionIndex() - 1) + c.getField().getName()
c.getField().hasQualifiedName(namespace, type, base)
|
arg = repeatStars(c.getIndirectionIndex() - 1) + formatQualifiedName(namespace, type, base)
or
// TODO: This disjunct can be removed once we stop supporting unqualified field names.
arg = repeatStars(c.getIndirectionIndex() - 1) + base
)
or
exists(ElementContent ec |
@@ -102,10 +133,22 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
private import Make<Location, DataFlowImplSpecific::CppDataFlow, Input> as Impl
private module StepsInput implements Impl::Private::StepsInputSig {
Impl::Private::SummaryNode getSummaryNode(Node n) {
result = n.(FlowSummaryNode).getSummaryNode()
}
DataFlowCall getACall(Public::SummarizedCallable sc) {
result.getStaticCallTarget().getUnderlyingCallable() = sc
}
Node getSourceOutNode(Input::FlowSummaryCallBase call, ReturnKind rk) {
exists(IndirectReturnOutNode out | result = out |
out.getCallInstruction() = call and
pragma[only_bind_out](rk.(NormalReturnKind).getIndirectionIndex()) =
pragma[only_bind_out](out.getIndirectionIndex())
)
}
DataFlowCallable getSourceNodeEnclosingCallable(Input::SourceBase source) { none() }
Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) { none() }
@@ -218,40 +261,11 @@ module SourceSinkInterpretationInput implements
/** Provides additional sink specification logic. */
bindingset[c]
predicate interpretOutput(string c, InterpretNode mid, InterpretNode node) {
// Allow variables to be picked as output nodes.
exists(Node n, Element ast |
n = node.asNode() and
ast = mid.asElement()
|
c = "" and
n.asExpr().(VariableAccess).getTarget() = ast
)
}
predicate interpretOutput(string c, InterpretNode mid, InterpretNode node) { none() }
/** Provides additional source specification logic. */
bindingset[c]
predicate interpretInput(string c, InterpretNode mid, InterpretNode node) {
exists(Node n, Element ast, VariableAccess e |
n = node.asNode() and
ast = mid.asElement() and
e.getTarget() = ast
|
// Allow variables to be picked as input nodes.
// We could simply do this as `e = n.asExpr()`, but that would not allow
// us to pick `x` as a sink in an example such as `x = source()` (but
// only subsequent uses of `x`) since the variable access on `x` doesn't
// actually load the value of `x`. So instead, we pick the instruction
// node corresponding to the generated `StoreInstruction` and use the
// expression associated with the destination instruction. This means
// that the `x` in `x = source()` can be marked as an input.
c = "" and
exists(StoreInstruction store |
store.getDestinationAddress().getUnconvertedResultExpression() = e and
n.asInstruction() = store
)
)
}
predicate interpretInput(string c, InterpretNode mid, InterpretNode node) { none() }
}
module Private {

View File

@@ -1534,12 +1534,8 @@ class FlowSummaryNode extends Node, TFlowSummaryNode {
result = this.getSummaryNode().getSummarizedCallable()
}
/**
* Gets the enclosing callable. For a `FlowSummaryNode` this is always the
* summarized function this node is part of.
*/
override DataFlowCallable getEnclosingCallable() {
result.asSummarizedCallable() = this.getSummarizedCallable()
result = FlowSummaryImpl::Private::getEnclosingCallable(this.getSummaryNode())
}
override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() }

View File

@@ -561,6 +561,21 @@ class SummaryArgumentNode extends ArgumentNode, FlowSummaryNode {
}
}
/** An argument node that re-enters return output as input to a flow summary. */
private class FlowSummaryArgumentNode extends ArgumentNode, FlowSummaryNode {
private CallInstruction callInstruction;
private ReturnKind rk;
FlowSummaryArgumentNode() {
this.getSummaryNode() = FlowSummaryImpl::Private::summaryArgumentNode(callInstruction, rk)
}
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
call.asCallInstruction() = callInstruction and
pos = TFlowSummaryPosition(rk)
}
}
/** A parameter position represented by an integer. */
class ParameterPosition = Position;
@@ -616,6 +631,18 @@ class IndirectionPosition extends Position, TIndirectionPosition {
final override int getIndirectionIndex() { result = indirectionIndex }
}
class FlowSummaryPosition extends Position, TFlowSummaryPosition {
ReturnKind rk;
FlowSummaryPosition() { this = TFlowSummaryPosition(rk) }
override string toString() { result = "write to: " + rk.toString() }
override int getArgumentIndex() { none() }
final override int getIndirectionIndex() { result = rk.getIndirectionIndex() }
}
newtype TPosition =
TDirectPosition(int argumentIndex) {
exists(any(CallInstruction c).getArgument(argumentIndex))
@@ -634,7 +661,8 @@ newtype TPosition =
p = f.getParameter(argumentIndex) and
indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(p.getUnspecifiedType()) - 1]
)
}
} or
TFlowSummaryPosition(ReturnKind rk) { FlowSummaryImpl::Private::relevantFlowSummaryPosition(rk) }
private newtype TReturnKind =
TNormalReturnKind(int indirectionIndex) {
@@ -1378,6 +1406,8 @@ predicate nodeIsHidden(Node n) {
n instanceof InitialGlobalValue
or
n instanceof SsaSynthNode
or
n.(FlowSummaryNode).getSummaryNode().isHidden()
}
predicate neverSkipInPathGraph(Node n) {

View File

@@ -158,7 +158,7 @@ private module Cached {
model = ""
or
// models-as-data summarized flow
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
}

View File

@@ -67,7 +67,7 @@ private module Cached {
model = ""
or
// models-as-data summarized flow
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
or
// object->field conflation for content that is a `TaintInheritingContent`.

View File

@@ -1,3 +1,7 @@
## 1.6.5
No user-facing changes.
## 1.6.4
No user-facing changes.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.6.4
lastReleaseVersion: 1.6.5

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.6.5-dev
version: 1.6.6-dev
groups:
- cpp
- queries

View File

@@ -1 +1,2 @@
jsf/4.13 Functions/AV Rule 107.ql
query: jsf/4.13 Functions/AV Rule 107.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1 +1,2 @@
Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql
query: Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -48,7 +48,7 @@ void test1()
void test2()
{
Lock<Mutex> myLock(); // BAD (interpreted as a function declaration, this does nothing)
Lock<Mutex> myLock(); // $ Alert[cpp/function-in-block] // BAD (interpreted as a function declaration, this does nothing)
// ...
}
@@ -62,14 +62,14 @@ void test3()
void test4()
{
Lock<Mutex>(myMutex); // BAD (creates an uninitialized variable called `myMutex`, probably not intended)
Lock<Mutex>(myMutex); // $ Alert[cpp/local-variable-hides-global-variable] // BAD (creates an uninitialized variable called `myMutex`, probably not intended)
// ...
}
void test5()
{
Lock<Mutex> myLock(Mutex); // BAD (interpreted as a function declaration, this does nothing)
Lock<Mutex> myLock(Mutex); // $ Alert[cpp/function-in-block] // BAD (interpreted as a function declaration, this does nothing)
// ...
}
@@ -86,7 +86,7 @@ public:
void test7()
{
Lock<Mutex>(memberMutex); // BAD (creates an uninitialized variable called `memberMutex`, probably not intended) [NOT DETECTED]
Lock<Mutex>(memberMutex); // $ MISSING: Alert // BAD (creates an uninitialized variable called `memberMutex`, probably not intended) [NOT DETECTED]
// ...
}

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql
query: experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -19,7 +19,7 @@ void test1(int p)
{
sys_somesystemcall(&p);
unsafe_put_user(123, &p); // BAD [NOT DETECTED]
unsafe_put_user(123, &p); // $ MISSING: Alert // BAD [NOT DETECTED]
}
void test2(int p)
@@ -40,7 +40,7 @@ void test3()
sys_somesystemcall(&v);
unsafe_put_user(123, &v); // BAD [NOT DETECTED]
unsafe_put_user(123, &v); // $ MISSING: Alert // BAD [NOT DETECTED]
}
void test4()
@@ -68,7 +68,7 @@ void test5()
sys_somesystemcall(&myData);
unsafe_put_user(123, &(myData.x)); // BAD [NOT DETECTED]
unsafe_put_user(123, &(myData.x)); // $ MISSING: Alert // BAD [NOT DETECTED]
}
void test6()

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql
query: experimental/Security/CWE/CWE-020/LateCheckOfFunctionArgument.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -3,6 +3,6 @@ void workFunction_0(char *s) {
char buf[80], buf1[8];
if(len<0) return;
memset(buf,0,len); //GOOD
memset(buf1,0,len1); //BAD
memset(buf1,0,len1); // $ Alert //BAD
if(len1<0) return;
}

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-078/WordexpTainted.ql
query: experimental/Security/CWE/CWE-078/WordexpTainted.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -19,14 +19,14 @@ enum {
int wordexp(const char *restrict s, wordexp_t *restrict p, int flags);
int main(int argc, char** argv) {
int main(int argc, char** argv) { // $ Source
char *filePath = argv[2];
{
// BAD: the user string is injected directly into `wordexp` which performs command substitution
wordexp_t we;
wordexp(filePath, &we, 0);
wordexp(filePath, &we, 0); // $ Alert
}
{

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql
query: experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -20,7 +20,7 @@ void myFclose(FILE * fmy)
int main(int argc, char *argv[])
{
fe = fopen("myFile.txt", "wt");
fclose(fe); // BAD
fclose(fe); // $ Alert // BAD
fe = fopen("myFile.txt", "wt");
myFclose(fe); // GOOD
return 0;

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
query: experimental/Security/CWE/CWE-1126/DeclarationOfVariableWithUnnecessarilyWideScope.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -11,7 +11,7 @@ void workFunction_0(char *s) {
while(intIndex > 2)
{
buf[intIndex] = 1;
int intIndex; // BAD
int intIndex; // $ Alert // BAD
intIndex--;
}
intIndex = 10;

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-1240/CustomCryptographicPrimitive.ql
query: experimental/Security/CWE/CWE-1240/CustomCryptographicPrimitive.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -8,7 +8,7 @@ int strlen(const char *string);
// the following function is homebrew crypto written for this test. This is a bad algorithm
// on multiple levels and should never be used in cryptography.
void encryptString(char *string, unsigned int key) {
void encryptString(char *string, unsigned int key) { // $ Alert
char *ptr = string;
int len = strlen(string);
@@ -27,7 +27,7 @@ void encryptString(char *string, unsigned int key) {
// the following function is homebrew crypto written for this test. This is a bad algorithm
// on multiple levels and should never be used in cryptography.
void MyEncrypt(const unsigned int *dataIn, unsigned int *dataOut, unsigned int dataSize, unsigned int key[2]) {
void MyEncrypt(const unsigned int *dataIn, unsigned int *dataOut, unsigned int dataSize, unsigned int key[2]) { // $ Alert
unsigned int state[2];
unsigned int t;
@@ -48,7 +48,7 @@ void MyEncrypt(const unsigned int *dataIn, unsigned int *dataOut, unsigned int d
// the following function resembles an implementation of the AES "mix columns"
// step. It is not accurate, efficient or safe and should never be used in
// cryptography.
void mix_columns(const uint8_t inputs[4], uint8_t outputs[4]) {
void mix_columns(const uint8_t inputs[4], uint8_t outputs[4]) { // $ Alert
// The "mix columns" step takes four bytes as inputs. Each byte represents a
// polynomial with 8 one-bit coefficients, e.g. input bits 00001101
// represent the polynomial x^3 + x^2 + 1. Arithmetic is reduced modulo
@@ -80,7 +80,7 @@ void mix_columns(const uint8_t inputs[4], uint8_t outputs[4]) {
// the following function resembles initialization of an S-box as may be done
// in an implementation of DES, AES and other encryption algorithms. It is not
// accurate, efficient or safe and should never be used in cryptography.
void init_aes_sbox(unsigned char data[256]) {
void init_aes_sbox(unsigned char data[256]) { // $ Alert
// initialize `data` in a loop using lots of ^, ^= and << operations and
// a few fixed constants.
unsigned int state = 0x12345678;

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-125/DangerousWorksWithMultibyteOrWideCharacters.ql
query: experimental/Security/CWE/CWE-125/DangerousWorksWithMultibyteOrWideCharacters.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -63,7 +63,7 @@ static void badTest1(const char* ptr)
int ret;
int len;
len = strlen(ptr);
for (wchar_t wc; (ret = mbtowc(&wc, ptr, 4)) > 0; len-=ret) { // BAD:we can get unpredictable results
for (wchar_t wc; (ret = mbtowc(&wc, ptr, 4)) > 0; len-=ret) { // $ Alert // BAD:we can get unpredictable results
wprintf(L"%lc", wc);
ptr += ret;
}
@@ -73,7 +73,7 @@ static void badTest2(const char* ptr)
int ret;
int len;
len = strlen(ptr);
for (wchar_t wc; (ret = mbtowc(&wc, ptr, sizeof(wchar_t))) > 0; len-=ret) { // BAD:we can get unpredictable results
for (wchar_t wc; (ret = mbtowc(&wc, ptr, sizeof(wchar_t))) > 0; len-=ret) { // $ Alert // BAD:we can get unpredictable results
wprintf(L"%lc", wc);
ptr += ret;
}
@@ -103,7 +103,7 @@ static void badTest3(const char* ptr,int wc_len)
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, MB_CUR_MAX); // BAD
ret = mbtowc(wc, ptr, MB_CUR_MAX); // $ Alert // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
@@ -120,7 +120,7 @@ static void badTest4(const char* ptr,int wc_len)
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, 16); // BAD
ret = mbtowc(wc, ptr, 16); // $ Alert // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
@@ -137,7 +137,7 @@ static void badTest5(const char* ptr,int wc_len)
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, sizeof(wchar_t)); // BAD
ret = mbtowc(wc, ptr, sizeof(wchar_t)); // $ Alert // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
@@ -155,7 +155,7 @@ static void badTest6(const char* ptr,int wc_len)
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && wc_len > 0) {
ret = mbtowc(wc, ptr, wc_len); // BAD
ret = mbtowc(wc, ptr, wc_len); // $ Alert // BAD
if (ret <0)
if (checkErrors()) {
++ptr;
@@ -178,7 +178,7 @@ static void badTest7(const char* ptr,int wc_len)
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && wc_len > 0) {
ret = mbtowc(wc, ptr, len); // BAD
ret = mbtowc(wc, ptr, len); // $ Alert // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
@@ -194,7 +194,7 @@ static void badTest8(const char* ptr,wchar_t *wc)
int len;
len = strlen(ptr);
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, len); // BAD
ret = mbtowc(wc, ptr, len); // $ Alert // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)

View File

@@ -25,8 +25,8 @@ void* calloc (size_t num, size_t size);
void* malloc (size_t size);
static void badTest1(void *src, int size) {
WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, (LPSTR)src, size, 0, 0); // BAD
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, (LPCWSTR)src, 30); // BAD
WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, (LPSTR)src, size, 0, 0); // $ Alert // BAD
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, (LPCWSTR)src, 30); // $ Alert // BAD
}
void goodTest2(){
wchar_t src[] = L"0123456789ABCDEF";
@@ -42,7 +42,7 @@ void goodTest2(){
static void badTest2(){
wchar_t src[] = L"0123456789ABCDEF";
char dst[16];
WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, 16, NULL, NULL); // BAD
WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, 16, NULL, NULL); // $ Alert // BAD
printf("%s\n", dst);
}
static void goodTest3(){
@@ -55,7 +55,7 @@ static void badTest3(){
char src[] = "0123456789ABCDEF";
int size = MultiByteToWideChar(CP_UTF8, 0, src,sizeof(src),NULL,0);
wchar_t * dst = (wchar_t*)calloc(size + 1, 1);
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // BAD
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // $ Alert // BAD
}
static void goodTest4(){
char src[] = "0123456789ABCDEF";
@@ -67,13 +67,13 @@ static void badTest4(){
char src[] = "0123456789ABCDEF";
int size = MultiByteToWideChar(CP_UTF8, 0, src,sizeof(src),NULL,0);
wchar_t * dst = (wchar_t*)malloc(size + 1);
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // BAD
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // $ Alert // BAD
}
static int goodTest5(void *src){
return WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, 0, 0, 0, 0); // GOOD
}
static int badTest5 (void *src) {
return WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, 0, 3, 0, 0); // BAD
return WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, 0, 3, 0, 0); // $ Alert // BAD
}
static void goodTest6(WCHAR *src)
{
@@ -90,6 +90,6 @@ static void goodTest6(WCHAR *src)
static void badTest6(WCHAR *src)
{
char dst[5] ="";
WideCharToMultiByte(CP_ACP, 0, src, -1, dst, 260, 0, 0); // BAD
WideCharToMultiByte(CP_ACP, 0, src, -1, dst, 260, 0, 0); // $ Alert // BAD
printf("%s\n", dst);
}

View File

@@ -12,11 +12,11 @@ size_t mbsrtowcs(wchar_t *wcstr,const char *mbstr,size_t count, mbstate_t *mbsta
static void badTest1(void *src, int size) {
mbstowcs((wchar_t*)src,(char*)src,size); // BAD
mbstowcs((wchar_t*)src,(char*)src,size); // $ Alert // BAD
_locale_t locale;
_mbstowcs_l((wchar_t*)src,(char*)src,size,locale); // BAD
_mbstowcs_l((wchar_t*)src,(char*)src,size,locale); // $ Alert // BAD
mbstate_t *mbstate;
mbsrtowcs((wchar_t*)src,(char*)src,size,mbstate); // BAD
mbsrtowcs((wchar_t*)src,(char*)src,size,mbstate); // $ Alert // BAD
}
static void goodTest2(){
char src[] = "0123456789ABCDEF";
@@ -32,7 +32,7 @@ static void goodTest2(){
static void badTest2(){
char src[] = "0123456789ABCDEF";
wchar_t dst[16];
mbstowcs(dst, src,16); // BAD
mbstowcs(dst, src,16); // $ Alert // BAD
printf("%s\n", dst);
}
static void goodTest3(){
@@ -45,7 +45,7 @@ static void badTest3(){
char src[] = "0123456789ABCDEF";
int size = mbstowcs(NULL, src,NULL);
wchar_t * dst = (wchar_t*)calloc(size + 1, 1);
mbstowcs(dst, src,size+1); // BAD
mbstowcs(dst, src,size+1); // $ Alert // BAD
}
static void goodTest4(){
char src[] = "0123456789ABCDEF";
@@ -57,13 +57,13 @@ static void badTest4(){
char src[] = "0123456789ABCDEF";
int size = mbstowcs(NULL, src,NULL);
wchar_t * dst = (wchar_t*)malloc(size + 1);
mbstowcs(dst, src,size+1); // BAD
mbstowcs(dst, src,size+1); // $ Alert // BAD
}
static int goodTest5(void *src){
return mbstowcs(NULL, (char*)src,NULL); // GOOD
}
static int badTest5 (void *src) {
return mbstowcs(NULL, (char*)src,3); // BAD
return mbstowcs(NULL, (char*)src,3); // $ Alert // BAD
}
static void goodTest6(void *src){
wchar_t dst[5];
@@ -77,6 +77,6 @@ static void goodTest6(void *src){
}
static void badTest6(void *src){
wchar_t dst[5];
mbstowcs(dst, (char*)src,260); // BAD
mbstowcs(dst, (char*)src,260); // $ Alert // BAD
printf("%s\n", dst);
}

View File

@@ -13,7 +13,7 @@ static size_t badTest1(unsigned char *src){
int cb = 0;
unsigned char dst[50];
while( cb < sizeof(dst) )
dst[cb++]=*src++; // BAD
dst[cb++]=*src++; // $ Alert // BAD
return _mbclen(dst);
}
static void goodTest2(unsigned char *src){
@@ -33,7 +33,7 @@ static void badTest2(unsigned char *src){
unsigned char dst[50];
while( cb < sizeof(dst) )
{
_mbccpy(dst+cb,src); // BAD
_mbccpy(dst+cb,src); // $ Alert // BAD
cb+=_mbclen(src);
src=_mbsinc(src);
}
@@ -44,5 +44,5 @@ static void goodTest3(){
}
static void badTest3(){
wchar_t name[50];
name[sizeof(name) - 1] = L'\0'; // BAD
name[sizeof(name) - 1] = L'\0'; // $ Alert // BAD
}

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql
query: experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -10,31 +10,31 @@ void test()
int y = getAnInt();
char *buffer1 = (char *)malloc(x + y); // GOOD
char *buffer2 = (char *)malloc(x * y); // BAD
char *buffer2 = (char *)malloc(x * y); // $ Alert // BAD
int *buffer3 = (int *)malloc(x * sizeof(int)); // GOOD
int *buffer4 = (int *)malloc(x * y * sizeof(int)); // BAD
int *buffer4 = (int *)malloc(x * y * sizeof(int)); // $ Alert // BAD
if ((x <= 1000) && (y <= 1000))
{
char *buffer5 = (char *)malloc(x * y); // GOOD [FALSE POSITIVE]
char *buffer5 = (char *)malloc(x * y); // $ SPURIOUS: Alert // GOOD [FALSE POSITIVE]
}
size_t size1 = x * y;
char *buffer5 = (char *)malloc(size1); // BAD
size_t size1 = x * y; // $ Source
char *buffer5 = (char *)malloc(size1); // $ Alert // BAD
size_t size2 = x;
size2 *= y;
char *buffer6 = (char *)malloc(size2); // BAD [NOT DETECTED]
char *buffer6 = (char *)malloc(size2); // $ MISSING: Alert // BAD [NOT DETECTED]
char *buffer7 = new char[x * 10]; // GOOD
char *buffer8 = new char[x * y]; // BAD
char *buffer9 = new char[x * x]; // BAD
char *buffer8 = new char[x * y]; // $ Alert // BAD
char *buffer9 = new char[x * x]; // $ Alert // BAD
}
// --- custom allocators ---
void *MyMalloc1(size_t size) { return malloc(size); } // [additional detection here]
void *MyMalloc1(size_t size) { return malloc(size); } // $ Alert // [additional detection here]
void *MyMalloc2(size_t size);
void customAllocatorTests()
@@ -42,6 +42,6 @@ void customAllocatorTests()
int x = getAnInt();
int y = getAnInt();
char *buffer1 = (char *)MyMalloc1(x * y); // BAD
char *buffer2 = (char *)MyMalloc2(x * y); // BAD
char *buffer1 = (char *)MyMalloc1(x * y); // $ Alert Source // BAD
char *buffer2 = (char *)MyMalloc2(x * y); // $ Alert // BAD
}

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-190/DangerousUseOfTransformationAfterOperation.ql
query: experimental/Security/CWE/CWE-190/DangerousUseOfTransformationAfterOperation.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -6,17 +6,17 @@ void functionWork(char aA[10],unsigned int aUI) {
int aI;
aI = (aUI*8)/10; // GOOD
aI = aUI*8; // BAD
aI = aUI*8; // $ Alert // BAD
aP = aA+aI;
aI = (int)aUI*8; // GOOD
aL = (unsigned long)(aI*aI); // BAD
aL = (unsigned long)(aI*aI); // $ Alert // BAD
aL = ((unsigned long)aI*aI); // GOOD
testCall((unsigned long)(aI*aI)); // BAD
testCall((unsigned long)(aI*aI)); // $ Alert // BAD
testCall(((unsigned long)aI*aI)); // GOOD
if((unsigned long)(aI*aI) > aL) // BAD
if((unsigned long)(aI*aI) > aL) // $ Alert // BAD
return;
if(((unsigned long)aI*aI) > aL) // GOOD
return;

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-190/IfStatementAdditionOverflow.ql
query: experimental/Security/CWE/CWE-190/IfStatementAdditionOverflow.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -15,49 +15,49 @@ void test()
unsigned short b1 = getAnUnsignedShort();
unsigned short c1 = getAnUnsignedShort();
if (a+b>c) a = c-b; // BAD
if (a+b>c) { a = c-b; } // BAD
if (b+a>c) a = c-b; // BAD
if (b+a>c) { a = c-b; } // BAD
if (c>a+b) a = c-b; // BAD
if (c>a+b) { a = c-b; } // BAD
if (c>b+a) a = c-b; // BAD
if (c>b+a) { a = c-b; } // BAD
if (a+b>c) a = c-b; // $ Alert // BAD
if (a+b>c) { a = c-b; } // $ Alert // BAD
if (b+a>c) a = c-b; // $ Alert // BAD
if (b+a>c) { a = c-b; } // $ Alert // BAD
if (c>a+b) a = c-b; // $ Alert // BAD
if (c>a+b) { a = c-b; } // $ Alert // BAD
if (c>b+a) a = c-b; // $ Alert // BAD
if (c>b+a) { a = c-b; } // $ Alert // BAD
if (a+b>=c) a = c-b; // BAD
if (a+b>=c) { a = c-b; } // BAD
if (b+a>=c) a = c-b; // BAD
if (b+a>=c) { a = c-b; } // BAD
if (c>=a+b) a = c-b; // BAD
if (c>=a+b) { a = c-b; } // BAD
if (c>=b+a) a = c-b; // BAD
if (c>=b+a) { a = c-b; } // BAD
if (a+b>=c) a = c-b; // $ Alert // BAD
if (a+b>=c) { a = c-b; } // $ Alert // BAD
if (b+a>=c) a = c-b; // $ Alert // BAD
if (b+a>=c) { a = c-b; } // $ Alert // BAD
if (c>=a+b) a = c-b; // $ Alert // BAD
if (c>=a+b) { a = c-b; } // $ Alert // BAD
if (c>=b+a) a = c-b; // $ Alert // BAD
if (c>=b+a) { a = c-b; } // $ Alert // BAD
if (a+b<c) a = c-b; // BAD
if (a+b<c) { a = c-b; } // BAD
if (b+a<c) a = c-b; // BAD
if (b+a<c) { a = c-b; } // BAD
if (c<a+b) a = c-b; // BAD
if (c<a+b) { a = c-b; } // BAD
if (c<b+a) a = c-b; // BAD
if (c<b+a) { a = c-b; } // BAD
if (a+b<c) a = c-b; // $ Alert // BAD
if (a+b<c) { a = c-b; } // $ Alert // BAD
if (b+a<c) a = c-b; // $ Alert // BAD
if (b+a<c) { a = c-b; } // $ Alert // BAD
if (c<a+b) a = c-b; // $ Alert // BAD
if (c<a+b) { a = c-b; } // $ Alert // BAD
if (c<b+a) a = c-b; // $ Alert // BAD
if (c<b+a) { a = c-b; } // $ Alert // BAD
if (a+b<=c) a = c-b; // BAD
if (a+b<=c) { a = c-b; } // BAD
if (b+a<=c) a = c-b; // BAD
if (b+a<=c) { a = c-b; } // BAD
if (c<=a+b) a = c-b; // BAD
if (c<=a+b) { a = c-b; } // BAD
if (c<=b+a) a = c-b; // BAD
if (c<=b+a) { a = c-b; } // BAD
if (a+b<=c) a = c-b; // $ Alert // BAD
if (a+b<=c) { a = c-b; } // $ Alert // BAD
if (b+a<=c) a = c-b; // $ Alert // BAD
if (b+a<=c) { a = c-b; } // $ Alert // BAD
if (c<=a+b) a = c-b; // $ Alert // BAD
if (c<=a+b) { a = c-b; } // $ Alert // BAD
if (c<=b+a) a = c-b; // $ Alert // BAD
if (c<=b+a) { a = c-b; } // $ Alert // BAD
if (a+b>d) a = d-b; // BAD
if (a+b>d) a = d-b; // $ Alert // BAD
if (a+(double)b>c) a = c-b; // GOOD
if (a+(-x)>c) a = c-(-y); // GOOD
if (a+b>c) { b++; a = c-b; } // GOOD
if (a+d>c) a = c-d; // GOOD
if (a1+b1>c1) a1 = c1-b1; // GOOD
if (a+b<=c) { /* ... */ } else { a = c-b; } // BAD
if (a+b<=c) { return; } a = c-b; // BAD
if (a+b<=c) { /* ... */ } else { a = c-b; } // $ Alert // BAD
if (a+b<=c) { return; } a = c-b; // $ Alert // BAD
}

View File

@@ -1 +1,2 @@
experimental/Likely Bugs/ArrayAccessProductFlow.ql
query: experimental/Likely Bugs/ArrayAccessProductFlow.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,13 +1,13 @@
char *malloc(int size);
void test1(int size) {
char *arr = malloc(size);
char *arr = malloc(size); // $ Source
for (int i = 0; i < size; i++) {
arr[i] = 0; // GOOD
}
for (int i = 0; i <= size; i++) {
arr[i] = i; // BAD
arr[i] = i; // $ Alert // BAD
}
}
@@ -18,7 +18,7 @@ typedef struct {
array_t mk_array(int size) {
array_t arr;
arr.p = malloc(size);
arr.p = malloc(size); // $ Source
arr.size = size;
return arr;
@@ -32,7 +32,7 @@ void test2(int size) {
}
for (int i = 0; i <= arr.size; i++) {
arr.p[i] = i; // BAD
arr.p[i] = i; // $ Alert // BAD
}
}
@@ -42,7 +42,7 @@ void test3_callee(array_t arr) {
}
for (int i = 0; i <= arr.size; i++) {
arr.p[i] = i; // BAD
arr.p[i] = i; // $ Alert // BAD
}
}
@@ -52,7 +52,7 @@ void test3(int size) {
void test4(int size) {
array_t arr;
arr.p = malloc(size);
arr.p = malloc(size); // $ Source
arr.size = size;
for (int i = 0; i < arr.size; i++) {
@@ -60,13 +60,13 @@ void test4(int size) {
}
for (int i = 0; i <= arr.size; i++) {
arr.p[i] = i; // BAD
arr.p[i] = i; // $ Alert // BAD
}
}
array_t *mk_array_p(int size) {
array_t *arr = (array_t*) malloc(sizeof(array_t));
arr->p = malloc(size);
arr->p = malloc(size); // $ Source
arr->size = size;
return arr;
@@ -80,7 +80,7 @@ void test5(int size) {
}
for (int i = 0; i <= arr->size; i++) {
arr->p[i] = i; // BAD
arr->p[i] = i; // $ Alert // BAD
}
}
@@ -90,7 +90,7 @@ void test6_callee(array_t *arr) {
}
for (int i = 0; i <= arr->size; i++) {
arr->p[i] = i; // BAD
arr->p[i] = i; // $ Alert // BAD
}
}
@@ -105,6 +105,6 @@ void test7(int size) {
}
for (char *p = arr; p <= arr + size; p++) {
*p = 0; // BAD [NOT DETECTED]
*p = 0; // $ MISSING: Alert // BAD [NOT DETECTED]
}
}

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql
query: experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -32,60 +32,60 @@ void testOneArray(OneArray *arr) {
void testBig(BigArray *arr) {
arr->buf[MAX_SIZE-1] = 0; // GOOD
arr->buf[MAX_SIZE] = 0; // BAD
arr->buf[MAX_SIZE+1] = 0; // BAD
arr->buf[MAX_SIZE] = 0; // $ Alert // BAD
arr->buf[MAX_SIZE+1] = 0; // $ Alert // BAD
for(int i = 0; i < MAX_SIZE; i++) {
arr->buf[i] = 0; // GOOD
}
for(int i = 0; i <= MAX_SIZE; i++) {
arr->buf[i] = 0; // BAD
arr->buf[i] = 0; // $ Alert // BAD
}
}
void testFields(ArrayAndFields *arr) {
arr->buf[MAX_SIZE-1] = 0; // GOOD
arr->buf[MAX_SIZE] = 0; // BAD?
arr->buf[MAX_SIZE+1] = 0; // BAD?
arr->buf[MAX_SIZE] = 0; // $ Alert // BAD?
arr->buf[MAX_SIZE+1] = 0; // $ Alert // BAD?
for(int i = 0; i < MAX_SIZE; i++) {
arr->buf[i] = 0; // GOOD
}
for(int i = 0; i <= MAX_SIZE; i++) {
arr->buf[i] = 0; // BAD?
arr->buf[i] = 0; // $ Alert // BAD?
}
for(int i = 0; i < MAX_SIZE+2; i++) {
arr->buf[i] = 0; // BAD?
arr->buf[i] = 0; // $ Alert // BAD?
}
// is this different if it's a memcpy?
}
void assignThroughPointer(int *p) {
void assignThroughPointer(int *p) { // $ Sink
*p = 0; // ??? should the result go at a flow source?
}
void addToPointerAndAssign(int *p) {
p[MAX_SIZE-1] = 0; // GOOD
p[MAX_SIZE] = 0; // BAD
p[MAX_SIZE] = 0; // $ Alert // BAD
}
void testInterproc(BigArray *arr) {
assignThroughPointer(&arr->buf[MAX_SIZE-1]); // GOOD
assignThroughPointer(&arr->buf[MAX_SIZE]); // BAD
assignThroughPointer(&arr->buf[MAX_SIZE]); // $ Alert // BAD
addToPointerAndAssign(arr->buf);
addToPointerAndAssign(arr->buf); // $ Source
}
#define MAX_SIZE_BYTES 4096
void testCharIndex(BigArray *arr) {
char *charBuf = (char*) arr->buf;
char *charBuf = (char*) arr->buf; // $ Source
charBuf[MAX_SIZE_BYTES - 1] = 0; // GOOD
charBuf[MAX_SIZE_BYTES] = 0; // BAD
charBuf[MAX_SIZE_BYTES] = 0; // $ Alert // BAD
}
void testEqRefinement() {
@@ -125,7 +125,7 @@ void testStackAllocated() {
char *arr[MAX_SIZE];
for(int i = 0; i <= MAX_SIZE; i++) {
arr[i] = 0; // BAD
arr[i] = 0; // $ Alert // BAD
}
}
@@ -133,18 +133,18 @@ int strncmp(const char*, const char*, int);
char testStrncmp2(char *arr) {
if(strncmp(arr, "<test>", 6) == 0) {
arr += 6;
arr += 6; // $ Alert
}
return *arr; // GOOD [FALSE POSITIVE]
return *arr; // $ SPURIOUS: Sink // GOOD [FALSE POSITIVE]
}
void testStrncmp1() {
char asdf[5];
testStrncmp2(asdf);
testStrncmp2(asdf); // $ Source
}
void countdownBuf1(int **p) {
*--(*p) = 1; // GOOD [FALSE POSITIVE]
*--(*p) = 1; // $ SPURIOUS: Sink // GOOD [FALSE POSITIVE]
*--(*p) = 2; // GOOD
*--(*p) = 3; // GOOD
*--(*p) = 4; // GOOD
@@ -153,7 +153,7 @@ void countdownBuf1(int **p) {
void countdownBuf2() {
int buf[4];
int *x = buf + 4;
int *x = buf + 4; // $ Alert
countdownBuf1(&x);
}
@@ -182,7 +182,7 @@ int countdownLength1(int *p, int len) {
}
int callCountdownLength() {
int buf[6];
return countdownLength1(buf, 6);
@@ -192,7 +192,7 @@ int countdownLength2() {
int buf[6];
int len = 6;
int *p = buf;
if(len % 8) {
return -1;
}
@@ -215,10 +215,10 @@ int countdownLength2() {
void pointer_size_larger_than_array_element_size() {
unsigned char buffer[100]; // getByteSize() = 100
int *ptr = (int *)buffer; // pai.getElementSize() will be sizeof(int) = 4 -> size = 25
int *ptr = (int *)buffer; // $ Source // pai.getElementSize() will be sizeof(int) = 4 -> size = 25
ptr[24] = 0; // GOOD: writes bytes 96, 97, 98, 99
ptr[25] = 0; // BAD: writes bytes 100, 101, 102, 103
ptr[25] = 0; // $ Alert // BAD: writes bytes 100, 101, 102, 103
}
struct vec2 { int x, y; };
@@ -226,10 +226,10 @@ struct vec3 { int x, y, z; };
void pointer_size_smaller_than_array_element_size_but_does_not_divide_it() {
vec3 array[3]; // getByteSize() = 9 * sizeof(int)
vec2 *ptr = (vec2 *)array; // pai.getElementSize() will be 2 * sizeof(int) -> size = 4
vec2 *ptr = (vec2 *)array; // $ Source // pai.getElementSize() will be 2 * sizeof(int) -> size = 4
ptr[3] = vec2{}; // GOOD: writes ints 6, 7
ptr[4] = vec2{}; // BAD: writes ints 8, 9
ptr[4] = vec2{}; // $ Alert // BAD: writes ints 8, 9
}
void pointer_size_larger_than_array_element_size_and_does_not_divide_it() {
@@ -258,7 +258,7 @@ void call_use(unsigned char* p, int n) {
if(n == 3) {
unsigned char x = p[0];
unsigned char y = p[1];
unsigned char z = p[2]; // GOOD [FALSE POSITIVE]: `call_use(buffer2, 2)` won't reach this point.
unsigned char z = p[2]; // $ SPURIOUS: Alert // GOOD [FALSE POSITIVE]: `call_use(buffer2, 2)` won't reach this point.
use(x, y, z);
}
}
@@ -283,7 +283,7 @@ void test_call_use2() {
call_call_use(buffer1,1);
unsigned char buffer2[2];
call_call_use(buffer2,2);
call_call_use(buffer2,2); // $ Source
unsigned char buffer3[3];
call_call_use(buffer3,3);
@@ -296,7 +296,7 @@ int guardingCallee(int *arr, int size) {
int sum;
for (int i = 0; i < size; i++) {
sum += arr[i]; // GOOD [FALSE POSITIVE] - guarded by size
sum += arr[i]; // $ SPURIOUS: Alert // GOOD [FALSE POSITIVE] - guarded by size
}
return sum;
}
@@ -304,9 +304,9 @@ int guardingCallee(int *arr, int size) {
int guardingCaller() {
int arr1[MAX_SIZE];
guardingCallee(arr1, MAX_SIZE);
int arr2[10];
guardingCallee(arr2, 10);
guardingCallee(arr2, 10); // $ Source
}
// simplified md5 padding
@@ -319,10 +319,10 @@ void correlatedCondition(int num) {
end = temp + 56;
}
else if (num < 64) {
end = temp + 64; // GOOD [FALSE POSITVE]
end = temp + 64; // $ SPURIOUS: Alert // GOOD [FALSE POSITVE]
}
char *temp2 = temp + num;
while(temp2 != end) {
while(temp2 != end) { // $ Sink
*temp2 = 0;
temp2++;
}

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql
query: experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -9,7 +9,7 @@ int main(int argc, char *argv[])
{
//umask(0022);
FILE *fp;
fp = fopen("myFile.txt","w"); // BAD
fp = fopen("myFile.txt","w"); // $ Alert // BAD
//chmod("myFile.txt",0644);
fprintf(fp,"%s\n","data to file");
fclose(fp);

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql
query: experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql
query: experimental/Security/CWE/CWE-200/ExposureSensitiveInformationUnauthorizedActor.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -10,8 +10,8 @@ int main(int argc, char *argv[])
{
FILE *fp;
char buf[128];
fp = fopen("myFile.txt","r+"); // BAD [NOT DETECTED]
fgets(buf,128,fp);
fp = fopen("myFile.txt","r+"); // $ MISSING: Alert // BAD [NOT DETECTED]
fgets(buf,128,fp);
fprintf(fp,"%s\n","data to file");
fclose(fp);
return 0;

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-243/IncorrectChangingWorkingDirectory.ql
query: experimental/Security/CWE/CWE-243/IncorrectChangingWorkingDirectory.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -9,13 +9,13 @@ int chdir(char *path);
void exit(int status);
int funTest1(){
if (chroot("/myFold/myTmp") == -1) { // BAD
if (chroot("/myFold/myTmp") == -1) { // $ Alert // BAD
exit(-1);
}
return 0;
}
int funTest2(){
int funTest2(){
if (chdir("/myFold/myTmp") == -1) { // GOOD
exit(-1);
}
@@ -25,8 +25,8 @@ int funTest2(){
return 0;
}
int funTest3(){
chdir("/myFold/myTmp"); // BAD
int funTest3(){
chdir("/myFold/myTmp"); // $ Alert // BAD
return 0;
}
int main(int argc, char *argv[])

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
query: experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -6,7 +6,7 @@ int fclose(FILE *stream);
void funcTest1()
{
umask(0666); // BAD
umask(0666); // $ Alert // BAD
FILE *fe;
fe = fopen("myFile.txt", "wt");
fclose(fe);
@@ -27,7 +27,7 @@ void funcTest2(int mode)
FILE *fe;
fe = fopen("myFile.txt", "wt");
fclose(fe);
chmod("myFile.txt",0555-mode); // BAD
chmod("myFile.txt",0555-mode); // $ Alert // BAD
}
void funcTest2g(int mode)

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-285/PamAuthorization.ql
query: experimental/Security/CWE/CWE-285/PamAuthorization.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -26,7 +26,7 @@ bool PamAuthBad(const std::string &username_in,
return false;
}
err = pam_authenticate(pamh, 0);
err = pam_authenticate(pamh, 0); // $ Alert
if (err != PAM_SUCCESS)
return err;

View File

@@ -7,7 +7,7 @@ namespace std{
CURLOPT_URL,
CURLOPT_SSL_VERIFYHOST,
CURLOPT_SSL_VERIFYPEER
};
};
CURL *curl_easy_init();
void curl_easy_cleanup(CURL *handle);
@@ -22,8 +22,8 @@ char host[] = "codeql.com";
void bad(void) {
std::unique_ptr<CURL> curl = std::unique_ptr<CURL>(curl_easy_init());
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, 0); // $ Alert
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, 0); // $ Alert
curl_easy_setopt(curl.get(), CURLOPT_URL, host);
curl_easy_perform(curl.get());
}
@@ -31,7 +31,7 @@ void bad(void) {
void good(void) {
std::unique_ptr<CURL> curl = std::unique_ptr<CURL>(curl_easy_init());
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, 2);
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, 2);
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, 2);
curl_easy_setopt(curl.get(), CURLOPT_URL, host);
curl_easy_perform(curl.get());
}
@@ -40,4 +40,3 @@ int main(int c, char** argv){
bad();
good();
}

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-295/CurlSSL.ql
query: experimental/Security/CWE/CWE-295/CurlSSL.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql
query: experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -54,7 +54,7 @@ void file()
FILE *file;
// BAD: write zipcode to file in cleartext
fputs(theZipcode, file);
fputs(theZipcode, file); // $ Alert
// GOOD: encrypt first
char *encrypted = encrypt(theZipcode);
@@ -71,15 +71,15 @@ int main(int argc, char **argv)
char *buff4;
// BAD: write medical to buffer in cleartext
sprintf(buff1, "%s", medical);
sprintf(buff1, "%s", medical); // $ Alert Source
// BAD: write medical to buffer in cleartext
char *temp = medical;
sprintf(buff2, "%s", temp);
char *temp = medical; // $ Source
sprintf(buff2, "%s", temp); // $ Alert
// BAD: write medical to buffer in cleartext
char *buff5 = func(medical);
sprintf(buff3, "%s", buff5);
char *buff5 = func(medical); // $ Source
sprintf(buff3, "%s", buff5); // $ Alert
char *buff6 = encrypt(medical);
// GOOD: encrypt first
@@ -93,10 +93,10 @@ void stream()
ofstream mystream;
// BAD: write zipcode to file in cleartext
mystream << "the zipcode is: " << theZipcode;
mystream << "the zipcode is: " << theZipcode; // $ Alert Source
// BAD: write zipcode to file in cleartext
(mystream << "the zipcode is: ").write(theZipcode, strlen(theZipcode));
(mystream << "the zipcode is: ").write(theZipcode, strlen(theZipcode)); // $ Alert
// GOOD: encrypt first
char *encrypted = encrypt(theZipcode);

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-369/DivideByZeroUsingReturnValue.ql
query: experimental/Security/CWE/CWE-369/DivideByZeroUsingReturnValue.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -44,13 +44,13 @@ int getSize2(int type) {
int badTestf1(int type, int met) {
int is = getSize(type);
if (met == 1) return 123 / is; // BAD
else return 123 / getSize2(type); // BAD
if (met == 1) return 123 / is; // $ Alert // BAD
else return 123 / getSize2(type); // $ Alert // BAD
}
int badTestf2(int type) {
int is;
is = getSize(type);
return 123 / is; // BAD
return 123 / is; // $ Alert // BAD
}
int badTestf3(int type, int met) {
@@ -58,31 +58,31 @@ int badTestf3(int type, int met) {
is = getSize(type);
switch (met) {
case 1:
if (is >= 0) return 123 / is; // BAD [NOT DETECTED]
if (is >= 0) return 123 / is; // $ MISSING: Alert // BAD [NOT DETECTED]
case 2:
if (0 == is) return 123 / is; // BAD [NOT DETECTED]
if (0 == is) return 123 / is; // $ MISSING: Alert // BAD [NOT DETECTED]
case 3:
if (!is & 123 / is) // BAD
if (!is & 123 / is) // $ Alert // BAD
return 123;
case 4:
if (!is | 123 / is) // BAD
if (!is | 123 / is) // $ Alert // BAD
return 123;
case 5:
if (123 / is || !is) // BAD
if (123 / is || !is) // $ Alert // BAD
return 123;
case 6:
if (123 / is && !is) // BAD
if (123 / is && !is) // $ Alert // BAD
return 123;
case 7:
if (!is) return 123 / is; // BAD
if (!is) return 123 / is; // $ Alert // BAD
case 8:
if (is > -1) return 123 / is; // BAD
if (is > -1) return 123 / is; // $ Alert // BAD
case 9:
if (is < 2) return 123 / is; // BAD
if (is < 2) return 123 / is; // $ Alert // BAD
}
if (is != 0) return -1;
if (is == 0) type += 1;
return 123 / is; // BAD [NOT DETECTED]
return 123 / is; // $ MISSING: Alert // BAD [NOT DETECTED]
}
int goodTestf3(int type, int met) {
@@ -92,7 +92,7 @@ int goodTestf3(int type, int met) {
case 1:
if (is < 0) return 123 / is; // GOOD
case 2:
if (!is && 123 / is) // GOOD
if (!is && 123 / is) // GOOD
return 123;
case 3:
if (!is || 123 / is) // GOOD
@@ -112,10 +112,10 @@ int goodTestf3a(int type, int met) {
if (is < 0)
return 123 / is; // GOOD
case 2:
if (!is && 123 / is) // GOOD
if (!is && 123 / is) // GOOD
return 123;
case 3:
if (!is || 123 / is) // GOOD
if (!is || 123 / is) // GOOD
return 123;
}
return 1;
@@ -125,20 +125,20 @@ int badTestf4(int type) {
int is = getSize(type);
int d;
d = type * is;
return 123 / d; // BAD
return 123 / d; // $ Alert // BAD
}
int badTestf5(int type) {
int is = getSize(type);
int d;
d = is / type;
return 123 / d; // BAD
return 123 / d; // $ Alert // BAD
}
int badTestf6(int type) {
int is = getSize(type);
int d;
d = is / type;
return type * 123 / d; // BAD
return type * 123 / d; // $ Alert // BAD
}
int badTestf7(int type, int met) {
@@ -150,7 +150,7 @@ int badTestf7(int type, int met) {
return 123 / is; // GOOD
}
quit:
return 123 / is; // BAD
return 123 / is; // $ Alert // BAD
}
int goodTestf7(int type, int met) {
@@ -169,8 +169,8 @@ int goodTestf7(int type, int met) {
int badTestf8(int type) {
int is = getSize(type);
type /= is; // BAD
type %= is; // BAD
type /= is; // $ Alert // BAD
type %= is; // $ Alert // BAD
return type;
}
@@ -184,7 +184,7 @@ float getSizeFloat(float type) {
}
float badTestf9(float type) {
float is = getSizeFloat(type);
return 123 / is; // BAD
return 123 / is; // $ Alert // BAD
}
float goodTestf9(float type) {
float is = getSizeFloat(type);
@@ -196,18 +196,18 @@ int badTestf10(int type) {
int out = type;
int is = getSize(type);
if (is > -2) {
out /= 123 / (is + 1); // BAD
out /= 123 / (is + 1); // $ Alert // BAD
}
if (is > 0) {
return 123 / (is - 1); // BAD
return 123 / (is - 1); // $ Alert // BAD
}
if (is <= 0) return 0;
return 123 / (is - 1); // BAD
return 123 / (is - 1); // $ Alert // BAD
return 0;
}
int badTestf11(int type) {
int is = getSize(type);
return 123 / (is - 3); // BAD
return 123 / (is - 3); // $ Alert // BAD
}
int goodTestf11(int type) {
@@ -223,7 +223,7 @@ int badTestf12(FILE * f) {
int a;
int ret = -1;
a = getc(f);
if (a == 0) ret = 123 / a; // BAD [NOT DETECTED]
if (a == 0) ret = 123 / a; // $ MISSING: Alert // BAD [NOT DETECTED]
return ret;
}
@@ -255,14 +255,14 @@ int badMySubDiv(int type, int is) {
void badTestf13(int type) {
int is = getSize(type);
badMyDiv(type, is); // BAD
badMyDiv(type, is - 2); // BAD
badMySubDiv(type, is); // BAD
badMyDiv(type, is); // $ Alert // BAD
badMyDiv(type, is - 2); // $ Alert // BAD
badMySubDiv(type, is); // $ Alert // BAD
goodMyDiv(type, is); // GOOD
if (is < 5)
badMySubDiv(type, is); // BAD
badMySubDiv(type, is); // $ Alert // BAD
if (is < 0)
badMySubDiv(type, is); // BAD [NOT DETECTED]
badMySubDiv(type, is); // $ MISSING: Alert // BAD [NOT DETECTED]
if (is > 5)
badMySubDiv(type, is); // GOOD
if (is == 0)
@@ -270,9 +270,9 @@ void badTestf13(int type) {
if (is > 0)
badMyDiv(type, is); // GOOD
if (is < 5)
badMyDiv(type, is - 3); // BAD
badMyDiv(type, is - 3); // $ Alert // BAD
if (is < 0)
badMyDiv(type, is + 1); // BAD
badMyDiv(type, is + 1); // $ Alert // BAD
if (is > 5)
badMyDiv(type, is - 3); // GOOD
}

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-377/InsecureTemporaryFile.ql
query: experimental/Security/CWE/CWE-377/InsecureTemporaryFile.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -13,7 +13,7 @@ int fclose(FILE *stream);
int funcTest1()
{
FILE *fp;
char *filename = tmpnam(NULL); // BAD
char *filename = tmpnam(NULL); // $ Alert // BAD
fp = fopen(filename,"w");
fprintf(fp,"%s\n","data to file");
fclose(fp);
@@ -39,7 +39,7 @@ int funcTest3()
FILE *fp;
char filename[80];
strcat(filename, "/tmp/tmp.name");
fp = fopen(filename,"w"); // BAD [NOT DETECTED]
fp = fopen(filename,"w"); // $ MISSING: Alert // BAD [NOT DETECTED]
fprintf(fp,"%s\n","data to file");
fclose(fp);
return 0;

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql
query: experimental/Security/CWE/CWE-401/MemoryLeakOnFailedCallToRealloc.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -31,7 +31,7 @@ unsigned char * badResize_0(unsigned char * buffer,size_t currentSize,size_t new
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
}
return buffer;
}
@@ -60,7 +60,7 @@ unsigned char * badResize_1_0(unsigned char * buffer,size_t currentSize,size_t n
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
}
return buffer;
}
@@ -136,7 +136,7 @@ unsigned char * badResize_1_1(unsigned char * buffer,size_t currentSize,size_t n
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
}
if(!buffer)
aFakeFailed_1(1, 1);
@@ -183,7 +183,7 @@ unsigned char * badResize_2_0(unsigned char * buffer,size_t currentSize,size_t n
assert(buffer!=0);
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
}
return buffer;
}
@@ -279,7 +279,7 @@ unsigned char *goodResize_3_1(unsigned char *buffer, size_t currentSize, size_t
unsigned char *tmp = buffer;
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
if (buffer == NULL)
{
free(tmp);
@@ -296,7 +296,7 @@ unsigned char *goodResize_3_2(unsigned char *buffer, size_t currentSize, size_t
unsigned char *tmp = buffer;
if (currentSize < newSize)
{
tmp = (unsigned char *)realloc(tmp, newSize);
tmp = (unsigned char *)realloc(tmp, newSize); // $ Alert
if (tmp != 0)
{
buffer = tmp;
@@ -325,7 +325,7 @@ unsigned char * badResize_5_2(unsigned char *buffer, size_t currentSize, size_t
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
}
if (cond)
{
@@ -339,7 +339,7 @@ unsigned char * badResize_5_1(unsigned char *buffer, size_t currentSize, size_t
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
buffer = (unsigned char *)realloc(buffer, newSize); // $ Alert
assert(cond); // irrelevant
}
return buffer;

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-409/DecompressionBombs.ql
query: experimental/Security/CWE/CWE-409/DecompressionBombs.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -15,12 +15,12 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
void brotli_test(int argc, const char **argv) {
uint8_t output[1024];
size_t output_size = sizeof(output);
BrotliDecoderDecompress(1024, (uint8_t *) argv[2], &output_size, output); // BAD
BrotliDecoderDecompress(1024, (uint8_t *) argv[2], &output_size, output); // $ Alert // BAD
size_t input_size = 1024;
const uint8_t *input_p = (const uint8_t*)argv[2];
uint8_t *output_p = output;
size_t out_size;
BrotliDecoderDecompressStream(0, &input_size, &input_p, &output_size, // BAD
BrotliDecoderDecompressStream(0, &input_size, &input_p, &output_size, // $ Alert // BAD
&output_p, &out_size);
}

View File

@@ -19,7 +19,7 @@ static int read_data(archive *ar) {
size_t size;
la_int64_t offset;
int r = archive_read_data_block(ar, &buff, &size, &offset); // BAD
int r = archive_read_data_block(ar, &buff, &size, &offset); // $ Alert // BAD
if (r == ARCHIVE_EOF)
return ARCHIVE_OK;
if (r < ARCHIVE_OK)

View File

@@ -4,7 +4,7 @@ void minizip_test(int argc, const char **argv);
void zlib_test(int argc, const char **argv);
void zstd_test(int argc, const char **argv);
int main(int argc, const char **argv) {
int main(int argc, const char **argv) { // $ Source
brotli_test(argc, argv);
libarchive_test(argc, argv);
minizip_test(argc, argv);

View File

@@ -14,7 +14,7 @@ void minizip_test(int argc, const char **argv) {
int32_t bytes_read;
char buf[4096];
while(true) {
bytes_read = mz_zip_entry_read(zip_handle, (char *) argv[1], sizeof(buf)); // BAD
bytes_read = mz_zip_entry_read(zip_handle, (char *) argv[1], sizeof(buf)); // $ Alert // BAD
if (bytes_read <= 0) {
break;
}
@@ -23,7 +23,7 @@ void minizip_test(int argc, const char **argv) {
void *zip_reader = mz_zip_reader_create();
mz_zip_reader_open_file(zip_reader, argv[1]);
mz_zip_reader_goto_first_entry(zip_reader);
mz_zip_reader_entry_save(zip_reader, 0, 0); // BAD
mz_zip_reader_entry_save(zip_reader, 0, 0); // $ Alert // BAD
UnzOpen(argv[3]); // BAD
UnzOpen(argv[3]); // $ Alert // BAD
}

View File

@@ -22,7 +22,7 @@ void UnsafeInflate(char *input) {
infstream.next_out = output; // output char array
inflateInit(&infstream);
inflate(&infstream, 0); // BAD
inflate(&infstream, 0); // $ Alert // BAD
}
@@ -38,7 +38,7 @@ void UnsafeGzread(char *fileName) {
gzFile inFileZ = gzopen(fileName, "rb");
unsigned char unzipBuffer[8192];
while (true) {
if (gzread(inFileZ, unzipBuffer, 8192) <= 0) { // BAD
if (gzread(inFileZ, unzipBuffer, 8192) <= 0) { // $ Alert // BAD
break;
}
}
@@ -48,7 +48,7 @@ void UnsafeGzfread(char *fileName) {
gzFile inFileZ = gzopen(fileName, "rb");
while (true) {
char buffer[1000];
if (!gzfread(buffer, 999, 1, inFileZ)) { // BAD
if (!gzfread(buffer, 999, 1, inFileZ)) { // $ Alert // BAD
break;
}
}
@@ -59,7 +59,7 @@ void UnsafeGzgets(char *fileName) {
char *buffer = new char[4000000000];
char *result;
while (true) {
result = gzgets(inFileZ, buffer, 1000000000); // BAD
result = gzgets(inFileZ, buffer, 1000000000); // $ Alert // BAD
if (result == nullptr) {
break;
}
@@ -74,7 +74,7 @@ void InflateString(char *input) {
uLong source_length = 500;
uLong destination_length = sizeof(output);
uncompress(output, &destination_length, (Bytef *) input, source_length); // BAD
uncompress(output, &destination_length, (Bytef *) input, source_length); // $ Alert // BAD
}
void zlib_test(int argc, char **argv) {

View File

@@ -36,7 +36,7 @@ void zstd_test(int argc, const char **argv) {
ZSTD_inBuffer input = {buffIn, read, 0};
while (input.pos < input.size) {
ZSTD_outBuffer output = {buffOut, buffOutSize, 0};
size_t const ret = ZSTD_decompressStream(dctx, &output, &input); // BAD
size_t const ret = ZSTD_decompressStream(dctx, &output, &input); // $ Alert // BAD
CHECK_ZSTD(ret);
}
}

View File

@@ -1 +1,2 @@
experimental/Security/CWE/CWE-415/DoubleFree.ql
query: experimental/Security/CWE/CWE-415/DoubleFree.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -8,14 +8,14 @@ void workFunction_0(char *s) {
char *buf;
buf = (char *) malloc(intSize);
free(buf); // GOOD
if(buf) free(buf); // BAD
if(buf) free(buf); // $ Alert // BAD
}
void workFunction_1(char *s) {
int intSize = 10;
char *buf;
buf = (char *) malloc(intSize);
free(buf); // GOOD
free(buf); // BAD
free(buf); // $ Alert // BAD
}
void workFunction_2(char *s) {
int intSize = 10;
@@ -54,7 +54,7 @@ void workFunction_5(char *s, int intFlag) {
if(intFlag) {
free(buf); // GOOD
}
free(buf); // BAD
free(buf); // $ Alert // BAD
}
void workFunction_6(char *s, int intFlag) {
int intSize = 10;
@@ -75,7 +75,7 @@ void workFunction_7(char *s) {
char *buf1;
buf = (char *) malloc(intSize);
buf1 = (char *) realloc(buf,intSize*4);
free(buf); // BAD
free(buf); // $ Alert // BAD
}
void workFunction_8(char *s) {
int intSize = 10;

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