Compare commits

..

395 Commits

Author SHA1 Message Date
Paolo Tranquilli
ff78ac98d2 Merge pull request #13249 from github/redsun82/swift-hidden-ast
Swift: make only certain elements hideable in the AST
2023-05-24 11:22:10 +02:00
Arthur Baars
7c5fef37eb Merge pull request #13257 from smowton/smowton/hotfix/useless-assignment-to-field-exclude-method-receivers
Hotfix: Go: exclude method receivers from dead-store-of-field query
2023-05-23 16:20:34 +02:00
Paolo Tranquilli
09ce29b79f Merge branch 'codeql-cli-2.13.3' into redsun82/swift-hidden-ast 2023-05-23 16:12:54 +02:00
Paolo Tranquilli
a14f7dd153 Merge pull request #13238 from github/redsun82/swift-remove-props-from-interpolated-strings
Swift: remove unneeded properties from `InterpolatedStringLiteralExpr`
2023-05-23 15:57:31 +02:00
Paolo Tranquilli
fce33d369b Merge branch 'codeql-cli-2.13.3' into redsun82/swift-hidden-ast 2023-05-23 15:31:29 +02:00
Chris Smowton
99c211955b Hotfix: Go: exclude method receivers from dead-store-of-field query 2023-05-23 14:31:25 +01:00
Geoffrey White
b2a958f8d3 Merge pull request #13163 from geoffw0/cleartextlogging
Swift: Make the cleartext logging query consistent with other cleartext-* queries.
2023-05-23 14:14:56 +01:00
Paolo Tranquilli
86eecea5f6 Merge branch 'codeql-cli-2.13.3' into cleartextlogging 2023-05-23 14:44:36 +02:00
Paolo Tranquilli
aca85d76ee Merge branch 'codeql-cli-2.13.3' into redsun82/swift-remove-props-from-interpolated-strings 2023-05-23 14:42:00 +02:00
Paolo Tranquilli
f964d196dc Merge pull request #13213 from geoffw0/hideenumcasedecl
Swift: Add EnumDecl.getEnumElement(_)
2023-05-23 14:37:02 +02:00
Chris Smowton
8b28848c82 Merge pull request #13250 from smowton/smowton/hotfix/golang-field-store-varargs-function
Hotfix: Go: count passing to a vararg function as escaping
2023-05-23 12:03:48 +01:00
Paolo Tranquilli
67d4788dc5 Merge branch 'codeql-cli-2.13.3' into hideenumcasedecl 2023-05-23 12:53:07 +02:00
Paolo Tranquilli
7aac538480 Merge branch 'codeql-cli-2.13.3' into redsun82/swift-remove-props-from-interpolated-strings 2023-05-23 12:47:17 +02:00
Paolo Tranquilli
b4edc92079 Swift: make hideability spread upward in the hierarchy 2023-05-23 12:45:18 +02:00
Paolo Tranquilli
b19194bd06 Swift: make only Expr, Pattern and Type hideable 2023-05-23 12:45:18 +02:00
Paolo Tranquilli
a087fef335 Swift: implement @ql.hideable 2023-05-23 12:45:18 +02:00
Paolo Tranquilli
7dd18ff801 Swift: add @ql.hideable to schema loading 2023-05-23 12:45:18 +02:00
Arthur Baars
89985e2cb7 Merge pull request #13252 from github/redsun82/swift-workflow
Swift: trigger workflow on `codeql-cli-*`
2023-05-23 12:43:44 +02:00
Paolo Tranquilli
0574f2784f Swift: trigger workflow on codeql-cli-* 2023-05-23 12:32:28 +02:00
Arthur Baars
674c31d54d Merge pull request #13243 from github/release-prep/2.13.3
Release preparation for version 2.13.3
2023-05-23 12:31:51 +02:00
Paolo Tranquilli
6059d8c007 Merge branch 'codeql-cli-2.13.3' into hideenumcasedecl 2023-05-23 12:19:57 +02:00
Chris Smowton
d5d56cde5a Dead store of field: count passing to a vararg function as escaping 2023-05-23 10:51:21 +01:00
Paolo Tranquilli
c9c1f08de7 Swift: mark downgrade as backwards compatible 2023-05-23 08:36:49 +02:00
github-actions[bot]
7aa23cf11d Release preparation for version 2.13.3 2023-05-22 20:47:00 +00:00
Jeroen Ketema
a319fc0044 Merge pull request #13234 from jketema/std-inline
C++: Include inline namespaces in `StdNamespace`
2023-05-22 19:56:15 +02:00
Geoffrey White
3bcaff6059 Swift: re-run codegen. 2023-05-22 16:37:03 +01:00
Geoffrey White
830686218f Merge branch 'main' into hideenumcasedecl 2023-05-22 16:35:28 +01:00
Tom Hvitved
97b0012a5e Merge pull request #13233 from hvitved/ruby/type-tracking-summary-ret-node
Ruby: Allow for flow out of callbacks passed to summarized methods in type tracking
2023-05-22 16:05:18 +02:00
Jeroen Ketema
f31ab3a7e7 C++: Add change note 2023-05-22 16:00:12 +02:00
Paolo Tranquilli
9a0f87434e Swift: remove unneeded properties from InterpolatedStringLiteralExpr
These properties were unused in the QL library (hence the full
upgrade/downgrade compatibility).
2023-05-22 15:28:54 +02:00
Mathias Vorreiter Pedersen
e3a5805916 Merge pull request #13237 from jketema/pointer-deref-fp
C++: Add `cpp/invalid-pointer-deref` false positives
2023-05-22 14:27:14 +01:00
Philip Ginsbach
cff4317cb1 Merge pull request #13236 from github/ginsbach/IdentifierSpecification
repair and update the Identifier section of the QL specification
2023-05-22 14:26:46 +01:00
Jeroen Ketema
ec265c6bb2 Merge pull request #13229 from MathiasVP/add-fp-testcase
C++: Add FP testcase for `cpp/overrun-write`
2023-05-22 15:26:13 +02:00
Paolo Tranquilli
f56ffbc25e Merge pull request #13232 from github/redsun82/swift-hidden-ast
Swift: fix hidden AST getters
2023-05-22 14:47:11 +02:00
Jeroen Ketema
3f289b1c99 C++: Add cpp/invalid-pointer-deref false positives 2023-05-22 14:34:59 +02:00
Philip Ginsbach
35114d5ac4 introduce parameterName rule 2023-05-22 11:48:13 +01:00
Philip Ginsbach
42e81015d0 mention signatureExpr in section on use of identifier rules 2023-05-22 11:48:13 +01:00
Philip Ginsbach
d98fcdd6aa do not use upperId directly in type signature rules 2023-05-22 11:48:13 +01:00
Philip Ginsbach
b707815370 do not use simpleId directly in module expression rules 2023-05-22 11:48:06 +01:00
Philip Ginsbach
7ace4cd43e add rule for module signature names (differing from module names) 2023-05-22 11:44:59 +01:00
Tom Hvitved
20efe81f10 Update ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll
Co-authored-by: Asger F <asgerf@github.com>
2023-05-22 12:43:05 +02:00
Philip Ginsbach
d4ab1c9643 such identifiers do not actually exist in QL 2023-05-22 11:22:47 +01:00
Erik Krogh Kristensen
3647b9cfeb Merge pull request #13196 from erik-krogh/indirectCommand
JS: require arguments to be shell interpreted to be flagged by indirect-command-injection
2023-05-22 11:53:57 +02:00
Jeroen Ketema
f46183d0ba C++: Include inline namespaces in StdNamespace 2023-05-22 11:41:49 +02:00
Tom Hvitved
33be52f0b7 Ruby: Allow for flow out of callbacks passed to summarized methods in type tracking 2023-05-22 11:01:08 +02:00
Paolo Tranquilli
20893bdef5 Swift: accept test changes after hidden AST fix 2023-05-22 10:14:29 +02:00
Tony Torralba
05c30e8fac Merge pull request #13230 from atorralba/atorralba/java/groove-template-engine-sink
Java: Add TemplateEngine.createTemplate as a Groovy injection sink
2023-05-22 10:04:29 +02:00
Paolo Tranquilli
de03bdc235 Swift: fix hidden AST getters
For consistency with the C/C++ QL library, getters of AST elements
within the hidden AST should not themselves skip other hidden AST
elements.
2023-05-22 09:57:48 +02:00
Tom Hvitved
224a2c3d91 Merge pull request #13231 from hvitved/ruby/type-tracker-missing-callback-flow-out
Ruby: Allow for flow through callbacks to summarized methods in type tracking
2023-05-22 09:38:59 +02:00
Tom Hvitved
128168a7e7 Ruby: Allow for flow through callbacks to summarized methods in type tracking 2023-05-21 20:51:45 +02:00
Mathias Vorreiter Pedersen
58f4b7696d Merge pull request #13223 from geoffw0/useasnominaltypedecl
Swift: Use asNominalTypeDecl more.
2023-05-19 16:53:28 +01:00
Tony Torralba
b58eb3a92c Java: Add TemplateEngine.createTemplate as a groovy injection sink 2023-05-19 17:45:47 +02:00
Mathias Vorreiter Pedersen
c15ebf83ee C++: Add testcase with FP (and also fix an incorrect test annotation). 2023-05-19 16:38:18 +01:00
Philip Ginsbach
999e7f96c7 Merge pull request #13222 from github/ginsbach/SignatureSyntax
add syntax for signature definitions to QL specification
2023-05-19 16:22:45 +01:00
Geoffrey White
881134a6f5 Swift: Add warning note to Decl.getMember. 2023-05-19 16:12:09 +01:00
Alexandre Boulgakov
f943502e41 Merge pull request #13224 from github/sashabu/tsp-empty-help-links
Swift: Drop support for plaintext diagnostics (and `helpLinks`).
2023-05-19 15:44:44 +01:00
Alexandre Boulgakov
b3e76d6052 Swift: Drop support for plaintext diagnostics (and helpLinks).
The recommended option is Markdown diagnostics, and we have already migrated everything to emit them. The empty help link we're currently emitting everywhere is a bug.
2023-05-19 15:16:02 +01:00
Alexandre Boulgakov
a1beaa6300 Merge pull request #13186 from github/redsun82/swift-diagnostics-wording
Swift: reword TSP diagnostics after doc team review
2023-05-19 15:15:46 +01:00
Geoffrey White
5ffde7a762 Update swift/ql/lib/codeql/swift/elements/decl/EnumDecl.qll
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2023-05-19 14:55:39 +01:00
Alexandre Boulgakov
110b766770 Swift: Add a . to a test message to match the logging API change in this PR. 2023-05-19 14:46:12 +01:00
Philip Ginsbach
6957857773 add syntax for signature declarations to QL specification 2023-05-19 14:44:29 +01:00
Alexandre Boulgakov
1e9b849e93 Merge branch 'main' into redsun82/swift-diagnostics-wording 2023-05-19 14:43:01 +01:00
Alexandre Boulgakov
8f7279ee05 Swift: TSP message wording changes. 2023-05-19 14:39:57 +01:00
Alexandre Boulgakov
5bb2eb4155 Swift: TSP message wording changes.
Co-authored-by: Isaac Brown <101839405+isaacmbrown@users.noreply.github.com>
2023-05-19 14:37:18 +01:00
Alexandre Boulgakov
137b4a99ef Swift: TSP message wording changes.
Co-authored-by: Isaac Brown <101839405+isaacmbrown@users.noreply.github.com>
2023-05-19 14:36:24 +01:00
Alexandre Boulgakov
ddcac20a94 Swift: TSP message wording changes.
Co-authored-by: Isaac Brown <101839405+isaacmbrown@users.noreply.github.com>
2023-05-19 14:36:14 +01:00
Alexandre Boulgakov
8a15af5614 Swift: TSP message wording changes.
Co-authored-by: Isaac Brown <101839405+isaacmbrown@users.noreply.github.com>
2023-05-19 14:36:04 +01:00
Geoffrey White
68bdd51dd3 Swift: Add QLDoc encouraging this pattern. 2023-05-19 14:35:08 +01:00
Geoffrey White
0d8aa825d9 Swift: Use asNominalType() more widely to include things declared in extensions. 2023-05-19 14:19:32 +01:00
Geoffrey White
ccbd041875 Swift: Use asNominalTypeDecl() to simplify models. 2023-05-19 14:04:49 +01:00
Mathias Vorreiter Pedersen
2206216dbb Merge pull request #13221 from geoffw0/filepath
Swift: Taint model for FilePath
2023-05-19 14:01:22 +01:00
Geoffrey White
c8dfc87dae Swift: getName -> getFullName. 2023-05-19 12:18:17 +01:00
Geoffrey White
13755ad5f5 Swift: Remove placeholder lines I had left in. 2023-05-19 11:42:00 +01:00
Tony Torralba
babf429c9a Merge pull request #13220 from github/workflow/coverage/update
Update CSV framework coverage reports
2023-05-19 08:57:15 +02:00
github-actions[bot]
66f2579437 Add changed framework coverage reports 2023-05-19 00:15:25 +00:00
Geoffrey White
6dfad79972 Swift: Model FilePath. 2023-05-18 18:56:08 +01:00
Geoffrey White
371bcc55fa Swift: Consolidate and extend tests of taint flow through FilePath. 2023-05-18 18:01:38 +01:00
Alexandre Boulgakov
fa52c32564 Merge pull request #13170 from github/sashabu/internal-error-tsp
Swift: Emit diagnostics on assertion/expectation violations.
2023-05-18 17:19:43 +01:00
Mathias Vorreiter Pedersen
e0263a719e Merge pull request #13218 from MathiasVP/c18-to-c17
C++: Replace `C18` with `C17` in documentation
2023-05-18 16:42:15 +01:00
Mathias Vorreiter Pedersen
70b08a093c C++: Replace 'C18' with 'C17'. 2023-05-18 15:55:21 +01:00
Mathias Vorreiter Pedersen
8f7bb8b11f Merge pull request #13217 from MathiasVP/cleanup-overrun-write-product-flow
C++: Small cleanup of `cpp/overrun-write`
2023-05-18 13:59:44 +01:00
Tony Torralba
a8afa4785e Merge pull request #13140 from atorralba/atorralba/java/spring-jdbc-namedparam-models
Java: Add SQLi sinks for Spring JDBC
2023-05-18 14:49:28 +02:00
Mathias Vorreiter Pedersen
a77c62473e C++: Reduce code-duplication in 'cpp/overrun-write'. 2023-05-18 13:23:15 +01:00
Mathias Vorreiter Pedersen
8cf25ba421 Merge pull request #13191 from MathiasVP/fix-pointer-pointee-conflation
C++: Fix pointer/pointee conflation
2023-05-18 13:09:10 +01:00
Mathias Vorreiter Pedersen
2e734755fb Merge pull request #13215 from MathiasVP/update-qldoc-on-typemention
C++: Update documentation for `TypeMention`
2023-05-18 10:24:13 +01:00
Jeroen Ketema
34fdeb4e6b Merge pull request #13203 from jketema/deref-size
C++: Use range analysis-based `hasSize` predicate in `cpp/invalid-pointer-deref`
2023-05-18 11:03:09 +02:00
Geoffrey White
d26a86185f Swift: Codegen. 2023-05-18 09:43:13 +01:00
Geoffrey White
f0ce5b09c6 Swift: Address QL-for-QL warning. 2023-05-18 09:43:07 +01:00
Mathias Vorreiter Pedersen
a475efbe39 Update cpp/ql/lib/semmle/code/cpp/Type.qll 2023-05-18 09:37:20 +01:00
Mathias Vorreiter Pedersen
f3b6b470f4 C++: Update documentation for 'TypeMention'. 2023-05-18 09:32:31 +01:00
Tony Torralba
2c54996499 Apply @jcogs33's suggestions from code review 2023-05-18 08:51:19 +02:00
Geoffrey White
3539e55bb2 Swift: Autoformat. 2023-05-17 19:21:41 +01:00
Geoffrey White
6c35bbf5c2 Swift: Simplify / focus the test. 2023-05-17 19:15:27 +01:00
Geoffrey White
95caaecd71 Swift: Add EnumDecl.getEnumElement(_). 2023-05-17 19:05:27 +01:00
Geoffrey White
66b13e2294 Swift: Add a test of enum decls. 2023-05-17 19:01:57 +01:00
Tony Torralba
1b06bf132c Merge pull request #12932 from atorralba/atorralba/java/promote-xxe-experimental-sinks
Java: Promote experimental XXE sinks
2023-05-17 17:39:31 +02:00
Óscar San José
cc36e3c809 Merge pull request #13192 from github/post-release-prep/codeql-cli-2.13.2-fix-release-notes-check
Change regexp to include released change-notes pattern in check-change-note CI check
2023-05-17 17:28:59 +02:00
Jeroen Ketema
d1efffe492 Merge branch 'main' into deref-size 2023-05-17 17:13:49 +02:00
Jeroen Ketema
e3aecd3f1f Merge pull request #13200 from jketema/deref-subpath
C++: Implement the `subpaths` query predicate for `cpp/invalid-pointer-deref`
2023-05-17 17:13:28 +02:00
Óscar San José
f72afd0727 fixing typo 2023-05-17 17:08:37 +02:00
Michael Nebel
5a1c001f07 Merge pull request #13204 from michaelnebel/csharp/madextensionmethodtest
C#: Add extension method testcase for Models as Data.
2023-05-17 16:14:13 +02:00
Mathias Vorreiter Pedersen
f1530aa4b4 Merge pull request #12977 from RasmusWL/accept-expected-changes-from-ci-script
Misc: Add script to accept `.expected` changes from CI
2023-05-17 14:55:23 +01:00
yoff
1c6d643b53 Merge pull request #13146 from yoff/python/container-summaries-1
Python: Container summaries, part 1
2023-05-17 15:45:37 +02:00
Erik Krogh Kristensen
239234c5d2 fix bad change-note
Co-authored-by: Asger F <asgerf@github.com>
2023-05-17 14:47:32 +02:00
Óscar San José
baddfc4357 Suggestion from CR 2023-05-17 14:47:28 +02:00
Mathias Vorreiter Pedersen
06d5a7f0ef Merge pull request #13139 from MathiasVP/faster-product-flow
C++: Speedup product dataflow
2023-05-17 13:40:39 +01:00
Asger F
13a989b390 Merge pull request #13194 from asgerf/js/remove-mention-of-tracked-node
JS: remove mention of TrackedNode from docs
2023-05-17 13:44:07 +02:00
Michael Nebel
c2ec1b0a81 C#: Add extension method testcase for Models as Data. 2023-05-17 13:11:32 +02:00
AlexDenisov
6a8855e1e5 Merge pull request #13201 from github/alexdenisov/make-swift-versions-more-reasonable
Swift: bump all versions to 0.1.0
2023-05-17 11:43:14 +01:00
Jeroen Ketema
8ad11595cb Merge pull request #13199 from jketema/private-prod-flow
C++: Add forgotten `private` specifiers in product flow
2023-05-17 12:33:26 +02:00
Jeroen Ketema
e143002ae5 Merge pull request #13197 from jketema/test-annotation
C++: Add forgotten test annotation for `cpp/invalid-pointer-deref` test
2023-05-17 12:32:58 +02:00
Stephan Brandauer
7c02a9b6ea Merge pull request #13185 from github/fix-automodel-extraction-parameterName
Java: Automodel Extraction Parameter Name Fix
2023-05-17 12:16:44 +02:00
Jeroen Ketema
014eb255bb C++: Update expected test results 2023-05-17 12:09:22 +02:00
erik-krogh
5a82454710 add change-note 2023-05-17 12:02:21 +02:00
Jeroen Ketema
b83aaf9594 C++: Use range analysis-based hasSize predicate in cpp/invalid-pointer-deref
This is copied from `cpp/overrun-write`.
2023-05-17 11:39:41 +02:00
Alex Denisov
7e15386376 Swift: bump all versions to 0.1.0 2023-05-17 11:28:28 +02:00
Jeroen Ketema
31ae513f8c C++: Implement the subpaths query predicate for cpp/invalid-pointer-deref 2023-05-17 11:27:37 +02:00
Jeroen Ketema
883ec7a0e9 C++: Add forgotten private specifiers in product flow 2023-05-17 11:24:46 +02:00
Jeroen Ketema
b1c1513a10 C++: Add forgotten test annotation in for cpp/invalid-pointer-deref test 2023-05-17 11:21:09 +02:00
erik-krogh
cbd7601a41 implement isShellInterpreted on ExecActionsCall 2023-05-17 11:07:48 +02:00
erik-krogh
3293a55e8f require arguments to be shell interpreted to be flagged by indirect-command-injection 2023-05-17 11:07:45 +02:00
Tom Hvitved
b46983a381 Merge pull request #13068 from hvitved/ruby/type-tracking-flow-through
Ruby: Include `self` parameters in type tracking flow-through logic
2023-05-17 10:59:01 +02:00
Asger F
f47acfb083 JS: Trim whitespace 2023-05-17 10:37:19 +02:00
Stephan Brandauer
a5ef738bb0 add extra parameters in query-messages 2023-05-17 08:37:18 +00:00
Asger F
f94fdc6348 JS: Remove mention of TrackedNode in docs 2023-05-17 10:37:12 +02:00
Tom Hvitved
867bdcf74d Merge pull request #13183 from hvitved/csharp/ilogger-extension-methods
C#: Include arguments to `ILogger` extension method calls in `LogMessageSink`
2023-05-17 08:20:57 +02:00
Óscar San José
c599460a52 Change regexp to include released change-notes pattern 2023-05-16 21:53:09 +02:00
Jeroen Ketema
2dcdc71e45 Merge pull request #13142 from MathiasVP/precompute-states-in-overrun-write
C++: Restrict flow-state space of `cpp/overrun-write`
2023-05-16 21:31:56 +02:00
Alexandre Boulgakov
060a48571a Swift: Emit diagnostics on assertion/expectation violations. 2023-05-16 19:40:00 +01:00
Michael B. Gale
f5b04ab859 Merge pull request #13187 from github/mbg/java/fix-java-version-too-old-more
Java: Use empty toolchains.xml for the `java-version-too-old` test
2023-05-16 19:26:07 +01:00
Mathias Vorreiter Pedersen
402212bab9 C++: Accept query test changes. 2023-05-16 18:35:05 +01:00
Alexandre Boulgakov
7ada125299 Swift: Support fmtlib for assertions/expectations.
Specifically, this adds custom formatters using `path::operator string()` and `error_code::message()` and dereferences a (non-empty) optional. `fmtlib` provides formatters for these standard library types in `fmt/std.h`, but that file also requires RTTI (which we disable) for `std::exception` so we can't use it without either patching `fmtlib` (which they're open to: https://github.com/fmtlib/fmt/issues/3170) or enabling RTTI (which will require some consideration).
2023-05-16 18:33:28 +01:00
Mathias Vorreiter Pedersen
a5632a21d1 Merge branch 'main' into precompute-states-in-overrun-write 2023-05-16 18:09:16 +01:00
Mathias Vorreiter Pedersen
99545420d5 Merge pull request #13177 from MathiasVP/recommend-secure-randomness
Swift: Recommend a proper source of randomness in `swift/hardcoded-key`
2023-05-16 18:04:13 +01:00
Mathias Vorreiter Pedersen
9def3dd440 Update swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2023-05-16 17:42:34 +01:00
Geoffrey White
3bd16fa1d8 Merge pull request #13184 from geoffw0/docconsistency
Swift: Mirror changes made in the tutorial docs.
2023-05-16 17:42:03 +01:00
Mathias Vorreiter Pedersen
c93a051243 C++: Accept test changes. 2023-05-16 17:41:41 +01:00
Mathias Vorreiter Pedersen
150d4f341a C++: Fix looping flow that goes from the output argument node and back into the function argument. 2023-05-16 17:39:59 +01:00
Mathias Vorreiter Pedersen
35e91bafa7 C++: Introduce 'indirect_sink' in dataflow tests. 2023-05-16 17:39:53 +01:00
Mathias Vorreiter Pedersen
f5be8cfe58 Merge pull request #13167 from geoffw0/sensitivefps
Swift: Fix some FPs from the sensitive data library
2023-05-16 17:12:47 +01:00
Mathias Vorreiter Pedersen
afd1a120ff Merge pull request #13182 from MathiasVP/add-conflation-in-dataflow
C++: Add example with conflation in dataflow
2023-05-16 17:11:18 +01:00
Michael B. Gale
2d80302108 Use empty toolchains.xml for java-version-too-old 2023-05-16 16:54:19 +01:00
Paolo Tranquilli
42d40900d3 Swift: reword TSP diagnostics after doc team review 2023-05-16 17:52:02 +02:00
Mathias Vorreiter Pedersen
c45032844e C++: Add example with conflation in dataflow. 2023-05-16 16:34:20 +01:00
Stephan Brandauer
2cd8a879a5 use asParameter().getName() instead of toString()
Co-authored-by: Taus <tausbn@github.com>
2023-05-16 17:28:02 +02:00
Paolo Tranquilli
fc9fe13278 Merge pull request #13181 from github/redsun82/swift-diagnostics-enable-warnings
Swift: turn internal error into a TSP warning
2023-05-16 17:20:46 +02:00
Tom Hvitved
406acbe6a4 Update csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md
Co-authored-by: Michael B. Gale <mbg@github.com>
2023-05-16 17:13:21 +02:00
Stephan Brandauer
9845887452 automodel java fix: export method name as 'name' metadata parameter; export parameter name as 'parameterName' parameter 2023-05-16 15:07:14 +00:00
Tom Hvitved
c412bfde68 Add change note 2023-05-16 16:54:59 +02:00
Paolo Tranquilli
7e61e99e4a Swift: make help links optional argument more explicit 2023-05-16 16:52:22 +02:00
Michael B. Gale
ed79113c7f Merge pull request #13180 from github/mbg/java/fix-java-version-too-old
Java: Hide GHA variables in `java-version-too-old` test
2023-05-16 15:49:38 +01:00
Tom Hvitved
3027ed2ca8 C#: Include arguments to ILogger extension method calls in LogMessageSink 2023-05-16 16:04:58 +02:00
Geoffrey White
35b35ec377 Swift: Mirror changes made in the docs. 2023-05-16 14:26:16 +01:00
Michael B. Gale
9660b47879 Hide GHA variables in java-version-too-old test 2023-05-16 14:20:17 +01:00
Alexandre Boulgakov
9e9be4fc5e Merge pull request #13169 from github/sashabu/swift-tests
Swift: Use `...` to find and run all Bazel tests instead of having list them.
2023-05-16 14:20:03 +01:00
Paolo Tranquilli
8291b2229a Swift: turn internal error into a TSP warning 2023-05-16 15:18:29 +02:00
Geoffrey White
94b4ebe38b Update swift/ql/src/queries/Security/CWE-312/CleartextLogging.ql
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2023-05-16 14:16:30 +01:00
Rasmus Lerchedahl Petersen
5d68473d12 python: elide nodes without location from basic 2023-05-16 14:38:51 +02:00
Rasmus Lerchedahl Petersen
5b4f98d6c4 python: Add summaries for container constructors
Also:
- turn on flow summaries for taint
- do not restrict node type
  (as now we need summary nodes)
2023-05-16 14:38:51 +02:00
Jeroen Ketema
e8423f858f Merge pull request #13149 from MathiasVP/barrier-out-on-phi-back-edges
C++: Block flow through back-edges in `cpp/overrun-write`
2023-05-16 14:22:55 +02:00
Mathias Vorreiter Pedersen
03ef18b286 Swift: Recommend a proper source of randomness in 'swift/hardcoded-key'. 2023-05-16 11:59:41 +01:00
Kasper Svendsen
843640c486 Merge pull request #13173 from kaspersv/kaspersv/enable-implicit-this-warnings-shared-packs
Enable implicit this warnings for shared packs
2023-05-16 10:50:28 +02:00
Rasmus Lerchedahl Petersen
145eaf3947 python: remove steps for container constructors 2023-05-16 10:35:10 +02:00
Tony Torralba
770099f210 Merge branch 'main' into atorralba/java/promote-xxe-experimental-sinks 2023-05-16 09:49:34 +02:00
Kasper Svendsen
bfb098c3d6 Enable implicit this warnings for shared packs 2023-05-16 09:22:29 +02:00
Tony Torralba
ac1df4de91 Merge pull request #13166 from atorralba/atorralba/java/xpath-xxe-sink
Java: Add `XPath.evaluate` as XXE sink
2023-05-16 09:14:56 +02:00
Erik Krogh Kristensen
57858afbd9 Merge pull request #13165 from erik-krogh/proto-assign-qhelp
JS: fixup in the qhelp for `js/prototype-polluting-assignment`
2023-05-16 08:52:52 +02:00
Owen Mansel-Chan
1a9bd9ccde Merge pull request #13135 from owen-mc/go/fix-unit-test
Go: fix unit test
2023-05-16 07:50:50 +01:00
Alexandre Boulgakov
8db945a11e Swift: Use ... to find and run all Bazel tests instead of having to list them. 2023-05-15 20:51:31 +01:00
Philip Ginsbach
167a5723b4 Merge pull request #13156 from github/ginsbach/SpecifyParameterisedSyntax
add parameter syntax for module declarations and module references
2023-05-15 17:07:20 +01:00
Tony Torralba
7d79d87d48 Add XPath.evaluate as XXE sink 2023-05-15 17:39:35 +02:00
erik-krogh
2ebce99eae add another example of how to fix the prototype pollution issue 2023-05-15 17:24:02 +02:00
erik-krogh
7a338c408e fix typo, the variable in the example is called items 2023-05-15 17:23:40 +02:00
Geoffrey White
4781881a6a Swift: Improve mobile/phone number regexp. 2023-05-15 15:30:30 +01:00
Tom Hvitved
826b6219a0 Ruby: Include self parameters in type tracking flow-through logic 2023-05-15 16:02:33 +02:00
Tom Hvitved
3cdb27725a Ruby: Add more call graph tests 2023-05-15 16:02:33 +02:00
Tom Hvitved
9dede31c0d Merge pull request #13077 from hvitved/ruby/track-regexp-improvements
Ruby: Improvements to `RegExpTracking`
2023-05-15 16:02:00 +02:00
Geoffrey White
a0cba8cb6b Swift: Address boolean value FPs. 2023-05-15 14:24:18 +01:00
Geoffrey White
27c8eb301e Swift: Fix URL-related FPs. 2023-05-15 14:08:43 +01:00
Mathias Vorreiter Pedersen
650e9e1088 C++: Fix Code Scanning error. 2023-05-15 14:05:41 +01:00
Mathias Vorreiter Pedersen
f1c124a3da C++: Share more code between 'ValidState' and 'StringSizeConfig'. 2023-05-15 14:01:17 +01:00
Geoffrey White
e59d7e0345 Swift: Remove assumption that 'username' is not sensitive (in the tests). 2023-05-15 13:58:44 +01:00
Geoffrey White
dba951111a Swift: Add more sensitive data test cases. 2023-05-15 13:58:44 +01:00
Paolo Tranquilli
725a0a5eec Merge pull request #13161 from github/redsun82/swift-markdown-diagnostics
Swift: support markdown TSP diagnostics
2023-05-15 14:47:59 +02:00
Mathias Vorreiter Pedersen
f31709fb29 C++: Make comment more clear. 2023-05-15 13:36:29 +01:00
Paolo Tranquilli
10d084fbbf Swift: update comment 2023-05-15 13:48:24 +02:00
Paolo Tranquilli
cfcd26cf0d Swift: support markdown TSP diagnostics 2023-05-15 13:48:24 +02:00
Paolo Tranquilli
d8c0054ea9 Merge pull request #13133 from github/redsun82/swift-diagnostics-locations
Swift: add location and visibility support to TSP diagnostics
2023-05-15 13:47:52 +02:00
Geoffrey White
2a4d7cb642 Swift: Make the result message consistent as well. 2023-05-15 11:53:58 +01:00
Mathias Vorreiter Pedersen
a7712b608a C++: Add more comments. 2023-05-15 11:14:06 +01:00
Geoffrey White
3193b3b171 Swift: Make the CleartextLogging.ql query ID consistent with the other swift/cleartext-* queries. 2023-05-15 10:51:21 +01:00
Rasmus Wriedt Larsen
4be226ffe4 Merge pull request #13113 from yoff/python/test-container-steps
python: Add tests for container steps
2023-05-15 11:07:27 +02:00
Asger F
20e8ee8423 Merge pull request #12748 from JarLob/yi
JS: Add more sources, more unit tests, fixes to the GitHub Actions injection query
2023-05-15 11:03:00 +02:00
Tom Hvitved
cc6da7e38e Merge pull request #13031 from hvitved/identity-consistency-check
C#: Remove local identity flow steps
2023-05-15 10:45:35 +02:00
Paolo Tranquilli
dbff3e4fa4 Swift: remove unneeded SwiftDiagnosticLogWrapper 2023-05-15 10:08:43 +02:00
Paolo Tranquilli
a2cb331ebe Swift: remove hacky binlog interception 2023-05-15 10:02:24 +02:00
Paolo Tranquilli
9a555aea5f Merge branch 'main' into redsun82/swift-diagnostics-locations 2023-05-15 10:01:45 +02:00
Tom Hvitved
027cb2d335 C#: Reenable consistency check 2023-05-15 09:36:37 +02:00
Tom Hvitved
3c173df69e C#: Update expected test output 2023-05-15 09:35:20 +02:00
Tom Hvitved
165dc0b9bf C#: Filter away phi (read) input steps from a node into itself 2023-05-15 09:35:04 +02:00
Tom Hvitved
75dd4c8653 C#: Filter away use-use steps from a node into itself 2023-05-15 09:35:04 +02:00
Paolo Tranquilli
b214003720 Merge pull request #13131 from github/sashabu/tsp-incompatible-os
Swift: Emit a diagnostic when attempting to use the autobuilder on Linux.
2023-05-15 08:23:40 +02:00
Paolo Tranquilli
95cd948f09 Swift: order help links in integration test checks
They are currently a set within the codeql cli.
2023-05-14 22:33:48 +02:00
Ian Lynagh
202037e925 Merge pull request #13148 from igfoo/igfoo/arrays
Kotlin: Add some documentation on arrays, and tweak the tests we use for them
2023-05-12 18:52:16 +01:00
Max Schaefer
5dfe52afd0 Merge pull request #13152 from github/max-schaefer/unsafe-shell-command-construction-examples-sync
JavaScript: Use synchronous APIs in examples for js/shell-command-constructed-from-input.
2023-05-12 16:50:25 +01:00
Jeroen Ketema
ed0524d08c Merge pull request #13155 from jketema/invalid-pointer-deref-fp
C++: Add FP test case for `cpp/invalid-pointer-deref`
2023-05-12 17:33:28 +02:00
Mathias Vorreiter Pedersen
e1cc7dcdc1 C++: Tweak join orders. 2023-05-12 16:12:15 +01:00
Philip Ginsbach
c5be3fb6c0 add missing syntax for parameterised module declaration 2023-05-12 15:50:28 +01:00
Max Schaefer
ef659310d3 Merge pull request #13151 from github/max-schaefer-patch-1
JavaScript: Use gender-neutral language in qhelp for js/user-controlled-bypass
2023-05-12 15:37:32 +01:00
Jeroen Ketema
eb493a1981 C++: Add FP test case for cpp/invalid-pointer-deref
Also add reduced range analysis test case that seems to expose the underlying
reason for the FP.
2023-05-12 16:25:34 +02:00
Philip Ginsbach
41df8cafe5 'Expr' is more appropriate than 'Id' now that instantiation can be involved 2023-05-12 15:21:12 +01:00
Max Schaefer
2e7eb50319 JavaScript: Use synchronous APIs in examples for js/shell-command-constructed-from-input. 2023-05-12 14:42:11 +01:00
Kasper Svendsen
d27f84e34e Merge pull request #13143 from kaspersv/kaspersv/java-explicit-this-receivers2
Java: Make implicit this receivers explicit
2023-05-12 15:22:15 +02:00
Max Schaefer
a4f6ccf2fc JavaScript: Use gender-neutral language in qhelp for js/user-controlled-bypass 2023-05-12 14:21:40 +01:00
Mathias Vorreiter Pedersen
3f01a2157b Revert "C++: Speedup 'isSuccessor'."
This reverts commit 594da1a21a.
2023-05-12 13:41:34 +01:00
Rasmus Lerchedahl Petersen
81adf5aad4 python: remember to adjust annotation 2023-05-12 14:28:41 +02:00
Mathias Vorreiter Pedersen
de1f81a4b9 C++: Accept test changes. 2023-05-12 13:01:42 +01:00
Mathias Vorreiter Pedersen
f20a69074a C++: Remove flow through ssa phi back-edges. 2023-05-12 13:01:29 +01:00
Mathias Vorreiter Pedersen
0b7fc3cbf7 C++: Add a FP testcase involving flow through back-edges. 2023-05-12 13:00:39 +01:00
Ian Lynagh
826e87f435 Kotlin: Simplify some array tests 2023-05-12 12:54:08 +01:00
Rasmus Lerchedahl Petersen
1b848bb510 python: fix tests 2023-05-12 13:51:50 +02:00
Mathias Vorreiter Pedersen
2458fa0ab3 C++: Push conjunct into 'isSuccessor' and rename it to 'fwdIsSuccessor'. 2023-05-12 12:50:40 +01:00
Ian Lynagh
ad51767374 Kotlin: Add comment describing Kotlin array predicates 2023-05-12 12:38:05 +01:00
Harry Maclean
48f22681a5 Merge pull request #13029 from hmac/ruby-autobuilder-refactor
Shared: Share autobuilder code between Ruby and QL
2023-05-12 18:24:06 +07:00
yoff
3adaa21571 Merge branch 'main' into python/test-container-steps 2023-05-12 13:19:53 +02:00
Kasper Svendsen
c91d1cf721 Merge pull request #13145 from kaspersv/kaspersv/javascript-implicit-this-receiver3
JS: Make implicit this receivers explicit
2023-05-12 13:16:57 +02:00
yoff
72c6919f4e Merge pull request #13095 from yoff/python/interpret-summary-content
Python: Interpret summary content
2023-05-12 13:09:14 +02:00
yoff
6a5fc3c1b1 Update python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py 2023-05-12 13:06:08 +02:00
Mathias Vorreiter Pedersen
594da1a21a C++: Speedup 'isSuccessor'. 2023-05-12 12:05:09 +01:00
Mathias Vorreiter Pedersen
e58b99ddd1 C++: Don't carry the sources around as columns during the main loop of product flow. 2023-05-12 11:58:43 +01:00
yoff
62b60f490c Apply suggestions from code review
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2023-05-12 12:54:17 +02:00
Kasper Svendsen
d40cd0f275 Java: Make implicit this receivers explicit 2023-05-12 12:47:21 +02:00
Kasper Svendsen
8e18627eae Merge pull request #13144 from kaspersv/kaspersv/go-explicit-this-receivers2
Go: Make implicit this receivers explicit
2023-05-12 12:44:35 +02:00
Kasper Svendsen
7c5625a4dc Go: Make implicit this receivers explicit 2023-05-12 12:14:13 +02:00
Kasper Svendsen
fe2f36a1fe JS: Make implicit this receivers explicit 2023-05-12 12:12:48 +02:00
Kasper Svendsen
dd7a64d8e9 Merge pull request #13141 from kaspersv/kaspersv/ql-explicit-this-receivers
QL: Enable implicit this receiver warnings
2023-05-12 11:54:46 +02:00
Mathias Vorreiter Pedersen
75e36e89de C++: Precompute the set of necessary states. 2023-05-12 10:47:23 +01:00
Kasper Svendsen
1af1bf8917 QL: Enable implicit this receiver warnings 2023-05-12 11:35:35 +02:00
Kasper Svendsen
3dbc0cf0b6 QL: Make implicit receivers explicit 2023-05-12 11:35:35 +02:00
Kasper Svendsen
a6e8b00c26 Merge pull request #13138 from kaspersv/kaspersv/js-implicit-this-warnings
JS: Enable implicit this receiver warnings
2023-05-12 11:23:27 +02:00
Mathias Vorreiter Pedersen
f7924bda0d Merge pull request #13099 from MathiasVP/heuristic-allocation-for-overrun-write
C++: Use heuristic allocation functions in `cpp/overrun-write`
2023-05-12 10:15:28 +01:00
Tony Torralba
a48fa652ce Java: Add SQLi sinks for Spring JDBC 2023-05-12 10:57:49 +02:00
Paolo Tranquilli
d7cc506080 Merge branch 'main' into sashabu/tsp-incompatible-os 2023-05-12 09:58:36 +02:00
Kasper Svendsen
7dd9906e95 JS: Enable implicit this receiver warnings 2023-05-12 09:49:14 +02:00
Kasper Svendsen
189f8515c0 JS: Make implicit this receivers explicit 2023-05-12 09:49:14 +02:00
Tony Torralba
d0451609a7 Merge pull request #13137 from github/workflow/coverage/update
Update CSV framework coverage reports
2023-05-12 09:23:00 +02:00
Paolo Tranquilli
9ffada31a8 Swift: make internal error telemetry only for the moment 2023-05-12 09:19:44 +02:00
Paolo Tranquilli
cce9352272 Swift: add visibility customization to diagnostics 2023-05-12 09:05:45 +02:00
Paolo Tranquilli
dedbd9ab63 Swift: remove unneeded SwiftDiagnosticsDumper 2023-05-12 08:30:43 +02:00
Paolo Tranquilli
86777fa4c2 Swift: remove obsolete comment 2023-05-12 08:23:14 +02:00
Kasper Svendsen
2184fefe7f Merge pull request #13121 from kaspersv/kaspersv/javascript-explicit-this-receivers4
JS: Make implicit this receivers explicit
2023-05-12 08:21:52 +02:00
Paolo Tranquilli
03f4625b5f Swift: go back to explicit DIAGNOSE_ERROR macros 2023-05-12 06:30:58 +02:00
github-actions[bot]
996d864e73 Add changed framework coverage reports 2023-05-12 00:15:01 +00:00
Chris Smowton
ee64ea59e1 Merge pull request #12901 from porcupineyhairs/goDsn
Go: Add query to detect DSN Injection.
2023-05-11 22:45:43 +01:00
Chris Smowton
820673470e Merge pull request #13119 from porcupineyhairs/goTiming
Go : Add query to detect potential timing attacks
2023-05-11 22:38:13 +01:00
Chris Smowton
99f4eef9c5 Fix spelling 2023-05-11 22:12:35 +01:00
Chris Smowton
a10b11e09e Fix spelling and remove dead code 2023-05-11 22:12:17 +01:00
Chris Smowton
b6c2db6baf Fix duplicate query ID 2023-05-11 22:10:09 +01:00
Porcupiney Hairs
2c518c1fa6 Include changes from review 2023-05-12 01:59:42 +05:30
Porcupiney Hairs
ae6fda03b7 Include changes from review 2023-05-11 23:56:50 +05:30
Ian Lynagh
4885e584a0 Merge pull request #13042 from igfoo/igfoo/ODASA_JAVA_LAYOUT
Kotlin: Remove ODASA_JAVA_LAYOUT support
2023-05-11 18:35:08 +01:00
Owen Mansel-Chan
77c8357705 Do not obscure exit code with call to grep
The output is a bit more verbose, but this is hard to avoid
2023-05-11 18:15:41 +01:00
Owen Mansel-Chan
3981bb1f58 Indent comment in Makefile better 2023-05-11 17:12:27 +01:00
Stephan Brandauer
510febf46d Merge pull request #12830 from github/kaeluka/parameter-candidate-extraction
Java: Automodel Framework Mode Extraction Queries
2023-05-11 18:00:55 +02:00
Paolo Tranquilli
3f2a059b3b Swift: add location support to TSP diagnostics
This required a bit of an overhaul of the original integration of
JSON diagnostics into binlog.

The problem is that it is quite hard to add a kind of metadata to
binlog entries without changing its code. Another problem is that when
wanting to avoid double evaluation of logging macro arguments one
cannot really add a separate "diagnose" step easily.

The proposed solution consists in two things:
* hook into a binlog plumbing function by providing a better overload
  resolution match, which happens after logging macro expansion,
  bypassing the problem of double evaluation
* in that hook, produce the diagnostic directly, without waiting to
  reconstruct the diagnostics entry from the binlog serialized entry.

This allows to forgo the weird category to diagnostic mapping, and now a
diagnostics emission simply happens when a diagnostic source is given
as the first argument after the log format string. A flavour of
diganostics sources with locations is then added with the same
mechanism, allowing to write something like
```cpp
LOG_ERROR("[{}] ouch!", internalError.withLocation("foo.swift", 32));
```
2023-05-11 17:52:02 +02:00
Owen Mansel-Chan
760ba82c7a Fix unit tests 2023-05-11 16:40:59 +01:00
Anders Schack-Mulligen
82e780d175 Merge pull request #13128 from aschackmull/java/externalapi-jar
Java: Fix ExternalApi.jarContainer().
2023-05-11 16:31:05 +02:00
Owen Mansel-Chan
d570914fdd Merge pull request #13129 from owen-mc/go/identify-environment-output-to-stdout
Go: --identify-environment output to stdout
2023-05-11 15:20:50 +01:00
Stephan Brandauer
c31ad01579 squash ql-for-ql warnings 2023-05-11 16:18:52 +02:00
Rasmus Wriedt Larsen
62f0c64a03 Merge pull request #12552 from erik-krogh/py-type-trackers
Py: refactor regex tracking to type-trackers
2023-05-11 16:18:34 +02:00
Stephan Brandauer
61b0514b53 Merge pull request #13122 from github/java/update-mad-decls-after-triage-2023-05-11T08-52-07
Java: Update MaD Declarations after Triage
2023-05-11 16:04:36 +02:00
Alexandre Boulgakov
0915d2ad77 Swift: Emit a diagnostic when attempting to use the autobuilder on Linux. 2023-05-11 14:43:13 +01:00
Owen Mansel-Chan
1beb348d95 Fix outdated message 2023-05-11 14:29:14 +01:00
Owen Mansel-Chan
02a224c28f --identify-environment should write json to stdout 2023-05-11 14:29:14 +01:00
Tony Torralba
ca6ae26aad Change provenance to ai-manual 2023-05-11 14:56:16 +02:00
Tony Torralba
c17b0e809f Apply suggestions from code review 2023-05-11 14:53:56 +02:00
Anders Schack-Mulligen
587ee53917 Java: Fix ExternalApi.jarContainer(). 2023-05-11 14:09:27 +02:00
Ian Lynagh
712561ffa2 Kotlin: Fix recommended variable names in error messages 2023-05-11 13:02:35 +01:00
Stephan Brandauer
9b35a9f74a Update java/ql/lib/ext/org.apache.hadoop.fs.model.yml
Co-authored-by: Tony Torralba <atorralba@users.noreply.github.com>
2023-05-11 14:01:25 +02:00
Kasper Svendsen
489a73c2c3 JS: Make implicit this receivers explicit 2023-05-11 11:50:56 +02:00
Stephan Brandauer
e15610cfcd use ascii dash 2023-05-11 11:32:05 +02:00
Stephan Brandauer
b0ec089a3a Update MaD Declarations after Triage 2023-05-11 10:52:09 +02:00
Porcupiney Hairs
d536157c1a Go : Add query to detect potential timing attacks 2023-05-11 09:57:50 +05:30
Porcupiney Hairs
ec424d7e51 Go: Add query to detect DSN Injection. 2023-05-11 03:45:29 +05:30
Rasmus Lerchedahl Petersen
0a9515dbcd python: add tests for built-in collections
- constructors: list, tuple, set, dict
- methods:
  - general: copy, pop
  - list: append
  - set: add
  - dict: keys, values, items, get, popitem
- functions: sorted, reversed, iter, next
2023-05-10 18:10:05 +02:00
Rasmus Wriedt Larsen
54d35dbc0b Misc: Delete empty CONSISTENCY files
As requested by `@hvitved`
2023-05-10 17:37:39 +02:00
Rasmus Wriedt Larsen
cb8c4094fc Misc: Add --force option 2023-05-10 17:20:32 +02:00
Stephan Brandauer
f3d096cf37 update DollarAtString class to use hasLocationInfo instead of getURL 2023-05-10 15:02:22 +02:00
Tom Hvitved
425ebba278 Address review comments 2023-05-10 14:04:41 +02:00
Stephan Brandauer
79f2beca2a ql-for-ql 2023-05-10 14:04:29 +02:00
Stephan Brandauer
cd388264d3 use new DollarAtString class to return metadata using notation 2023-05-10 13:44:50 +02:00
Stephan Brandauer
6be11d93bd document FrameworkCandidatesImpl 2023-05-10 12:03:32 +02:00
Stephan Brandauer
d2d884b007 special case for Argument[this] 2023-05-10 11:53:40 +02:00
yoff
9bd3957bc8 Merge branch 'main' into python/interpret-summary-content 2023-05-10 11:41:50 +02:00
Stephan Brandauer
7ae6a992b6 fix code compilation error after main branch breaking change 2023-05-10 11:29:49 +02:00
Stephan Brandauer
9ed3c248ad Merge branch 'main' into kaeluka/parameter-candidate-extraction 2023-05-10 11:26:49 +02:00
Stephan Brandauer
1e5c9e8a58 simplify by using hasQualifiedName 2023-05-10 10:49:27 +02:00
Stephan Brandauer
f43edb8046 rename query files to make framework mode explicit 2023-05-10 10:30:58 +02:00
Stephan Brandauer
170e895593 use newtype for related location type 2023-05-10 10:28:14 +02:00
Stephan Brandauer
5dab1b2a3b leftover renaming label->kind 2023-05-10 10:01:39 +02:00
Stephan Brandauer
1f60fd6d58 use specialized getAParameter predicate, instead of getParameter(_) 2023-05-10 10:01:04 +02:00
Tom Hvitved
51087d090b Address review comments 2023-05-10 09:42:41 +02:00
Stephan Brandauer
91ae61b744 more documentation 2023-05-10 09:42:22 +02:00
Tom Hvitved
211a1e188c Sync files 2023-05-10 09:36:00 +02:00
Tom Hvitved
60b0f25a9a Ruby: Improvements to RegExpTracking 2023-05-10 09:35:59 +02:00
Stephan Brandauer
46741c6e42 rename kind -> label 2023-05-10 09:34:13 +02:00
Stephan Brandauer
85f519b7b4 documentation updates from review comments 2023-05-10 09:33:37 +02:00
Mathias Vorreiter Pedersen
363514e4ca C++: Expand heuristic to catch more sources. 2023-05-10 08:27:29 +01:00
Mathias Vorreiter Pedersen
9da7c9f696 C++: Use heuristic allocation in 'cpp/overrun-write'. 2023-05-10 08:22:56 +01:00
Mathias Vorreiter Pedersen
023b8e4f15 C++: Add a testcase that needs heuristic allocation. 2023-05-10 08:21:21 +01:00
Stephan Brandauer
94cb82e553 remove TestFileCharacteristic as it's redundant 2023-05-10 09:06:11 +02:00
Stephan Brandauer
d7aca9e909 use comma separator in concatenation 2023-05-10 08:57:27 +02:00
Rasmus Lerchedahl Petersen
064877140e Python: interpret remaining content 2023-05-09 21:40:01 +02:00
Rasmus Lerchedahl Petersen
c1110666b5 Python: remaining content-based summary components 2023-05-09 21:40:01 +02:00
Ian Lynagh
24d7391f5b Kotlin: Remove ODASA_JAVA_LAYOUT support
This is no longer supported, and has never been used with Kotlin.
2023-05-09 16:25:37 +01:00
Jaroslav Lobačevski
891a94c166 Apply suggestions from code review
Co-authored-by: Asger F <asgerf@github.com>
2023-05-09 16:27:32 +02:00
Jaroslav Lobačevski
5aa71352dc Update javascript/ql/src/Security/CWE-094/ExpressionInjection.qhelp
Co-authored-by: Asger F <asgerf@github.com>
2023-05-09 12:23:52 +02:00
Jaroslav Lobačevski
1ad23c5366 Apply suggestions from code review
Co-authored-by: Asger F <asgerf@github.com>
2023-05-09 12:23:06 +02:00
Harry Maclean
9203efbdc4 Shared: Share autobuilder code between Ruby and QL 2023-05-05 07:20:14 +00:00
Stephan Brandauer
62ab91c14a fix ql-for-ql warning 2023-05-04 17:48:50 +02:00
Stephan Brandauer
27703c777a pull subtypes-logic out into helper predicate, and document it 2023-05-04 17:45:17 +02:00
Stephan Brandauer
0e5591ff86 move getCallable to signature module implementation, and document it 2023-05-04 17:35:46 +02:00
Stephan Brandauer
a616a786f0 formatting 2023-05-04 17:27:27 +02:00
Stephan Brandauer
36aabc077e Update java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll
Co-authored-by: Aditya Sharad <6874315+adityasharad@users.noreply.github.com>
2023-05-04 16:50:37 +02:00
Rasmus Wriedt Larsen
c9680b9202 Misc: Look for .expected changes from integration-tests... 2023-05-03 17:40:21 +02:00
Rasmus Wriedt Larsen
b048f9d8c4 Misc: Allow specifying SHA directly to script 2023-05-03 17:39:20 +02:00
Rasmus Wriedt Larsen
e3fc6d67cc Misc: Allow no internal CI 2023-05-03 17:31:52 +02:00
Stephan Brandauer
32f2614fe0 add typecheckable mechanism to enforce minimal set of metadata 2023-05-03 16:00:50 +02:00
Stephan Brandauer
6d29273c43 make framework mode explicit in file/module names 2023-05-03 14:36:42 +02:00
Stephan Brandauer
dfb9d88198 fix ql-for-ql errors 2023-05-03 14:17:11 +02:00
Stephan Brandauer
05bf13b020 use getCallable predicate 2023-05-03 11:27:14 +02:00
Stephan Brandauer
09f3296134 export related locations using notation 2023-05-03 10:27:46 +02:00
Stephan Brandauer
f1644adca9 add internal tag to extraction queries; use 'ml' in query ids, instead of 'ml-powered' 2023-05-02 13:30:22 +02:00
Stephan Brandauer
bb7e473cbf use the name callable, instead of callee for methods, functions 2023-05-02 13:22:31 +02:00
Stephan Brandauer
f7f6f104d0 use NegativeEndpointType class; replace link to slack discussion 2023-05-02 13:15:30 +02:00
erik-krogh
18f8c69261 satisfy the signature of HostnameRegexpSig, which doesn't understand RegExpSink 2023-05-01 10:49:51 +02:00
erik-krogh
d5029c94b6 changes based on review 2023-05-01 10:42:15 +02:00
erik-krogh
a7f733ab8c move RegExpInterpretation into Concepts.qll 2023-05-01 10:42:15 +02:00
erik-krogh
2fad406b5c move StdLibRegExpInterpretation to Stdlib.qll 2023-05-01 10:42:15 +02:00
erik-krogh
a64848c022 simplify StdLibRegExpInterpretation to only consider re.compile, because the rest is handled by RegexExecution 2023-05-01 10:42:14 +02:00
erik-krogh
113ce61d40 fix nit in qldoc 2023-05-01 10:42:14 +02:00
erik-krogh
2d2602b668 use that strings are local-source-nodes in regex-tracking 2023-05-01 10:42:14 +02:00
erik-krogh
3cde11efc8 use StrConst instead of Bytes and Unicode 2023-05-01 10:42:14 +02:00
erik-krogh
ffa3425195 rename away from deprecated alias in test-files 2023-05-01 10:42:14 +02:00
erik-krogh
f2adc4f958 add missing qldoc 2023-05-01 10:42:14 +02:00
erik-krogh
59cc90e547 move Regex into a ParseRegExp file, and rename the class to RegExp 2023-05-01 10:42:14 +02:00
erik-krogh
556bb41999 move all code to find Regex flag into a module 2023-05-01 10:42:14 +02:00
erik-krogh
f0254fc089 introduce RegExpInterpretation instead of RegexString, and move RegexTreeView.qll into a regexp folder 2023-05-01 10:42:13 +02:00
erik-krogh
e677b62241 use type-tracking instead of global dataflow for tracking regular expressions 2023-05-01 10:41:53 +02:00
Rasmus Wriedt Larsen
f2def84337 Misc: Add script to accept .expected changes from CI
This script can be used to go over `codeql test run` expected/actual log
output from actions CI checks for a PR, and apply patches locally to
make the tests pass.

Designed for use by GitHub employees, since it needs access to internal
CI runs. Just run this tool while the branch for the PR is checked out!

You need the `gh` cli tool installed and authenticated.

Example can be seen in https://github.com/github/codeql/pull/12950
2023-04-30 14:59:50 +02:00
Stephan Brandauer
bd3aaf0306 remove comment that no longer applies 2023-04-28 10:16:18 +02:00
Stephan Brandauer
adcf4a3dc2 documentation clean-up 2023-04-27 14:48:48 +02:00
Stephan Brandauer
52a8230ce3 restructure shared characteristics module; add framework support for sanitizers 2023-04-27 14:46:24 +02:00
Stephan Brandauer
ffe7c62766 use US spelling 2023-04-27 14:46:24 +02:00
Stephan Brandauer
a91b71c53b add parameter names to metadata, set subtypes = false for static method candidates; remove UndocumentedMethodCharacteristics, now that we use ModelApi 2023-04-27 14:46:23 +02:00
Stephan Brandauer
3868defb87 use ModelApi to define parameters worth modeling 2023-04-27 14:46:23 +02:00
Stephan Brandauer
6eefb268dd Automodel extraction queries in java telemetry query directory 2023-04-27 14:46:08 +02:00
Tony Torralba
4606df5cb6 Add change note 2023-04-26 12:24:43 +02:00
Tony Torralba
fba61d51ed Remove experimental files 2023-04-26 12:24:30 +02:00
Tony Torralba
e54eaed26f Refactor tests to use InlineFlowTest 2023-04-26 12:19:59 +02:00
Tony Torralba
db73e16b70 Add tests 2023-04-26 12:12:10 +02:00
Tony Torralba
1e66a544fd Promote exxperimental XXE sinks 2023-04-26 12:11:48 +02:00
Tony Torralba
8b65937159 Move ConstantStringExpr to RangeUtils.qll 2023-04-26 12:11:08 +02:00
jarlob
6e9f54ef55 Use double curly braces 2023-04-21 19:03:38 +02:00
jarlob
e9dee3a185 Move actions/github-script out of Actions.qll 2023-04-14 14:26:23 +02:00
jarlob
599ec5a3b4 Add comment 2023-04-14 10:52:11 +02:00
jarlob
3724ea1a7b Extract where parts into predicates 2023-04-14 10:49:56 +02:00
jarlob
ac1c20673d Encapsulate github-script 2023-04-14 10:23:49 +02:00
jarlob
d80c541da6 Encapsulate composite actions 2023-04-14 10:06:35 +02:00
jarlob
94065764d5 Make predicate name clearer 2023-04-14 01:05:21 +02:00
jarlob
79218a3946 Use YamlMapping for modeling Env 2023-04-14 00:56:51 +02:00
jarlob
dd52ef85cd Rename Env 2023-04-13 23:41:31 +02:00
jarlob
76834cbe53 Rename GlobalEnv 2023-04-13 23:13:56 +02:00
jarlob
a8a6913512 Simplify exists according to the warning 2023-04-13 23:10:16 +02:00
jarlob
8234ea33f0 More details in the changes file. 2023-04-13 23:05:32 +02:00
jarlob
6790318769 Added the composite word 2023-04-13 22:58:32 +02:00
Jaroslav Lobačevski
8f1bccbb4d Apply suggestions from code review (comments)
Co-authored-by: Aditya Sharad <6874315+adityasharad@users.noreply.github.com>
2023-04-13 22:55:53 +02:00
jarlob
72b66ffe97 Fix comment. 2023-04-07 10:01:14 +02:00
jarlob
7573c615f6 Fix warnings 2023-04-06 23:07:22 +02:00
jarlob
3745cccedd Fix warnings 2023-04-06 23:02:08 +02:00
jarlob
af83d8af41 Add comment 2023-04-06 22:59:09 +02:00
jarlob
9c7eecf547 Add support for composite actions 2023-04-06 22:53:59 +02:00
jarlob
baefeab2d1 fix tests 2023-04-06 19:11:04 +02:00
jarlob
0a878d4db9 Support yAml extensions 2023-04-06 19:07:38 +02:00
jarlob
40635e60d1 Improve documentation 2023-04-05 10:26:02 +02:00
jarlob
9fba7d31f1 Improve documentation 2023-04-05 10:24:07 +02:00
jarlob
40b7910473 Fix QLDoc warnings 2023-04-05 10:14:54 +02:00
jarlob
eef1973b93 Change UI message 2023-04-05 10:05:24 +02:00
jarlob
5c5b9f99a8 Add simple taint tracking for env variables 2023-04-05 10:03:46 +02:00
jarlob
39ff3c72a2 Remove label sanitizer because it is prone to race conditions 2023-04-03 23:28:31 +02:00
jarlob
8ea418216c Look for script injections in actions/github-script 2023-04-03 23:13:28 +02:00
jarlob
e941218e30 change notes added 2023-04-03 15:15:00 +02:00
jarlob
ba5747dff3 fix formatting 2023-04-03 15:10:27 +02:00
jarlob
c6eaf194a5 Remove empty.js as it is not needed anymore 2023-04-03 15:09:40 +02:00
jarlob
99d634c8a4 Add more sources, more unit tests, fixes to the GitHub Actions injection query 2023-04-03 15:02:02 +02:00
529 changed files with 21988 additions and 8408 deletions

View File

@@ -27,9 +27,9 @@ jobs:
run: |
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq 'any(.[].filename ; test("/change-notes/.*[.]md$"))' |
grep true -c
- name: Fail if the change note filename doesn't match the expected format. The file name must be of the form 'YYYY-MM-DD.md' or 'YYYY-MM-DD-{title}.md', where '{title}' is arbitrary text.
- name: Fail if the change note filename doesn't match the expected format. The file name must be of the form 'YYYY-MM-DD.md', 'YYYY-MM-DD-{title}.md', where '{title}' is arbitrary text, or released/x.y.z.md for released change-notes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq '[.[].filename | select(test("/change-notes/.*[.]md$"))] | all(test("/change-notes/[0-9]{4}-[0-9]{2}-[0-9]{2}.*[.]md$"))' |
grep true -c
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq '[.[].filename | select(test("/change-notes/.*[.]md$"))] | all(test("/change-notes/[0-9]{4}-[0-9]{2}-[0-9]{2}.*[.]md$") or test("/change-notes/released/[0-9]*[.][0-9]*[.][0-9]*[.]md$"))' |
grep true -c

View File

@@ -16,6 +16,7 @@ on:
branches:
- main
- rc/*
- codeql-cli-*
push:
paths:
- "swift/**"
@@ -30,6 +31,7 @@ on:
branches:
- main
- rc/*
- codeql-cli-*
jobs:
# not using a matrix as you cannot depend on a specific job in a matrix, and we want to start linux checks

18
.vscode/tasks.json vendored
View File

@@ -22,6 +22,22 @@
"command": "${config:python.pythonPath}",
},
"problemMatcher": []
},
{
"label": "Accept .expected changes from CI",
"type": "process",
// Non-Windows OS will usually have Python 3 already installed at /usr/bin/python3.
"command": "python3",
"args": [
"misc/scripts/accept-expected-changes-from-ci.py"
],
"group": "build",
"windows": {
// On Windows, use whatever Python interpreter is configured for this workspace. The default is
// just `python`, so if Python is already on the path, this will find it.
"command": "${config:python.pythonPath}",
},
"problemMatcher": []
}
]
}
}

View File

@@ -40,3 +40,6 @@ WORKSPACE.bazel @github/codeql-ci-reviewers
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers
/.github/workflows/ruby-* @github/codeql-ruby
/.github/workflows/swift.yml @github/codeql-swift
# Misc
/misc/scripts/accept-expected-changes-from-ci.py @RasmusWL

View File

@@ -47,7 +47,6 @@
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplForRegExp.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll",

View File

@@ -11,6 +11,7 @@
### Minor Analysis Improvements
* The `StdNamespace` class now also includes all inline namespaces that are children of `std` namespace.
* The new dataflow (`semmle.code.cpp.dataflow.new.DataFlow`) and taint-tracking libraries (`semmle.code.cpp.dataflow.new.TaintTracking`) now support tracking flow through static local variables.
## 0.7.1

View File

@@ -11,4 +11,5 @@
### Minor Analysis Improvements
* The `StdNamespace` class now also includes all inline namespaces that are children of `std` namespace.
* The new dataflow (`semmle.code.cpp.dataflow.new.DataFlow`) and taint-tracking libraries (`semmle.code.cpp.dataflow.new.TaintTracking`) now support tracking flow through static local variables.

View File

@@ -290,9 +290,9 @@ module ProductFlow {
predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn1(node) }
}
module Flow1 = DataFlow::GlobalWithState<Config1>;
private module Flow1 = DataFlow::GlobalWithState<Config1>;
module Config2 implements DataFlow::StateConfigSig {
private module Config2 implements DataFlow::StateConfigSig {
class FlowState = FlowState2;
predicate isSource(DataFlow::Node source, FlowState state) {
@@ -322,27 +322,90 @@ module ProductFlow {
predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn2(node) }
}
module Flow2 = DataFlow::GlobalWithState<Config2>;
private module Flow2 = DataFlow::GlobalWithState<Config2>;
private predicate isSourcePair(Flow1::PathNode node1, Flow2::PathNode node2) {
Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
}
private predicate isSinkPair(Flow1::PathNode node1, Flow2::PathNode node2) {
Config::isSinkPair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate fwdReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
isSourcePair(node1, node2)
or
fwdIsSuccessor(_, _, node1, node2)
}
pragma[nomagic]
private predicate reachableInterprocEntry(
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode node1, Flow2::PathNode node2
private predicate fwdIsSuccessorExit(
Flow1::PathNode mid1, Flow2::PathNode mid2, Flow1::PathNode succ1, Flow2::PathNode succ2
) {
Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState()) and
node1 = source1 and
node2 = source2
isSinkPair(mid1, mid2) and
succ1 = mid1 and
succ2 = mid2
or
exists(
Flow1::PathNode midEntry1, Flow2::PathNode midEntry2, Flow1::PathNode midExit1,
Flow2::PathNode midExit2
|
reachableInterprocEntry(source1, source2, midEntry1, midEntry2) and
interprocEdgePair(midExit1, midExit2, node1, node2) and
localPathStep1*(midEntry1, midExit1) and
localPathStep2*(midEntry2, midExit2)
interprocEdgePair(mid1, mid2, succ1, succ2)
}
private predicate fwdIsSuccessor1(
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2,
Flow1::PathNode succ1, Flow2::PathNode succ2
) {
fwdReachableInterprocEntry(pred1, pred2) and
localPathStep1*(pred1, mid1) and
fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
}
private predicate fwdIsSuccessor2(
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2,
Flow1::PathNode succ1, Flow2::PathNode succ2
) {
fwdReachableInterprocEntry(pred1, pred2) and
localPathStep2*(pred2, mid2) and
fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
}
pragma[assume_small_delta]
private predicate fwdIsSuccessor(
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
) {
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
fwdIsSuccessor1(pred1, pred2, mid1, mid2, succ1, succ2) and
fwdIsSuccessor2(pred1, pred2, mid1, mid2, succ1, succ2)
)
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate revReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
fwdReachableInterprocEntry(node1, node2) and
isSinkPair(node1, node2)
or
exists(Flow1::PathNode succ1, Flow2::PathNode succ2 |
revReachableInterprocEntry(succ1, succ2) and
fwdIsSuccessor(node1, node2, succ1, succ2)
)
}
private newtype TNodePair =
TMkNodePair(Flow1::PathNode node1, Flow2::PathNode node2) {
revReachableInterprocEntry(node1, node2)
}
private predicate pathSucc(TNodePair n1, TNodePair n2) {
exists(Flow1::PathNode n11, Flow2::PathNode n12, Flow1::PathNode n21, Flow2::PathNode n22 |
n1 = TMkNodePair(n11, n12) and
n2 = TMkNodePair(n21, n22) and
fwdIsSuccessor(n11, n12, n21, n22)
)
}
private predicate pathSuccPlus(TNodePair n1, TNodePair n2) = fastTC(pathSucc/2)(n1, n2)
private predicate localPathStep1(Flow1::PathNode pred, Flow1::PathNode succ) {
Flow1::PathGraph::edges(pred, succ) and
pragma[only_bind_out](pred.getNode().getEnclosingCallable()) =
@@ -474,11 +537,14 @@ module ProductFlow {
private predicate reachable(
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode sink1, Flow2::PathNode sink2
) {
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
reachableInterprocEntry(source1, source2, mid1, mid2) and
Config::isSinkPair(sink1.getNode(), sink1.getState(), sink2.getNode(), sink2.getState()) and
localPathStep1*(mid1, sink1) and
localPathStep2*(mid2, sink2)
isSourcePair(source1, source2) and
isSinkPair(sink1, sink2) and
exists(TNodePair n1, TNodePair n2 |
n1 = TMkNodePair(source1, source2) and
n2 = TMkNodePair(sink1, sink2)
|
pathSuccPlus(n1, n2) or
n1 = n2
)
}
}

View File

@@ -230,8 +230,12 @@ class GlobalNamespace extends Namespace {
}
/**
* The C++ `std::` namespace.
* The C++ `std::` namespace and its inline namespaces.
*/
class StdNamespace extends Namespace {
StdNamespace() { this.hasName("std") and this.getParentNamespace() instanceof GlobalNamespace }
StdNamespace() {
this.hasName("std") and this.getParentNamespace() instanceof GlobalNamespace
or
this.isInline() and this.getParentNamespace() instanceof StdNamespace
}
}

View File

@@ -1699,7 +1699,28 @@ class AutoType extends TemplateParameter {
private predicate suppressUnusedThis(Type t) { any() }
/** A source code location referring to a type */
/**
* A source code location referring to a user-defined type.
*
* Note that only _user-defined_ types have `TypeMention`s. In particular,
* built-in types, and derived types with built-in types as their base don't
* have any `TypeMention`s. For example, given
* ```cpp
* struct S { ... };
* void f(S s1, int i1) {
* S s2;
* S* s3;
* S& s4 = s2;
* decltype(s2) s5;
*
* int i2;
* int* i3;
* int i4[10];
* }
* ```
* there will be a `TypeMention` for the mention of `S` at `S s1`, `S s2`, and `S& s4 = s2`,
* but not at `decltype(s2) s5`. Additionally, there will be no `TypeMention`s for `int`.
*/
class TypeMention extends Locatable, @type_mention {
override string toString() { result = "type mention" }

View File

@@ -657,24 +657,16 @@ private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
* So this predicate recurses back along conversions and `PointerArithmeticInstruction`s to find the
* first use that has provides use-use flow, and uses that target as the target of the `nodeFrom`.
*/
private predicate adjustForPointerArith(
DefOrUse defOrUse, Node nodeFrom, UseOrPhi use, boolean uncertain
) {
nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and
exists(Node adjusted |
indirectConversionFlowStep*(adjusted, nodeFrom) and
nodeToDefOrUse(adjusted, defOrUse, uncertain) and
private predicate adjustForPointerArith(PostUpdateNode pun, UseOrPhi use) {
exists(DefOrUse defOrUse, Node adjusted |
indirectConversionFlowStep*(adjusted, pun.getPreUpdateNode()) and
nodeToDefOrUse(adjusted, defOrUse, _) and
adjacentDefRead(defOrUse, use)
)
}
private predicate ssaFlowImpl(SsaDefOrUse defOrUse, Node nodeFrom, Node nodeTo, boolean uncertain) {
// `nodeFrom = any(PostUpdateNode pun).getPreUpdateNode()` is implied by adjustedForPointerArith.
exists(UseOrPhi use |
adjustForPointerArith(defOrUse, nodeFrom, use, uncertain) and
useToNode(use, nodeTo)
or
not nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and
nodeToDefOrUse(nodeFrom, defOrUse, uncertain) and
adjacentDefRead(defOrUse, use) and
useToNode(use, nodeTo) and
@@ -719,14 +711,19 @@ predicate ssaFlow(Node nodeFrom, Node nodeTo) {
)
}
private predicate isArgumentOfCallable(DataFlowCall call, ArgumentNode arg) {
arg.argumentOf(call, _)
}
/** Holds if there is def-use or use-use flow from `pun` to `nodeTo`. */
predicate postUpdateFlow(PostUpdateNode pun, Node nodeTo) {
exists(Node preUpdate, Node nFrom, boolean uncertain, SsaDefOrUse defOrUse |
exists(UseOrPhi use, Node preUpdate |
adjustForPointerArith(pun, use) and
useToNode(use, nodeTo) and
preUpdate = pun.getPreUpdateNode() and
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain)
|
if uncertain = true
then preUpdate = [nFrom, getAPriorDefinition(defOrUse)]
else preUpdate = nFrom
not exists(DataFlowCall call |
isArgumentOfCallable(call, preUpdate) and isArgumentOfCallable(call, nodeTo)
)
)
}

View File

@@ -414,7 +414,7 @@ private module HeuristicAllocation {
int sizeArg;
HeuristicAllocationFunctionByName() {
Function.super.getName().matches("%alloc%") and
Function.super.getName().matches(["%alloc%", "%Alloc%"]) and
Function.super.getUnspecifiedType() instanceof PointerType and
sizeArg = unique( | | getAnUnsignedParameter(this))
}

View File

@@ -47,7 +47,7 @@ VariableAccess getAVariableAccess(Expr e) { e.getAChild*() = result }
* Holds if `(n, state)` pair represents the source of flow for the size
* expression associated with `alloc`.
*/
predicate hasSize(AllocationExpr alloc, DataFlow::Node n, int state) {
predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
exists(VariableAccess va, Expr size, int delta |
size = alloc.getSizeExpr() and
// Get the unique variable in a size expression like `x` in `malloc(x + 1)`.
@@ -78,6 +78,145 @@ predicate isSinkPairImpl(
)
}
module ValidState {
/**
* In the `StringSizeConfig` configuration we use an integer as the flow state for the second
* projection of the dataflow graph. The integer represents an offset that is added to the
* size of the allocation. For example, given:
* ```cpp
* char* p = new char[size + 1];
* size += 1;
* memset(p, 0, size);
* ```
* the initial flow state is `1`. This represents the fact that `size + 1` is a valid bound
* for the size of the allocation pointed to by `p`. After updating the size using `+=`, the
* flow state changes to `0`, which represents the fact that `size + 0` is a valid bound for
* the allocation.
*
* So we need to compute a set of valid integers that represent the offset applied to the
* size. We do this in two steps:
* 1. We first perform the dataflow traversal that the second projection of the product-flow
* library will perform, and visit all the places where the size argument is modified.
* 2. Once that dataflow traversal is done, we accumulate the offsets added at each places
* where the offset is modified (see `validStateImpl`).
*
* Because we want to guarantee that each place where we modify the offset has a `PathNode`
* we "flip" a boolean flow state in each `isAdditionalFlowStep`. This ensures that the node
* has a corresponding `PathNode`.
*/
private module ValidStateConfig implements DataFlow::StateConfigSig {
class FlowState = boolean;
predicate isSource(DataFlow::Node source, FlowState state) {
hasSize(_, source, _) and
state = false
}
predicate isSink(DataFlow::Node sink, FlowState state) {
isSinkPairImpl(_, _, sink, _, _) and
state = [false, true]
}
predicate isBarrier(DataFlow::Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
) {
isAdditionalFlowStep2(node1, node2, _) and
state1 = [false, true] and
state2 = state1.booleanNot()
}
predicate includeHiddenNodes() { any() }
}
private import DataFlow::GlobalWithState<ValidStateConfig>
private predicate inLoop(PathNode n) { n.getASuccessor+() = n }
/**
* Holds if `value` is a possible offset for `n`.
*
* To ensure termination, we limit `value` to be in the
* range `[-2, 2]` if the node is part of a loop. Without
* this restriction we wouldn't terminate on an example like:
* ```cpp
* while(unknown()) { size++; }
* ```
*/
private predicate validStateImpl(PathNode n, int value) {
// If the dataflow node depends recursively on itself we restrict the range.
(inLoop(n) implies value = [-2 .. 2]) and
(
// For the dataflow source we have an allocation such as `malloc(size + k)`,
// and the value of the flow-state is then `k`.
hasSize(_, n.getNode(), value)
or
// For a dataflow sink any `value` that is strictly smaller than the delta
// needs to be a valid flow-state. That is, for a snippet like:
// ```
// p = b ? new char[size] : new char[size + 1];
// memset(p, 0, size + 2);
// ```
// the valid flow-states at the `memset` must include the set `{0, 1}` since the
// flow-state at `new char[size]` is `0`, and the flow-state at `new char[size + 1]`
// is `1`.
//
// So we find a valid flow-state at the sink's predecessor, and use the definition
// of our sink predicate to compute the valid flow-states at the sink.
exists(int delta, PathNode n0 |
n0.getASuccessor() = n and
validStateImpl(n0, value) and
isSinkPairImpl(_, _, n.getNode(), delta, _) and
delta > value
)
or
// For a non-source and non-sink node there is two cases to consider.
// 1. A node where we have to update the flow-state, or
// 2. A node that doesn't update the flow-state.
//
// For case 1, we compute the new flow-state by adding the constant operand of the
// `AddInstruction` to the flow-state of any predecessor node.
// For case 2 we simply propagate the valid flow-states from the predecessor node to
// the next one.
exists(PathNode n0, DataFlow::Node node0, DataFlow::Node node, int value0 |
n0.getASuccessor() = n and
validStateImpl(n0, value0) and
node = n.getNode() and
node0 = n0.getNode()
|
exists(int delta |
isAdditionalFlowStep2(node0, node, delta) and
value0 = value + delta
)
or
not isAdditionalFlowStep2(node0, node, _) and
value = value0
)
)
}
predicate validState(DataFlow::Node n, int value) {
validStateImpl(any(PathNode pn | pn.getNode() = n), value)
}
}
import ValidState
/**
* Holds if `node2` is a dataflow node that represents an addition of two operands `op1`
* and `op2` such that:
* 1. `node1` is the dataflow node that represents `op1`, and
* 2. the value of `op2` can be upper bounded by `delta.`
*/
predicate isAdditionalFlowStep2(DataFlow::Node node1, DataFlow::Node node2, int delta) {
exists(AddInstruction add, Operand op |
add.hasOperands(node1.asOperand(), op) and
semBounded(getSemanticExpr(op.getDef()), any(SemZeroBound zero), delta, true, _) and
node2.asInstruction() = add
)
}
module StringSizeConfig implements ProductFlow::StateConfigSig {
class FlowState1 = Unit;
@@ -100,7 +239,7 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
DataFlow::Node bufSink, FlowState1 state1, DataFlow::Node sizeSink, FlowState2 state2
) {
exists(state1) and
state2 = [-32 .. 32] and // An arbitrary bound because we need to bound `state2`
validState(sizeSink, state2) and
exists(int delta |
isSinkPairImpl(_, bufSink, sizeSink, delta, _) and
delta > state2
@@ -111,6 +250,10 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
predicate isBarrier2(DataFlow::Node node, FlowState2 state) { none() }
predicate isBarrierOut2(DataFlow::Node node) {
node = any(DataFlow::SsaPhiNode phi).getAnInput(true)
}
predicate isAdditionalFlowStep1(
DataFlow::Node node1, FlowState1 state1, DataFlow::Node node2, FlowState1 state2
) {
@@ -120,14 +263,10 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
predicate isAdditionalFlowStep2(
DataFlow::Node node1, FlowState2 state1, DataFlow::Node node2, FlowState2 state2
) {
exists(AddInstruction add, Operand op, int delta, int s1, int s2 |
s1 = [-32 .. 32] and // An arbitrary bound because we need to bound `state`
state1 = s1 and
state2 = s2 and
add.hasOperands(node1.asOperand(), op) and
semBounded(getSemanticExpr(op.getDef()), any(SemZeroBound zero), delta, true, _) and
node2.asInstruction() = add and
s1 = s2 + delta
validState(node2, state2) and
exists(int delta |
isAdditionalFlowStep2(node1, node2, delta) and
state1 = state2 + delta
)
}
}

View File

@@ -48,44 +48,23 @@ bindingset[b]
pragma[inline_late]
predicate bounded2(Instruction i, Instruction b, int delta) { boundedImpl(i, b, delta) }
/**
* Holds if the combination of `n` and `state` represents an appropriate
* source for the expression `e` suitable for use-use flow.
*/
private predicate hasSizeImpl(Expr e, DataFlow::Node n, int state) {
// The simple case: If the size is a variable access with no qualifier we can just use the
// dataflow node for that expression and no state.
exists(VariableAccess va |
va = e and
not va instanceof FieldAccess and
n.asConvertedExpr() = va.getFullyConverted() and
state = 0
)
or
// If the size is a choice between two expressions we allow both to be nodes representing the size.
exists(ConditionalExpr cond | cond = e | hasSizeImpl([cond.getThen(), cond.getElse()], n, state))
or
// If the size is an expression plus a constant, we pick the dataflow node of the expression and
// remember the constant in the state.
exists(Expr const, Expr nonconst |
e.(AddExpr).hasOperands(const, nonconst) and
state = const.getValue().toInt() and
hasSizeImpl(nonconst, n, _)
)
or
exists(Expr const, Expr nonconst |
e.(SubExpr).hasOperands(const, nonconst) and
state = -const.getValue().toInt() and
hasSizeImpl(nonconst, n, _)
)
}
VariableAccess getAVariableAccess(Expr e) { e.getAChild*() = result }
/**
* Holds if `(n, state)` pair represents the source of flow for the size
* expression associated with `alloc`.
*/
predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
hasSizeImpl(alloc.getSizeExpr(), n, state)
exists(VariableAccess va, Expr size, int delta |
size = alloc.getSizeExpr() and
// Get the unique variable in a size expression like `x` in `malloc(x + 1)`.
va = unique( | | getAVariableAccess(size)) and
// Compute `delta` as the constant difference between `x` and `x + 1`.
bounded1(any(Instruction instr | instr.getUnconvertedResultExpression() = size),
any(LoadInstruction load | load.getUnconvertedResultExpression() = va), delta) and
n.asConvertedExpr() = va.getFullyConverted() and
state = delta
)
}
/**
@@ -345,6 +324,16 @@ query predicate edges(MergedPathNode node1, MergedPathNode node2) {
joinOn2(node1.asPathNode3(), node2.asSinkNode(), _)
}
query predicate subpaths(
MergedPathNode arg, MergedPathNode par, MergedPathNode ret, MergedPathNode out
) {
AllocToInvalidPointerFlow::PathGraph1::subpaths(arg.asPathNode1(), par.asPathNode1(),
ret.asPathNode1(), out.asPathNode1())
or
InvalidPointerToDerefFlow::PathGraph::subpaths(arg.asPathNode3(), par.asPathNode3(),
ret.asPathNode3(), out.asPathNode3())
}
/**
* Holds if `p1` is a sink of `AllocToInvalidPointerConf` and `p2` is a source
* of `InvalidPointerToDerefConf`, and they are connected through `pai`.

View File

@@ -1,202 +1,62 @@
edges
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:24:21:24:31 | call to mk_string_t indirection [string] |
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:34:21:34:31 | call to mk_string_t indirection [string] |
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:39:21:39:31 | call to mk_string_t indirection [string] |
| test.cpp:18:5:18:30 | ... = ... | test.cpp:18:10:18:15 | str indirection [post update] [string] |
| test.cpp:18:10:18:15 | str indirection [post update] [string] | test.cpp:16:11:16:21 | mk_string_t indirection [string] |
| test.cpp:18:19:18:24 | call to malloc | test.cpp:18:5:18:30 | ... = ... |
| test.cpp:24:21:24:31 | call to mk_string_t indirection [string] | test.cpp:26:13:26:15 | str indirection [string] |
| test.cpp:26:13:26:15 | str indirection [string] | test.cpp:26:18:26:23 | string |
| test.cpp:26:13:26:15 | str indirection [string] | test.cpp:26:18:26:23 | string indirection |
| test.cpp:26:18:26:23 | string indirection | test.cpp:26:18:26:23 | string |
| test.cpp:29:32:29:34 | str indirection [string] | test.cpp:30:13:30:15 | str indirection [string] |
| test.cpp:30:13:30:15 | str indirection [string] | test.cpp:30:18:30:23 | string |
| test.cpp:30:13:30:15 | str indirection [string] | test.cpp:30:18:30:23 | string indirection |
| test.cpp:30:18:30:23 | string indirection | test.cpp:30:18:30:23 | string |
| test.cpp:34:21:34:31 | call to mk_string_t indirection [string] | test.cpp:35:21:35:23 | str indirection [string] |
| test.cpp:35:21:35:23 | str indirection [string] | test.cpp:29:32:29:34 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:41:13:41:15 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:42:13:42:15 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:44:13:44:15 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:45:13:45:15 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:48:17:48:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:52:17:52:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:56:17:56:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:60:17:60:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:64:17:64:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:68:17:68:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:72:17:72:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:76:17:76:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:80:17:80:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:84:17:84:19 | str indirection [string] |
| test.cpp:41:13:41:15 | str indirection [string] | test.cpp:41:18:41:23 | string |
| test.cpp:41:13:41:15 | str indirection [string] | test.cpp:41:18:41:23 | string indirection |
| test.cpp:41:18:41:23 | string indirection | test.cpp:41:18:41:23 | string |
| test.cpp:42:13:42:15 | str indirection [string] | test.cpp:42:18:42:23 | string |
| test.cpp:42:13:42:15 | str indirection [string] | test.cpp:42:18:42:23 | string indirection |
| test.cpp:42:18:42:23 | string indirection | test.cpp:42:18:42:23 | string |
| test.cpp:44:13:44:15 | str indirection [string] | test.cpp:44:18:44:23 | string |
| test.cpp:44:13:44:15 | str indirection [string] | test.cpp:44:18:44:23 | string indirection |
| test.cpp:44:18:44:23 | string indirection | test.cpp:44:18:44:23 | string |
| test.cpp:45:13:45:15 | str indirection [string] | test.cpp:45:18:45:23 | string |
| test.cpp:45:13:45:15 | str indirection [string] | test.cpp:45:18:45:23 | string indirection |
| test.cpp:45:18:45:23 | string indirection | test.cpp:45:18:45:23 | string |
| test.cpp:48:17:48:19 | str indirection [string] | test.cpp:48:22:48:27 | string |
| test.cpp:48:17:48:19 | str indirection [string] | test.cpp:48:22:48:27 | string indirection |
| test.cpp:48:22:48:27 | string indirection | test.cpp:48:22:48:27 | string |
| test.cpp:52:17:52:19 | str indirection [string] | test.cpp:52:22:52:27 | string |
| test.cpp:52:17:52:19 | str indirection [string] | test.cpp:52:22:52:27 | string indirection |
| test.cpp:52:22:52:27 | string indirection | test.cpp:52:22:52:27 | string |
| test.cpp:56:17:56:19 | str indirection [string] | test.cpp:56:22:56:27 | string |
| test.cpp:56:17:56:19 | str indirection [string] | test.cpp:56:22:56:27 | string indirection |
| test.cpp:56:22:56:27 | string indirection | test.cpp:56:22:56:27 | string |
| test.cpp:60:17:60:19 | str indirection [string] | test.cpp:60:22:60:27 | string |
| test.cpp:60:17:60:19 | str indirection [string] | test.cpp:60:22:60:27 | string indirection |
| test.cpp:60:22:60:27 | string indirection | test.cpp:60:22:60:27 | string |
| test.cpp:64:17:64:19 | str indirection [string] | test.cpp:64:22:64:27 | string |
| test.cpp:64:17:64:19 | str indirection [string] | test.cpp:64:22:64:27 | string indirection |
| test.cpp:64:22:64:27 | string indirection | test.cpp:64:22:64:27 | string |
| test.cpp:68:17:68:19 | str indirection [string] | test.cpp:68:22:68:27 | string |
| test.cpp:68:17:68:19 | str indirection [string] | test.cpp:68:22:68:27 | string indirection |
| test.cpp:68:22:68:27 | string indirection | test.cpp:68:22:68:27 | string |
| test.cpp:72:17:72:19 | str indirection [string] | test.cpp:72:22:72:27 | string |
| test.cpp:72:17:72:19 | str indirection [string] | test.cpp:72:22:72:27 | string indirection |
| test.cpp:72:22:72:27 | string indirection | test.cpp:72:22:72:27 | string |
| test.cpp:76:17:76:19 | str indirection [string] | test.cpp:76:22:76:27 | string |
| test.cpp:76:17:76:19 | str indirection [string] | test.cpp:76:22:76:27 | string indirection |
| test.cpp:76:22:76:27 | string indirection | test.cpp:76:22:76:27 | string |
| test.cpp:80:17:80:19 | str indirection [string] | test.cpp:80:22:80:27 | string |
| test.cpp:80:17:80:19 | str indirection [string] | test.cpp:80:22:80:27 | string indirection |
| test.cpp:80:22:80:27 | string indirection | test.cpp:80:22:80:27 | string |
| test.cpp:84:17:84:19 | str indirection [string] | test.cpp:84:22:84:27 | string |
| test.cpp:84:17:84:19 | str indirection [string] | test.cpp:84:22:84:27 | string indirection |
| test.cpp:84:22:84:27 | string indirection | test.cpp:84:22:84:27 | string |
| test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] |
| test.cpp:90:5:90:34 | ... = ... | test.cpp:90:10:90:15 | str indirection [post update] [string] |
| test.cpp:90:10:90:15 | str indirection [post update] [string] | test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] |
| test.cpp:90:19:90:24 | call to malloc | test.cpp:90:5:90:34 | ... = ... |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:98:13:98:15 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:99:13:99:15 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:101:13:101:15 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:102:13:102:15 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:105:17:105:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:109:17:109:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:113:17:113:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:117:17:117:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:121:17:121:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:125:17:125:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:129:17:129:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:133:17:133:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:137:17:137:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:141:17:141:19 | str indirection [string] |
| test.cpp:98:13:98:15 | str indirection [string] | test.cpp:98:18:98:23 | string |
| test.cpp:98:13:98:15 | str indirection [string] | test.cpp:98:18:98:23 | string indirection |
| test.cpp:98:18:98:23 | string indirection | test.cpp:98:18:98:23 | string |
| test.cpp:99:13:99:15 | str indirection [string] | test.cpp:99:18:99:23 | string |
| test.cpp:99:13:99:15 | str indirection [string] | test.cpp:99:18:99:23 | string indirection |
| test.cpp:99:18:99:23 | string indirection | test.cpp:99:18:99:23 | string |
| test.cpp:101:13:101:15 | str indirection [string] | test.cpp:101:18:101:23 | string |
| test.cpp:101:13:101:15 | str indirection [string] | test.cpp:101:18:101:23 | string indirection |
| test.cpp:101:18:101:23 | string indirection | test.cpp:101:18:101:23 | string |
| test.cpp:102:13:102:15 | str indirection [string] | test.cpp:102:18:102:23 | string |
| test.cpp:102:13:102:15 | str indirection [string] | test.cpp:102:18:102:23 | string indirection |
| test.cpp:102:18:102:23 | string indirection | test.cpp:102:18:102:23 | string |
| test.cpp:105:17:105:19 | str indirection [string] | test.cpp:105:22:105:27 | string |
| test.cpp:105:17:105:19 | str indirection [string] | test.cpp:105:22:105:27 | string indirection |
| test.cpp:105:22:105:27 | string indirection | test.cpp:105:22:105:27 | string |
| test.cpp:109:17:109:19 | str indirection [string] | test.cpp:109:22:109:27 | string |
| test.cpp:109:17:109:19 | str indirection [string] | test.cpp:109:22:109:27 | string indirection |
| test.cpp:109:22:109:27 | string indirection | test.cpp:109:22:109:27 | string |
| test.cpp:113:17:113:19 | str indirection [string] | test.cpp:113:22:113:27 | string |
| test.cpp:113:17:113:19 | str indirection [string] | test.cpp:113:22:113:27 | string indirection |
| test.cpp:113:22:113:27 | string indirection | test.cpp:113:22:113:27 | string |
| test.cpp:117:17:117:19 | str indirection [string] | test.cpp:117:22:117:27 | string |
| test.cpp:117:17:117:19 | str indirection [string] | test.cpp:117:22:117:27 | string indirection |
| test.cpp:117:22:117:27 | string indirection | test.cpp:117:22:117:27 | string |
| test.cpp:121:17:121:19 | str indirection [string] | test.cpp:121:22:121:27 | string |
| test.cpp:121:17:121:19 | str indirection [string] | test.cpp:121:22:121:27 | string indirection |
| test.cpp:121:22:121:27 | string indirection | test.cpp:121:22:121:27 | string |
| test.cpp:125:17:125:19 | str indirection [string] | test.cpp:125:22:125:27 | string |
| test.cpp:125:17:125:19 | str indirection [string] | test.cpp:125:22:125:27 | string indirection |
| test.cpp:125:22:125:27 | string indirection | test.cpp:125:22:125:27 | string |
| test.cpp:129:17:129:19 | str indirection [string] | test.cpp:129:22:129:27 | string |
| test.cpp:129:17:129:19 | str indirection [string] | test.cpp:129:22:129:27 | string indirection |
| test.cpp:129:22:129:27 | string indirection | test.cpp:129:22:129:27 | string |
| test.cpp:133:17:133:19 | str indirection [string] | test.cpp:133:22:133:27 | string |
| test.cpp:133:17:133:19 | str indirection [string] | test.cpp:133:22:133:27 | string indirection |
| test.cpp:133:22:133:27 | string indirection | test.cpp:133:22:133:27 | string |
| test.cpp:137:17:137:19 | str indirection [string] | test.cpp:137:22:137:27 | string |
| test.cpp:137:17:137:19 | str indirection [string] | test.cpp:137:22:137:27 | string indirection |
| test.cpp:137:22:137:27 | string indirection | test.cpp:137:22:137:27 | string |
| test.cpp:141:17:141:19 | str indirection [string] | test.cpp:141:22:141:27 | string |
| test.cpp:141:17:141:19 | str indirection [string] | test.cpp:141:22:141:27 | string indirection |
| test.cpp:141:22:141:27 | string indirection | test.cpp:141:22:141:27 | string |
| test.cpp:147:5:147:34 | ... = ... | test.cpp:147:10:147:15 | str indirection [post update] [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:150:13:150:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:151:13:151:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:152:13:152:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:154:13:154:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:155:13:155:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:156:13:156:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:159:17:159:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:163:17:163:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:167:17:167:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:171:17:171:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:175:17:175:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:179:17:179:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:183:17:183:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:187:17:187:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:191:17:191:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:195:17:195:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:199:17:199:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:203:17:203:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:207:17:207:19 | str indirection [string] |
| test.cpp:147:19:147:24 | call to malloc | test.cpp:147:5:147:34 | ... = ... |
| test.cpp:150:13:150:15 | str indirection [string] | test.cpp:150:18:150:23 | string |
| test.cpp:150:13:150:15 | str indirection [string] | test.cpp:150:18:150:23 | string indirection |
| test.cpp:150:18:150:23 | string indirection | test.cpp:150:18:150:23 | string |
| test.cpp:151:13:151:15 | str indirection [string] | test.cpp:151:18:151:23 | string |
| test.cpp:151:13:151:15 | str indirection [string] | test.cpp:151:18:151:23 | string indirection |
| test.cpp:151:18:151:23 | string indirection | test.cpp:151:18:151:23 | string |
| test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string |
| test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string indirection |
| test.cpp:152:18:152:23 | string indirection | test.cpp:152:18:152:23 | string |
| test.cpp:154:13:154:15 | str indirection [string] | test.cpp:154:18:154:23 | string |
| test.cpp:154:13:154:15 | str indirection [string] | test.cpp:154:18:154:23 | string indirection |
| test.cpp:154:18:154:23 | string indirection | test.cpp:154:18:154:23 | string |
| test.cpp:155:13:155:15 | str indirection [string] | test.cpp:155:18:155:23 | string |
| test.cpp:155:13:155:15 | str indirection [string] | test.cpp:155:18:155:23 | string indirection |
| test.cpp:155:18:155:23 | string indirection | test.cpp:155:18:155:23 | string |
| test.cpp:156:13:156:15 | str indirection [string] | test.cpp:156:18:156:23 | string |
| test.cpp:156:13:156:15 | str indirection [string] | test.cpp:156:18:156:23 | string indirection |
| test.cpp:156:18:156:23 | string indirection | test.cpp:156:18:156:23 | string |
| test.cpp:159:17:159:19 | str indirection [string] | test.cpp:159:22:159:27 | string |
| test.cpp:159:17:159:19 | str indirection [string] | test.cpp:159:22:159:27 | string indirection |
| test.cpp:159:22:159:27 | string indirection | test.cpp:159:22:159:27 | string |
| test.cpp:163:17:163:19 | str indirection [string] | test.cpp:163:22:163:27 | string |
| test.cpp:163:17:163:19 | str indirection [string] | test.cpp:163:22:163:27 | string indirection |
| test.cpp:163:22:163:27 | string indirection | test.cpp:163:22:163:27 | string |
| test.cpp:167:17:167:19 | str indirection [string] | test.cpp:167:22:167:27 | string |
| test.cpp:167:17:167:19 | str indirection [string] | test.cpp:167:22:167:27 | string indirection |
| test.cpp:167:22:167:27 | string indirection | test.cpp:167:22:167:27 | string |
| test.cpp:171:17:171:19 | str indirection [string] | test.cpp:171:22:171:27 | string |
| test.cpp:171:17:171:19 | str indirection [string] | test.cpp:171:22:171:27 | string indirection |
| test.cpp:171:22:171:27 | string indirection | test.cpp:171:22:171:27 | string |
| test.cpp:175:17:175:19 | str indirection [string] | test.cpp:175:22:175:27 | string |
| test.cpp:175:17:175:19 | str indirection [string] | test.cpp:175:22:175:27 | string indirection |
| test.cpp:175:22:175:27 | string indirection | test.cpp:175:22:175:27 | string |
| test.cpp:179:17:179:19 | str indirection [string] | test.cpp:179:22:179:27 | string |
| test.cpp:179:17:179:19 | str indirection [string] | test.cpp:179:22:179:27 | string indirection |
| test.cpp:179:22:179:27 | string indirection | test.cpp:179:22:179:27 | string |
| test.cpp:183:17:183:19 | str indirection [string] | test.cpp:183:22:183:27 | string |
| test.cpp:183:17:183:19 | str indirection [string] | test.cpp:183:22:183:27 | string indirection |
| test.cpp:183:22:183:27 | string indirection | test.cpp:183:22:183:27 | string |
| test.cpp:187:17:187:19 | str indirection [string] | test.cpp:187:22:187:27 | string |
| test.cpp:187:17:187:19 | str indirection [string] | test.cpp:187:22:187:27 | string indirection |
| test.cpp:187:22:187:27 | string indirection | test.cpp:187:22:187:27 | string |
| test.cpp:191:17:191:19 | str indirection [string] | test.cpp:191:22:191:27 | string |
| test.cpp:191:17:191:19 | str indirection [string] | test.cpp:191:22:191:27 | string indirection |
| test.cpp:191:22:191:27 | string indirection | test.cpp:191:22:191:27 | string |
| test.cpp:195:17:195:19 | str indirection [string] | test.cpp:195:22:195:27 | string |
| test.cpp:195:17:195:19 | str indirection [string] | test.cpp:195:22:195:27 | string indirection |
| test.cpp:195:22:195:27 | string indirection | test.cpp:195:22:195:27 | string |
@@ -222,159 +82,57 @@ edges
| test.cpp:243:12:243:14 | str indirection [string] | test.cpp:243:12:243:21 | string |
| test.cpp:243:12:243:14 | str indirection [string] | test.cpp:243:16:243:21 | string indirection |
| test.cpp:243:16:243:21 | string indirection | test.cpp:243:12:243:21 | string |
| test.cpp:249:20:249:27 | call to my_alloc | test.cpp:250:12:250:12 | p |
| test.cpp:256:17:256:22 | call to malloc | test.cpp:257:12:257:12 | p |
| test.cpp:262:22:262:27 | call to malloc | test.cpp:266:12:266:12 | p |
| test.cpp:264:20:264:25 | call to malloc | test.cpp:266:12:266:12 | p |
nodes
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | semmle.label | mk_string_t indirection [string] |
| test.cpp:18:5:18:30 | ... = ... | semmle.label | ... = ... |
| test.cpp:18:10:18:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:18:19:18:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:24:21:24:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] |
| test.cpp:26:13:26:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:26:18:26:23 | string | semmle.label | string |
| test.cpp:26:18:26:23 | string indirection | semmle.label | string indirection |
| test.cpp:29:32:29:34 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:30:13:30:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:30:18:30:23 | string | semmle.label | string |
| test.cpp:30:18:30:23 | string indirection | semmle.label | string indirection |
| test.cpp:34:21:34:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] |
| test.cpp:35:21:35:23 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] |
| test.cpp:41:13:41:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:41:18:41:23 | string | semmle.label | string |
| test.cpp:41:18:41:23 | string indirection | semmle.label | string indirection |
| test.cpp:42:13:42:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:42:18:42:23 | string | semmle.label | string |
| test.cpp:42:18:42:23 | string indirection | semmle.label | string indirection |
| test.cpp:44:13:44:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:44:18:44:23 | string | semmle.label | string |
| test.cpp:44:18:44:23 | string indirection | semmle.label | string indirection |
| test.cpp:45:13:45:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:45:18:45:23 | string | semmle.label | string |
| test.cpp:45:18:45:23 | string indirection | semmle.label | string indirection |
| test.cpp:48:17:48:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:48:22:48:27 | string | semmle.label | string |
| test.cpp:48:22:48:27 | string indirection | semmle.label | string indirection |
| test.cpp:52:17:52:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:52:22:52:27 | string | semmle.label | string |
| test.cpp:52:22:52:27 | string indirection | semmle.label | string indirection |
| test.cpp:56:17:56:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:56:22:56:27 | string | semmle.label | string |
| test.cpp:56:22:56:27 | string indirection | semmle.label | string indirection |
| test.cpp:60:17:60:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:60:22:60:27 | string | semmle.label | string |
| test.cpp:60:22:60:27 | string indirection | semmle.label | string indirection |
| test.cpp:64:17:64:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:64:22:64:27 | string | semmle.label | string |
| test.cpp:64:22:64:27 | string indirection | semmle.label | string indirection |
| test.cpp:68:17:68:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:68:22:68:27 | string | semmle.label | string |
| test.cpp:68:22:68:27 | string indirection | semmle.label | string indirection |
| test.cpp:72:17:72:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:72:22:72:27 | string | semmle.label | string |
| test.cpp:72:22:72:27 | string indirection | semmle.label | string indirection |
| test.cpp:76:17:76:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:76:22:76:27 | string | semmle.label | string |
| test.cpp:76:22:76:27 | string indirection | semmle.label | string indirection |
| test.cpp:80:17:80:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:80:22:80:27 | string | semmle.label | string |
| test.cpp:80:22:80:27 | string indirection | semmle.label | string indirection |
| test.cpp:84:17:84:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:84:22:84:27 | string | semmle.label | string |
| test.cpp:84:22:84:27 | string indirection | semmle.label | string indirection |
| test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | semmle.label | mk_string_t_plus_one indirection [string] |
| test.cpp:90:5:90:34 | ... = ... | semmle.label | ... = ... |
| test.cpp:90:10:90:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:90:19:90:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | semmle.label | call to mk_string_t_plus_one indirection [string] |
| test.cpp:98:13:98:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:98:18:98:23 | string | semmle.label | string |
| test.cpp:98:18:98:23 | string indirection | semmle.label | string indirection |
| test.cpp:99:13:99:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:99:18:99:23 | string | semmle.label | string |
| test.cpp:99:18:99:23 | string indirection | semmle.label | string indirection |
| test.cpp:101:13:101:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:101:18:101:23 | string | semmle.label | string |
| test.cpp:101:18:101:23 | string indirection | semmle.label | string indirection |
| test.cpp:102:13:102:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:102:18:102:23 | string | semmle.label | string |
| test.cpp:102:18:102:23 | string indirection | semmle.label | string indirection |
| test.cpp:105:17:105:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:105:22:105:27 | string | semmle.label | string |
| test.cpp:105:22:105:27 | string indirection | semmle.label | string indirection |
| test.cpp:109:17:109:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:109:22:109:27 | string | semmle.label | string |
| test.cpp:109:22:109:27 | string indirection | semmle.label | string indirection |
| test.cpp:113:17:113:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:113:22:113:27 | string | semmle.label | string |
| test.cpp:113:22:113:27 | string indirection | semmle.label | string indirection |
| test.cpp:117:17:117:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:117:22:117:27 | string | semmle.label | string |
| test.cpp:117:22:117:27 | string indirection | semmle.label | string indirection |
| test.cpp:121:17:121:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:121:22:121:27 | string | semmle.label | string |
| test.cpp:121:22:121:27 | string indirection | semmle.label | string indirection |
| test.cpp:125:17:125:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:125:22:125:27 | string | semmle.label | string |
| test.cpp:125:22:125:27 | string indirection | semmle.label | string indirection |
| test.cpp:129:17:129:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:129:22:129:27 | string | semmle.label | string |
| test.cpp:129:22:129:27 | string indirection | semmle.label | string indirection |
| test.cpp:133:17:133:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:133:22:133:27 | string | semmle.label | string |
| test.cpp:133:22:133:27 | string indirection | semmle.label | string indirection |
| test.cpp:137:17:137:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:137:22:137:27 | string | semmle.label | string |
| test.cpp:137:22:137:27 | string indirection | semmle.label | string indirection |
| test.cpp:141:17:141:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:141:22:141:27 | string | semmle.label | string |
| test.cpp:141:22:141:27 | string indirection | semmle.label | string indirection |
| test.cpp:147:5:147:34 | ... = ... | semmle.label | ... = ... |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:147:19:147:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:150:13:150:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:150:18:150:23 | string | semmle.label | string |
| test.cpp:150:18:150:23 | string indirection | semmle.label | string indirection |
| test.cpp:151:13:151:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:151:18:151:23 | string | semmle.label | string |
| test.cpp:151:18:151:23 | string indirection | semmle.label | string indirection |
| test.cpp:152:13:152:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:152:18:152:23 | string | semmle.label | string |
| test.cpp:152:18:152:23 | string indirection | semmle.label | string indirection |
| test.cpp:154:13:154:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:154:18:154:23 | string | semmle.label | string |
| test.cpp:154:18:154:23 | string indirection | semmle.label | string indirection |
| test.cpp:155:13:155:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:155:18:155:23 | string | semmle.label | string |
| test.cpp:155:18:155:23 | string indirection | semmle.label | string indirection |
| test.cpp:156:13:156:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:156:18:156:23 | string | semmle.label | string |
| test.cpp:156:18:156:23 | string indirection | semmle.label | string indirection |
| test.cpp:159:17:159:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:159:22:159:27 | string | semmle.label | string |
| test.cpp:159:22:159:27 | string indirection | semmle.label | string indirection |
| test.cpp:163:17:163:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:163:22:163:27 | string | semmle.label | string |
| test.cpp:163:22:163:27 | string indirection | semmle.label | string indirection |
| test.cpp:167:17:167:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:167:22:167:27 | string | semmle.label | string |
| test.cpp:167:22:167:27 | string indirection | semmle.label | string indirection |
| test.cpp:171:17:171:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:171:22:171:27 | string | semmle.label | string |
| test.cpp:171:22:171:27 | string indirection | semmle.label | string indirection |
| test.cpp:175:17:175:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:175:22:175:27 | string | semmle.label | string |
| test.cpp:175:22:175:27 | string indirection | semmle.label | string indirection |
| test.cpp:179:17:179:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:179:22:179:27 | string | semmle.label | string |
| test.cpp:179:22:179:27 | string indirection | semmle.label | string indirection |
| test.cpp:183:17:183:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:183:22:183:27 | string | semmle.label | string |
| test.cpp:183:22:183:27 | string indirection | semmle.label | string indirection |
| test.cpp:187:17:187:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:187:22:187:27 | string | semmle.label | string |
| test.cpp:187:22:187:27 | string indirection | semmle.label | string indirection |
| test.cpp:191:17:191:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:191:22:191:27 | string | semmle.label | string |
| test.cpp:191:22:191:27 | string indirection | semmle.label | string indirection |
| test.cpp:195:17:195:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:195:22:195:27 | string | semmle.label | string |
| test.cpp:195:22:195:27 | string indirection | semmle.label | string indirection |
@@ -402,6 +160,13 @@ nodes
| test.cpp:243:12:243:14 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:243:12:243:21 | string | semmle.label | string |
| test.cpp:243:16:243:21 | string indirection | semmle.label | string indirection |
| test.cpp:249:20:249:27 | call to my_alloc | semmle.label | call to my_alloc |
| test.cpp:250:12:250:12 | p | semmle.label | p |
| test.cpp:256:17:256:22 | call to malloc | semmle.label | call to malloc |
| test.cpp:257:12:257:12 | p | semmle.label | p |
| test.cpp:262:22:262:27 | call to malloc | semmle.label | call to malloc |
| test.cpp:264:20:264:25 | call to malloc | semmle.label | call to malloc |
| test.cpp:266:12:266:12 | p | semmle.label | p |
subpaths
| test.cpp:242:22:242:27 | buffer | test.cpp:235:40:235:45 | buffer | test.cpp:236:12:236:17 | p_str indirection [post update] [string] | test.cpp:242:16:242:19 | set_string output argument [string] |
#select
@@ -420,5 +185,6 @@ subpaths
| test.cpp:199:9:199:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:199:22:199:27 | string | This write may overflow $@ by 2 elements. | test.cpp:199:22:199:27 | string | string |
| test.cpp:203:9:203:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:203:22:203:27 | string | This write may overflow $@ by 2 elements. | test.cpp:203:22:203:27 | string | string |
| test.cpp:207:9:207:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:207:22:207:27 | string | This write may overflow $@ by 3 elements. | test.cpp:207:22:207:27 | string | string |
| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 32 elements. | test.cpp:232:10:232:15 | buffer | buffer |
| test.cpp:243:5:243:10 | call to memset | test.cpp:241:27:241:32 | call to malloc | test.cpp:243:12:243:21 | string | This write may overflow $@ by 1 element. | test.cpp:243:16:243:21 | string | string |
| test.cpp:250:5:250:10 | call to memset | test.cpp:249:20:249:27 | call to my_alloc | test.cpp:250:12:250:12 | p | This write may overflow $@ by 1 element. | test.cpp:250:12:250:12 | p | p |
| test.cpp:266:5:266:10 | call to memset | test.cpp:262:22:262:27 | call to malloc | test.cpp:266:12:266:12 | p | This write may overflow $@ by 1 element. | test.cpp:266:12:266:12 | p | p |

View File

@@ -213,7 +213,7 @@ void *memset(void *, int, unsigned);
void call_memset(void *p, unsigned size)
{
memset(p, 0, size); // GOOD [FALSE POSITIVE]
memset(p, 0, size); // GOOD
}
void test_missing_call_context(unsigned char *unrelated_buffer, unsigned size) {
@@ -229,7 +229,7 @@ void repeated_alerts(unsigned size, unsigned offset) {
while(unknown()) {
++size;
}
memset(buffer, 0, size); // BAD
memset(buffer, 0, size); // BAD [NOT DETECTED]
}
void set_string(string_t* p_str, char* buffer) {
@@ -243,3 +243,25 @@ void test_flow_through_setter(unsigned size) {
memset(str.string, 0, size + 1); // BAD
}
void* my_alloc(unsigned size);
void foo(unsigned size) {
int* p = (int*)my_alloc(size); // BAD
memset(p, 0, size + 1);
}
void test6(unsigned long n, char *p) {
while (unknown()) {
n++;
p = (char *)malloc(n);
memset(p, 0, n); // GOOD
}
}
void test7(unsigned n) {
char* p = (char*)malloc(n);
if(!p) {
p = (char*)malloc(++n);
}
memset(p, 0, n); // GOOD [FALSE POSITIVE]
}

View File

@@ -649,6 +649,36 @@ edges
| test.cpp:280:13:280:24 | new[] | test.cpp:281:14:281:15 | xs |
| test.cpp:290:13:290:24 | new[] | test.cpp:291:14:291:15 | xs |
| test.cpp:290:13:290:24 | new[] | test.cpp:292:30:292:30 | x |
| test.cpp:304:15:304:26 | new[] | test.cpp:307:5:307:6 | xs |
| test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:6 | xs |
| test.cpp:308:5:308:6 | xs | test.cpp:308:5:308:11 | access to array |
| test.cpp:308:5:308:11 | access to array | test.cpp:308:5:308:29 | Store: ... = ... |
| test.cpp:313:16:313:29 | new[] | test.cpp:314:17:314:18 | xs |
| test.cpp:314:17:314:18 | xs | test.cpp:314:17:314:25 | ... + ... |
| test.cpp:314:17:314:18 | xs | test.cpp:314:17:314:25 | ... + ... |
| test.cpp:314:17:314:18 | xs | test.cpp:318:13:318:20 | * ... |
| test.cpp:314:17:314:25 | ... + ... | test.cpp:318:14:318:20 | current |
| test.cpp:314:17:314:25 | ... + ... | test.cpp:318:14:318:20 | current |
| test.cpp:314:17:314:25 | ... + ... | test.cpp:320:13:320:20 | * ... |
| test.cpp:314:17:314:25 | ... + ... | test.cpp:320:13:320:20 | * ... |
| test.cpp:314:17:314:25 | ... + ... | test.cpp:320:14:320:20 | current |
| test.cpp:314:17:314:25 | ... + ... | test.cpp:320:14:320:20 | current |
| test.cpp:318:13:318:20 | * ... | test.cpp:318:14:318:20 | current |
| test.cpp:318:13:318:20 | * ... | test.cpp:320:13:320:20 | * ... |
| test.cpp:318:13:318:20 | * ... | test.cpp:320:14:320:20 | current |
| test.cpp:318:14:318:20 | current | test.cpp:314:17:314:25 | Store: ... + ... |
| test.cpp:318:14:318:20 | current | test.cpp:318:13:318:20 | Load: * ... |
| test.cpp:318:14:318:20 | current | test.cpp:320:10:320:21 | Store: -- ... |
| test.cpp:318:14:318:20 | current | test.cpp:320:12:320:21 | Load: (...) |
| test.cpp:320:13:320:20 | * ... | test.cpp:314:17:314:25 | Store: ... + ... |
| test.cpp:320:13:320:20 | * ... | test.cpp:318:13:318:20 | Load: * ... |
| test.cpp:320:13:320:20 | * ... | test.cpp:320:10:320:21 | Store: -- ... |
| test.cpp:320:13:320:20 | * ... | test.cpp:320:12:320:21 | Load: (...) |
| test.cpp:320:14:320:20 | current | test.cpp:314:17:314:25 | Store: ... + ... |
| test.cpp:320:14:320:20 | current | test.cpp:318:13:318:20 | Load: * ... |
| test.cpp:320:14:320:20 | current | test.cpp:320:10:320:21 | Store: -- ... |
| test.cpp:320:14:320:20 | current | test.cpp:320:12:320:21 | Load: (...) |
subpaths
#select
| test.cpp:6:14:6:15 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
| test.cpp:8:14:8:21 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:8:14:8:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
@@ -672,3 +702,8 @@ edges
| test.cpp:254:9:254:16 | Store: ... = ... | test.cpp:248:24:248:30 | call to realloc | test.cpp:254:9:254:16 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:248:24:248:30 | call to realloc | call to realloc | test.cpp:254:11:254:11 | i | i |
| test.cpp:264:13:264:14 | Load: * ... | test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:260:13:260:24 | new[] | new[] | test.cpp:261:19:261:21 | len | len |
| test.cpp:274:5:274:10 | Store: ... = ... | test.cpp:270:13:270:24 | new[] | test.cpp:274:5:274:10 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:270:13:270:24 | new[] | new[] | test.cpp:271:19:271:21 | len | len |
| test.cpp:308:5:308:29 | Store: ... = ... | test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:29 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:304:15:304:26 | new[] | new[] | test.cpp:308:8:308:10 | ... + ... | ... + ... |
| test.cpp:314:17:314:25 | Store: ... + ... | test.cpp:313:16:313:29 | new[] | test.cpp:314:17:314:25 | Store: ... + ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:313:16:313:29 | new[] | new[] | test.cpp:314:22:314:25 | size | size |
| test.cpp:318:13:318:20 | Load: * ... | test.cpp:313:16:313:29 | new[] | test.cpp:318:13:318:20 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:313:16:313:29 | new[] | new[] | test.cpp:314:22:314:25 | size | size |
| test.cpp:320:10:320:21 | Store: -- ... | test.cpp:313:16:313:29 | new[] | test.cpp:320:10:320:21 | Store: -- ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:313:16:313:29 | new[] | new[] | test.cpp:314:22:314:25 | size | size |
| test.cpp:320:12:320:21 | Load: (...) | test.cpp:313:16:313:29 | new[] | test.cpp:320:12:320:21 | Load: (...) | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:313:16:313:29 | new[] | new[] | test.cpp:314:22:314:25 | size | size |

View File

@@ -293,4 +293,32 @@ void test20(unsigned len)
{
*x = 0; // GOOD
}
}
}
void* test21_get(int n);
void test21() {
int n = 0;
while (test21_get(n)) n+=2;
void** xs = new void*[n];
for (int i = 0; i < n; i += 2) {
xs[i] = test21_get(i); // GOOD
xs[i+1] = test21_get(i+1); // GOOD [FALSE POSITIVE]
}
}
void test22(unsigned size, int val) {
char *xs = new char[size];
char *end = xs + size; // GOOD [FALSE POSITIVE]
char **current = &end;
do
{
if( *current - xs < 1 ) // GOOD [FALSE POSITIVE]
return;
*--(*current) = 0; // GOOD [FALSE POSITIVE]
val >>= 8;
}
while( val > 0 );
}

View File

@@ -1,7 +1,7 @@
// semmle-extractor-options: --edg --clang
int source();
void sink(int); void sink(const int *); void sink(int **);
void sink(int); void sink(const int *); void sink(int **); void indirect_sink(...);
struct twoIntFields {
int m1, m2;
@@ -19,7 +19,8 @@ void following_pointers( // $ ast-def=sourceStruct1_ptr
sink(sourceArray1[0]); // no flow
sink(*sourceArray1); // no flow
sink(&sourceArray1); // $ ast,ir // [should probably be taint only]
sink(&sourceArray1); // $ ast // [should probably be taint only]
indirect_sink(&sourceArray1); // $ ast,ir
sink(sourceStruct1.m1); // no flow
sink(sourceStruct1_ptr->m1); // no flow
@@ -48,5 +49,6 @@ void following_pointers( // $ ast-def=sourceStruct1_ptr
int stackArray[2] = { source(), source() };
stackArray[0] = source();
sink(stackArray); // $ ast ir ir=49:25 ir=49:35 ir=50:19
sink(stackArray); // $ ast,ir
indirect_sink(stackArray); // $ ast ir=50:25 ir=50:35 ir=51:19
}

View File

@@ -28,9 +28,10 @@ postWithInFlow
| BarrierGuard.cpp:49:6:49:6 | x [post update] | PostUpdateNode should not be the target of local flow. |
| BarrierGuard.cpp:60:7:60:7 | x [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:22:9:22:20 | sourceArray1 [inner post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:28:22:28:23 | m1 [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:50:3:50:12 | stackArray [inner post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:50:3:50:15 | access to array [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:23:18:23:29 | sourceArray1 [inner post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:29:22:29:23 | m1 [post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:51:3:51:12 | stackArray [inner post update] | PostUpdateNode should not be the target of local flow. |
| clang.cpp:51:3:51:15 | access to array [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:60:3:60:14 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:61:3:61:14 | globalMiddle [post update] | PostUpdateNode should not be the target of local flow. |
| dispatch.cpp:78:24:78:37 | call to allocateBottom [inner post update] | PostUpdateNode should not be the target of local flow. |
@@ -125,6 +126,8 @@ postWithInFlow
| test.cpp:681:3:681:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:689:3:689:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:690:3:690:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:694:4:694:6 | buf [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:704:23:704:25 | buf [inner post update] | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge
uniqueParameterNodeAtPosition
uniqueParameterNodePosition

View File

@@ -1,5 +1,5 @@
int source();
void sink(int); void sink(const int *); void sink(int **);
void sink(int); void sink(const int *); void sink(int **); void indirect_sink(...);
void intraprocedural_with_local_flow() {
int t2;
@@ -626,7 +626,7 @@ void test_def_via_phi_read(bool b)
use(buffer);
}
intPointerSource(buffer);
sink(buffer); // $ ast,ir
indirect_sink(buffer); // $ ast,ir
}
void test_static_local_1() {
@@ -690,3 +690,16 @@ void test_static_local_9() {
s = 0;
}
void increment_buf(int** buf) { // $ ast-def=buf ir-def=*buf ir-def=**buf
*buf += 10;
sink(buf); // $ SPURIOUS: ast
}
void call_increment_buf(int** buf) { // $ ast-def=buf
increment_buf(buf);
}
void test_conflation_regression(int* source) { // $ ast-def=source
int* buf = source;
call_increment_buf(&buf);
}

View File

@@ -34,7 +34,7 @@ module AstTest {
override predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call |
call.getTarget().getName() = "sink" and
call.getTarget().getName() = ["sink", "indirect_sink"] and
sink.asExpr() = call.getAnArgument()
)
}
@@ -83,9 +83,12 @@ module IRTest {
}
override predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call |
exists(FunctionCall call, Expr e | e = call.getAnArgument() |
call.getTarget().getName() = "sink" and
call.getAnArgument() in [sink.asExpr(), sink.asIndirectExpr()]
sink.asExpr() = e
or
call.getTarget().getName() = "indirect_sink" and
sink.asIndirectExpr() = e
)
}

View File

@@ -49,3 +49,13 @@
return 0;
}
void* f3_get(int n);
void f3() {
int n = 0;
while (f3_get(n)) n+=2;
for (int i = 0; i < n; i += 2) {
range(i); // $ range=>=0 SPURIOUS: range="<=call to f3_get-1" range="<=call to f3_get-2"
}
}

View File

@@ -1,29 +1,16 @@
edges
| tests.cpp:26:15:26:23 | badSource indirection | tests.cpp:51:12:51:20 | call to badSource indirection |
| tests.cpp:26:32:26:35 | data indirection | tests.cpp:26:15:26:23 | badSource indirection |
| tests.cpp:26:32:26:35 | data indirection | tests.cpp:38:25:38:36 | strncat output argument |
| tests.cpp:33:34:33:39 | call to getenv indirection | tests.cpp:38:39:38:49 | environment indirection |
| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:26:15:26:23 | badSource indirection |
| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:26:15:26:23 | badSource indirection |
| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:51:22:51:25 | badSource output argument |
| tests.cpp:38:39:38:49 | environment indirection | tests.cpp:38:25:38:36 | strncat output argument |
| tests.cpp:51:12:51:20 | call to badSource indirection | tests.cpp:53:16:53:19 | data indirection |
| tests.cpp:51:22:51:25 | badSource output argument | tests.cpp:51:22:51:25 | data indirection |
| tests.cpp:51:22:51:25 | data indirection | tests.cpp:26:32:26:35 | data indirection |
| tests.cpp:51:22:51:25 | data indirection | tests.cpp:51:12:51:20 | call to badSource indirection |
nodes
| tests.cpp:26:15:26:23 | badSource indirection | semmle.label | badSource indirection |
| tests.cpp:26:15:26:23 | badSource indirection | semmle.label | badSource indirection |
| tests.cpp:26:32:26:35 | data indirection | semmle.label | data indirection |
| tests.cpp:33:34:33:39 | call to getenv indirection | semmle.label | call to getenv indirection |
| tests.cpp:38:25:38:36 | strncat output argument | semmle.label | strncat output argument |
| tests.cpp:38:25:38:36 | strncat output argument | semmle.label | strncat output argument |
| tests.cpp:38:39:38:49 | environment indirection | semmle.label | environment indirection |
| tests.cpp:51:12:51:20 | call to badSource indirection | semmle.label | call to badSource indirection |
| tests.cpp:51:22:51:25 | badSource output argument | semmle.label | badSource output argument |
| tests.cpp:51:22:51:25 | data indirection | semmle.label | data indirection |
| tests.cpp:53:16:53:19 | data indirection | semmle.label | data indirection |
subpaths
| tests.cpp:51:22:51:25 | data indirection | tests.cpp:26:32:26:35 | data indirection | tests.cpp:26:15:26:23 | badSource indirection | tests.cpp:51:12:51:20 | call to badSource indirection |
#select
| tests.cpp:53:16:53:19 | data | tests.cpp:33:34:33:39 | call to getenv indirection | tests.cpp:53:16:53:19 | data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | tests.cpp:33:34:33:39 | call to getenv indirection | user input (an environment variable) | tests.cpp:38:25:38:36 | strncat output argument | strncat output argument |

View File

@@ -45,8 +45,6 @@ edges
| test.cpp:186:47:186:54 | filename indirection | test.cpp:188:20:188:24 | flags indirection |
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument |
| test.cpp:187:18:187:25 | filename indirection | test.cpp:187:11:187:15 | strncat output argument |
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument |
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument |
| test.cpp:188:20:188:24 | flags indirection | test.cpp:188:11:188:17 | strncat output argument |
| test.cpp:194:9:194:16 | fread output argument | test.cpp:196:26:196:33 | filename indirection |
| test.cpp:196:10:196:16 | concat output argument | test.cpp:198:32:198:38 | command indirection |

View File

@@ -72,5 +72,5 @@ private class MyConsistencyConfiguration extends ConsistencyConfiguration {
override predicate reverseReadExclude(Node n) { n.asExpr() = any(AwaitExpr ae).getExpr() }
override predicate identityLocalStepExclude(Node n) { n.getLocation().getFile().fromLibrary() }
override predicate identityLocalStepExclude(Node n) { none() }
}

View File

@@ -2,6 +2,7 @@
### Minor Analysis Improvements
* The `cs/log-forging`, `cs/cleartext-storage`, and `cs/exposure-of-sensitive-information` queries now correctly handle unsanitized arguments to `ILogger` extension methods.
* Updated the `neutralModel` extensible predicate to include a `kind` column.
## 0.6.1

View File

@@ -2,4 +2,5 @@
### Minor Analysis Improvements
* The `cs/log-forging`, `cs/cleartext-storage`, and `cs/exposure-of-sensitive-information` queries now correctly handle unsanitized arguments to `ILogger` extension methods.
* Updated the `neutralModel` extensible predicate to include a `kind` column.

View File

@@ -335,7 +335,8 @@ module LocalFlow {
exists(ControlFlow::BasicBlock bb, int i |
SsaImpl::lastRefBeforeRedefExt(def, bb, i, next.getDefinitionExt()) and
def.definesAt(_, bb, i, _) and
def = getSsaDefinitionExt(nodeFrom)
def = getSsaDefinitionExt(nodeFrom) and
nodeFrom != next
)
}
@@ -414,7 +415,8 @@ module LocalFlow {
) {
exists(CIL::BasicBlock bb, int i | CilSsaImpl::lastRefBeforeRedefExt(def, bb, i, next) |
def.definesAt(_, bb, i, _) and
def = nodeFrom.(CilSsaDefinitionExtNode).getDefinition()
def = nodeFrom.(CilSsaDefinitionExtNode).getDefinition() and
def != next
or
nodeFrom = TCilExprNode(bb.getNode(i).(CIL::ReadAccess))
)
@@ -440,7 +442,8 @@ module LocalFlow {
exists(CIL::ReadAccess readFrom, CIL::ReadAccess readTo |
CilSsaImpl::hasAdjacentReadsExt(def, readFrom, readTo) and
nodeTo = TCilExprNode(readTo) and
nodeFrom = TCilExprNode(readFrom)
nodeFrom = TCilExprNode(readFrom) and
nodeFrom != nodeTo
)
or
// Flow into phi (read) node
@@ -483,7 +486,8 @@ module LocalFlow {
or
hasNodePath(any(LocalExprStepConfiguration x), nodeFrom, nodeTo)
or
ThisFlow::adjacentThisRefs(nodeFrom, nodeTo)
ThisFlow::adjacentThisRefs(nodeFrom, nodeTo) and
nodeFrom != nodeTo
or
ThisFlow::adjacentThisRefs(nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
or
@@ -541,7 +545,8 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
exists(SsaImpl::DefinitionExt def |
LocalFlow::localSsaFlowStepUseUse(def, nodeFrom, nodeTo) and
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _) and
not LocalFlow::usesInstanceField(def)
not LocalFlow::usesInstanceField(def) and
nodeFrom != nodeTo
)
or
// Flow into phi (read)/uncertain SSA definition node from read
@@ -880,7 +885,8 @@ private module Cached {
predicate localFlowStepImpl(Node nodeFrom, Node nodeTo) {
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
or
LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo)
LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo) and
nodeFrom != nodeTo
or
exists(SsaImpl::DefinitionExt def |
LocalFlow::localSsaFlowStep(def, nodeFrom, nodeTo) and

View File

@@ -26,7 +26,14 @@ private class ExternalModelSink extends ExternalLocationSink {
* An argument to a call to a method on a logger class.
*/
class LogMessageSink extends ExternalLocationSink {
LogMessageSink() { this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument() }
LogMessageSink() {
this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument()
or
this.getExpr() =
any(ExtensionMethodCall call |
call.getTarget().(ExtensionMethod).getExtendedType() instanceof LoggerType
).getArgument(any(int i | i > 0))
}
}
/**

View File

@@ -1,7 +0,0 @@
identityLocalStep
| test.cs:17:41:17:44 | this access | Node steps to itself |
| test.cs:34:41:34:44 | this access | Node steps to itself |
| test.cs:52:41:52:44 | this access | Node steps to itself |
| test.cs:67:41:67:44 | this access | Node steps to itself |
| test.cs:77:22:77:24 | this access | Node steps to itself |
| test.cs:90:41:90:44 | this access | Node steps to itself |

View File

@@ -1,2 +0,0 @@
identityLocalStep
| Conditions.cs:133:17:133:22 | [Field1 (line 129): false] this access | Node steps to itself |

View File

@@ -1,2 +0,0 @@
identityLocalStep
| Splitting.cs:133:21:133:29 | [b (line 123): false] this access | Node steps to itself |

View File

@@ -1,7 +0,0 @@
identityLocalStep
| SplittingStressTest.cs:172:16:172:16 | SSA phi read(b29) | Node steps to itself |
| SplittingStressTest.cs:179:13:183:13 | [b1 (line 170): false] SSA phi read(b1) | Node steps to itself |
| SplittingStressTest.cs:184:13:188:13 | [b2 (line 170): false] SSA phi read(b2) | Node steps to itself |
| SplittingStressTest.cs:189:13:193:13 | [b3 (line 170): false] SSA phi read(b3) | Node steps to itself |
| SplittingStressTest.cs:194:13:198:13 | [b4 (line 170): false] SSA phi read(b4) | Node steps to itself |
| SplittingStressTest.cs:199:13:203:13 | [b5 (line 170): false] SSA phi read(b5) | Node steps to itself |

View File

@@ -1,2 +0,0 @@
identityLocalStep
| Test.cs:80:37:80:42 | this access | Node steps to itself |

View File

@@ -214,4 +214,25 @@ namespace My.Qltest
static void Sink(object o) { }
}
public interface HI { }
public class HC : HI { }
public static class HE
{
public static object ExtensionMethod(this HI h) => throw null;
}
public class H
{
void M1()
{
var h = new HC();
var o = h.ExtensionMethod();
Sink(o);
}
static void Sink(object o) { }
}
}

View File

@@ -70,6 +70,9 @@ edges
| ExternalFlow.cs:197:42:197:43 | access to local variable o2 : Object | ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs |
| ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object |
| ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs |
| ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | ExternalFlow.cs:232:21:232:21 | access to local variable h : HC |
| ExternalFlow.cs:232:21:232:21 | access to local variable h : HC | ExternalFlow.cs:232:21:232:39 | call to method ExtensionMethod : HC |
| ExternalFlow.cs:232:21:232:39 | call to method ExtensionMethod : HC | ExternalFlow.cs:233:18:233:18 | access to local variable o |
nodes
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | semmle.label | call to method StepArgRes |
@@ -162,6 +165,10 @@ nodes
| ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | semmle.label | call to method MixedFlowArgs |
| ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object |
| ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | semmle.label | object creation of type HC : HC |
| ExternalFlow.cs:232:21:232:21 | access to local variable h : HC | semmle.label | access to local variable h : HC |
| ExternalFlow.cs:232:21:232:39 | call to method ExtensionMethod : HC | semmle.label | call to method ExtensionMethod : HC |
| ExternalFlow.cs:233:18:233:18 | access to local variable o | semmle.label | access to local variable o |
subpaths
#select
| ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | $@ | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | object creation of type Object : Object |
@@ -188,3 +195,4 @@ subpaths
| ExternalFlow.cs:194:18:194:44 | call to method GeneratedFlowArgs | ExternalFlow.cs:193:22:193:33 | object creation of type Object : Object | ExternalFlow.cs:194:18:194:44 | call to method GeneratedFlowArgs | $@ | ExternalFlow.cs:193:22:193:33 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs | ExternalFlow.cs:196:22:196:33 | object creation of type Object : Object | ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs | $@ | ExternalFlow.cs:196:22:196:33 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | $@ | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:233:18:233:18 | access to local variable o | ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | ExternalFlow.cs:233:18:233:18 | access to local variable o | $@ | ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | object creation of type HC : HC |

View File

@@ -29,3 +29,4 @@ extensions:
- ["My.Qltest", "G", false, "GeneratedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[0]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "manual"]
- ["My.Qltest", "HE", false, "ExtensionMethod", "(My.Qltest.HI)", "", "Argument[0]", "ReturnValue", "value", "manual"]

View File

@@ -1,2 +0,0 @@
identityLocalStep
| GlobalDataFlow.cs:573:9:576:9 | SSA phi read(f) | Node steps to itself |

View File

@@ -1,3 +0,0 @@
identityLocalStep
| DefUse.cs:80:37:80:42 | this access | Node steps to itself |
| Properties.cs:65:24:65:31 | this access | Node steps to itself |

View File

@@ -1,4 +0,0 @@
identityLocalStep
| D.cs:320:17:320:25 | this access | Node steps to itself |
| E.cs:123:21:123:24 | SSA phi read(x) | Node steps to itself |
| E.cs:123:21:123:24 | SSA phi(i) | Node steps to itself |

View File

@@ -1,2 +0,0 @@
identityLocalStep
| ZipSlip.cs:13:13:45:13 | SSA phi read(destDirectory) | Node steps to itself |

View File

@@ -3,6 +3,7 @@ using System.Diagnostics;
using System.IO;
using System.Net;
using System.Web;
using Microsoft.Extensions.Logging;
class ILogger
{
@@ -24,6 +25,10 @@ public class LogForgingHandler : IHttpHandler
logger.Warn(WebUtility.HtmlEncode(username) + " logged in");
// BAD: Logged as-is to TraceSource
new TraceSource("Test").TraceInformation(username + " logged in");
Microsoft.Extensions.Logging.ILogger logger2 = null;
// BAD: Logged as-is
logger2.LogError(username);
}
public bool IsReusable

View File

@@ -1,19 +1,23 @@
edges
| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:17:27:17:61 | access to indexer : String |
| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:20:21:20:43 | ... + ... |
| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:26:50:26:72 | ... + ... |
| LogForging.cs:17:27:17:61 | access to indexer : String | LogForging.cs:20:21:20:43 | ... + ... |
| LogForging.cs:17:27:17:61 | access to indexer : String | LogForging.cs:26:50:26:72 | ... + ... |
| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:18:27:18:61 | access to indexer : String |
| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:21:21:21:43 | ... + ... |
| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:27:50:27:72 | ... + ... |
| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:31:26:31:33 | access to local variable username |
| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:21:21:21:43 | ... + ... |
| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:27:50:27:72 | ... + ... |
| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:31:26:31:33 | access to local variable username |
| LogForgingAsp.cs:8:32:8:39 | username : String | LogForgingAsp.cs:12:21:12:43 | ... + ... |
nodes
| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| LogForging.cs:17:27:17:61 | access to indexer : String | semmle.label | access to indexer : String |
| LogForging.cs:20:21:20:43 | ... + ... | semmle.label | ... + ... |
| LogForging.cs:26:50:26:72 | ... + ... | semmle.label | ... + ... |
| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| LogForging.cs:18:27:18:61 | access to indexer : String | semmle.label | access to indexer : String |
| LogForging.cs:21:21:21:43 | ... + ... | semmle.label | ... + ... |
| LogForging.cs:27:50:27:72 | ... + ... | semmle.label | ... + ... |
| LogForging.cs:31:26:31:33 | access to local variable username | semmle.label | access to local variable username |
| LogForgingAsp.cs:8:32:8:39 | username : String | semmle.label | username : String |
| LogForgingAsp.cs:12:21:12:43 | ... + ... | semmle.label | ... + ... |
subpaths
#select
| LogForging.cs:20:21:20:43 | ... + ... | LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:20:21:20:43 | ... + ... | This log entry depends on a $@. | LogForging.cs:17:27:17:49 | access to property QueryString | user-provided value |
| LogForging.cs:26:50:26:72 | ... + ... | LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:26:50:26:72 | ... + ... | This log entry depends on a $@. | LogForging.cs:17:27:17:49 | access to property QueryString | user-provided value |
| LogForging.cs:21:21:21:43 | ... + ... | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:21:21:21:43 | ... + ... | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
| LogForging.cs:27:50:27:72 | ... + ... | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:27:50:27:72 | ... + ... | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
| LogForging.cs:31:26:31:33 | access to local variable username | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:31:26:31:33 | access to local variable username | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
| LogForgingAsp.cs:12:21:12:43 | ... + ... | LogForgingAsp.cs:8:32:8:39 | username : String | LogForgingAsp.cs:12:21:12:43 | ... + ... | This log entry depends on a $@. | LogForgingAsp.cs:8:32:8:39 | username | user-provided value |

View File

@@ -193,7 +193,7 @@ The class `ASTNode <https://codeql.github.com/codeql-standard-libraries/javascri
.. pull-quote::
Note
These predicates should only be used to perform generic AST traversal. To access children of specific AST node types, the specialized predicates introduced below should be used instead. In particular, queries should not rely on the numeric indices of child nodes relative to their parent nodes: these are considered an implementation detail that may change between versions of the library.
Top-levels
@@ -700,28 +700,7 @@ The data flow graph-based analyses described so far are all intraprocedural: the
We distinguish here between data flow proper, and *taint tracking*: the latter not only considers value-preserving flow (such as from variable definitions to uses), but also cases where one value influences ("taints") another without determining it entirely. For example, in the assignment ``s2 = s1.substring(i)``, the value of ``s1`` influences the value of ``s2``, because ``s2`` is assigned a substring of ``s1``. In general, ``s2`` will not be assigned ``s1`` itself, so there is no data flow from ``s1`` to ``s2``, but ``s1`` still taints ``s2``.
The simplest way of implementing an interprocedural data flow analysis is to extend either class ``DataFlow::TrackedNode`` or ``DataFlow::TrackedExpr``. The former is a subclass of ``DataFlow::Node``, the latter of ``Expr``, and extending them ensures that the newly added values are tracked interprocedurally. You can use the predicate ``flowsTo`` to find out which nodes/expressions the tracked value flows to.
For example, suppose that we are developing an analysis to find hard-coded passwords. We might start by writing a simple query that looks for string constants flowing into variables named ``"password"``. To do this, we can extend ``TrackedExpr`` to track all constant strings, ``flowsTo`` to find cases where such a string flows into a (SSA) definition of a password variable:
.. code-block:: ql
import javascript
class TrackedStringLiteral extends DataFlow::TrackedNode {
TrackedStringLiteral() {
this.asExpr() instanceof ConstantString
}
}
from TrackedStringLiteral source, DataFlow::Node sink, SsaExplicitDefinition def
where source.flowsTo(sink) and sink = DataFlow::ssaDefinitionNode(def) and
def.getSourceVariable().getName().toLowerCase() = "password"
select sink
Note that ``TrackedNode`` and ``TrackedExpr`` do not restrict the set of "sinks" for the inter-procedural flow analysis, tracking flow into any expression that they might flow to. This can be expensive for large code bases, and is often unnecessary, since usually you are only interested in flow to a particular set of sinks. For example, the above query only looks for flow into assignments to password variables.
This is a particular instance of a general pattern, whereby we want to specify a data flow or taint analysis in terms of its *sources* (where flow starts), *sinks* (where it should be tracked), and *barriers* or *sanitizers* (where flow is interrupted). The example does not include any sanitizers, but they are very common in security analyses: for example, an analysis that tracks the flow of untrusted user input into, say, a SQL query has to keep track of code that validates the input, thereby making it safe to use. Such a validation step is an example of a sanitizer.
It is a common pattern that we wish to specify data flow or taint analysis in terms of its *sources* (where flow starts), *sinks* (where it should be tracked), and *barriers* or *sanitizers* (where flow is interrupted). Sanitizers they are very common in security analyses: for example, an analysis that tracks the flow of untrusted user input into, say, a SQL query has to keep track of code that validates the input, thereby making it safe to use. Such a validation step is an example of a sanitizer.
The classes ``DataFlow::Configuration`` and ``TaintTracking::Configuration`` allow specifying a data flow or taint analysis, respectively, by overriding the following predicates:
@@ -735,10 +714,12 @@ Since for technical reasons both ``Configuration`` classes are subtypes of ``str
The predicate ``Configuration.hasFlow`` performs the actual flow tracking, starting at a source and looking for flow to a sink that does not pass through a barrier node or edge.
To continue with our above example, we can phrase it as a data flow configuration as follows:
For example, suppose that we are developing an analysis to find hard-coded passwords. We might write a simple query that looks for string constants flowing into variables named ``"password"``.
.. code-block:: ql
import javascript
class PasswordTracker extends DataFlow::Configuration {
PasswordTracker() {
// unique identifier for this configuration
@@ -754,11 +735,8 @@ To continue with our above example, we can phrase it as a data flow configuratio
}
predicate passwordVarAssign(Variable v, DataFlow::Node nd) {
exists (SsaExplicitDefinition def |
nd = DataFlow::ssaDefinitionNode(def) and
def.getSourceVariable() = v and
v.getName().toLowerCase() = "password"
)
v.getAnAssignedExpr() = nd.asExpr() and
v.getName().toLowerCase() = "password"
}
}
@@ -770,7 +748,6 @@ Now we can rephrase our query to use ``Configuration.hasFlow``:
where pt.hasFlow(source, sink) and pt.passwordVarAssign(v, sink)
select sink, "Password variable " + v + " is assigned a constant string."
Note that while analyses implemented in this way are inter-procedural in that they track flow and taint across function calls and returns, flow through global variables is not tracked. Flow through object properties is only tracked in limited cases, for example through properties of object literals or CommonJS ``module`` and ``exports`` objects.
Syntax errors
~~~~~~~~~~~~~
@@ -794,7 +771,7 @@ The ``semmle.javascript.frameworks.AngularJS`` library provides support for work
HTTP framework libraries
^^^^^^^^^^^^^^^^^^^^^^^^
The library ``semmle.javacript.frameworks.HTTP`` provides classes modeling common concepts from various HTTP frameworks.
The library ``semmle.javacript.frameworks.HTTP`` provides classes modeling common concepts from various HTTP frameworks.
Currently supported frameworks are `Express <https://expressjs.com/>`__, the standard Node.js ``http`` and ``https`` modules, `Connect <https://github.com/senchalabs/connect>`__, `Koa <https://koajs.com>`__, `Hapi <https://hapi.dev/>`__ and `Restify <http://restify.com/>`__.

View File

@@ -176,9 +176,13 @@ A QL module definition has the following syntax:
::
module ::= annotation* "module" modulename "{" moduleBody "}"
module ::= annotation* "module" modulename parameters? implements? "{" moduleBody "}"
moduleBody ::= (import | predicate | class | module | alias | select)*
parameters ::= "<" signatureExpr parameterName ("," signatureExpr parameterName)* ">"
implements ::= "implements" moduleSignatureExpr ("," moduleSignatureExpr)*
moduleBody ::= (import | predicate | class | module | signature | alias | select)*
A module definition extends the current module's declared module environment with a mapping from the module name to the module definition.
@@ -208,12 +212,15 @@ An import directive refers to a module identifier:
::
import ::= annotations "import" importModuleId ("as" modulename)?
import ::= annotations "import" importModuleExpr ("as" modulename)?
qualId ::= simpleId | qualId "." simpleId
importModuleId ::= qualId
| importModuleId "::" simpleId
importModuleExpr ::= qualId | importModuleExpr "::" modulename arguments?
arguments ::= "<" argument ("," argument)* ">"
argument ::= moduleExpr | type | predicateRef "/" int
An import directive may optionally name the imported module using an ``as`` declaration. If a name is defined, then the import directive adds to the declared module environment of the current module a mapping from the name to the declaration of the imported module. Otherwise, the current module *directly imports* the imported module.
@@ -280,9 +287,9 @@ With the exception of class domain types and character types (which cannot be re
::
type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string"
type ::= (moduleExpr "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string"
moduleId ::= simpleId | moduleId "::" simpleId
moduleExpr ::= modulename arguments? | moduleExpr "::" modulename arguments?
A type reference is resolved to a type as follows:
@@ -327,6 +334,40 @@ Active types
In a QL program, the *active* types are those defined in active modules. In the remainder of this specification, any reference to the types in the program refers only to the active types.
Signatures
----------
Signature definitions
~~~~~~~~~~~~~~~~~~~~~
A QL signature definition has the following syntax:
::
signature ::= predicateSignature | typeSignature | moduleSignature
predicateSignature ::= qldoc? annotations "signature" head ";"
typeSignature ::= qldoc? annotations "signature" "class" classname ("extends" type ("," type)*)? (";" | "{" signaturePredicate* "}")
moduleSignature ::= qldoc? annotation* "signature" "module" moduleSignatureName parameters? "{" moduleSignatureBody "}"
moduleSignatureBody ::= (signaturePredicate | defaultPredicate | signatureType)*
signaturePredicate ::= qldoc? annotations head ";"
defaultPredicate ::= qldoc? annotations "default" head "{" formula "}"
signatureType ::= qldoc? annotations "class" classname ("extends" type ("," type)*)? "{" signaturePredicate* "}"
A predicate signature definition extends the current module's declared predicate signature environment with a mapping from the predicate signature name and arity to the predicate signature definition.
A type signature definition extends the current module's declared type signature environment with a mapping from the type signature name to the type signature definition.
A module signature definition extends the current module's declared module signature environment with a mapping from the module signature name to the module signature definition.
Values
------
@@ -587,20 +628,21 @@ There are several kinds of identifiers:
- ``atLowerId``: an identifier that starts with an "@" sign and then a lower-case letter.
- ``atUpperId``: an identifier that starts with an "@" sign and then an upper-case letter.
Identifiers are used in following syntactic constructs:
::
simpleId ::= lowerId | upperId
modulename ::= simpleId
classname ::= upperId
dbasetype ::= atLowerId
predicateRef ::= (moduleId "::")? literalId
predicateName ::= lowerId
varname ::= lowerId
literalId ::= lowerId | atLowerId
simpleId ::= lowerId | upperId
modulename ::= simpleId
moduleSignatureName ::= upperId
classname ::= upperId
dbasetype ::= atLowerId
predicateRef ::= (moduleExpr "::")? literalId
signatureExpr ::= (moduleExpr "::")? simpleId ("/" Integer | arguments)?;
predicateName ::= lowerId
parameterName ::= simpleId
varname ::= lowerId
literalId ::= lowerId | atLowerId
Integer literals (int)
~~~~~~~~~~~~~~~~~~~~~~
@@ -1615,7 +1657,7 @@ Aliases define new names for existing QL entities.
alias ::= qldoc? annotations "predicate" literalId "=" predicateRef "/" int ";"
| qldoc? annotations "class" classname "=" type ";"
| qldoc? annotations "module" modulename "=" moduleId ";"
| qldoc? annotations "module" modulename "=" moduleExpr ";"
An alias introduces a binding from the new name to the entity referred to by the right-hand side in the current module's declared predicate, type, or module environment respectively.
@@ -2064,16 +2106,39 @@ The complete grammar for QL is as follows:
ql ::= qldoc? moduleBody
module ::= annotation* "module" modulename "{" moduleBody "}"
module ::= annotation* "module" modulename parameters? implements? "{" moduleBody "}"
parameters ::= "<" signatureExpr parameterName ("," signatureExpr parameterName)* ">"
implements ::= "implements" moduleSignatureExpr ("," moduleSignatureExpr)*
moduleBody ::= (import | predicate | class | module | alias | select)*
import ::= annotations "import" importModuleId ("as" modulename)?
import ::= annotations "import" importModuleExpr ("as" modulename)?
qualId ::= simpleId | qualId "." simpleId
importModuleId ::= qualId
| importModuleId "::" simpleId
importModuleExpr ::= qualId | importModuleExpr "::" modulename arguments?
arguments ::= "<" argument ("," argument)* ">"
argument ::= moduleExpr | type | predicateRef "/" int
signature ::= predicateSignature | typeSignature | moduleSignature
predicateSignature ::= qldoc? annotations "signature" head ";"
typeSignature ::= qldoc? annotations "signature" "class" classname ("extends" type ("," type)*)? (";" | "{" signaturePredicate* "}")
moduleSignature ::= qldoc? annotation* "signature" "module" moduleSignatureName parameters? "{" moduleSignatureBody "}"
moduleSignatureBody ::= (signaturePredicate | defaultPredicate | signatureType)*
signaturePredicate ::= qldoc? annotations head ";"
defaultPredicate ::= qldoc? annotations "default" head "{" formula "}"
signatureType ::= qldoc? annotations "class" classname ("extends" type ("," type)*)? "{" signaturePredicate* "}"
select ::= ("from" var_decls)? ("where" formula)? "select" as_exprs ("order" "by" orderbys)?
@@ -2120,15 +2185,19 @@ The complete grammar for QL is as follows:
field ::= qldoc? annotations var_decl ";"
moduleId ::= simpleId | moduleId "::" simpleId
moduleExpr ::= modulename arguments? | moduleExpr "::" modulename arguments?
type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string"
moduleSignatureExpr ::= (moduleExpr "::")? moduleSignatureName arguments?
signatureExpr : (moduleExpr "::")? simpleId ("/" Integer | arguments)?;
type ::= (moduleExpr "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string"
exprs ::= expr ("," expr)*
alias ::= qldoc? annotations "predicate" literalId "=" predicateRef "/" int ";"
| qldoc? annotations "class" classname "=" type ";"
| qldoc? annotations "module" modulename "=" moduleId ";"
| qldoc? annotations "module" modulename "=" moduleExpr ";"
var_decls ::= (var_decl ("," var_decl)*)?
@@ -2245,14 +2314,18 @@ The complete grammar for QL is as follows:
modulename ::= simpleId
moduleSignatureName ::= upperId
classname ::= upperId
dbasetype ::= atLowerId
predicateRef ::= (moduleId "::")? literalId
predicateRef ::= (moduleExpr "::")? literalId
predicateName ::= lowerId
parameterName ::= simpleId
varname ::= lowerId
literalId ::= lowerId | atLowerId | "any" | "none"

View File

@@ -4,7 +4,7 @@
:stub-columns: 1
Language,Variants,Compilers,Extensions
C/C++,"C89, C99, C11, C18, C++98, C++03, C++11, C++14, C++17, C++20 [1]_","Clang (and clang-cl [2]_) extensions (up to Clang 12.0),
C/C++,"C89, C99, C11, C17, C++98, C++03, C++11, C++14, C++17, C++20 [1]_","Clang (and clang-cl [2]_) extensions (up to Clang 12.0),
GNU extensions (up to GCC 11.1),

View File

@@ -113,9 +113,9 @@ ql/lib/go.dbscheme.stats: ql/lib/go.dbscheme build/stats/src.stamp extractor
test: all build/testdb/check-upgrade-path
codeql test run -j0 ql/test --search-path build/codeql-extractor-go --consistency-queries ql/test/consistency --compilation-cache=$(cache)
# use GOOS=linux because GOOS=darwin GOARCH=386 is no longer supported
# use GOOS=linux because GOOS=darwin GOARCH=386 is no longer supported
env GOOS=linux GOARCH=386 codeql$(EXE) test run -j0 ql/test/query-tests/Security/CWE-681 --search-path build/codeql-extractor-go --consistency-queries ql/test/consistency --compilation-cache=$(cache)
cd extractor; go test -mod=vendor ./... | grep -vF "[no test files]"
cd extractor; go test -mod=vendor ./...
bash extractor-smoke-test/test.sh || (echo "Extractor smoke test FAILED"; exit 1)
.PHONY: build/testdb/check-upgrade-path

View File

@@ -25,10 +25,8 @@ func usage() {
Options:
--identify-environment
Produce an environment file specifying which Go version should be installed in the environment
so that autobuilding will be successful. The location of this file is controlled by the
environment variable CODEQL_EXTRACTOR_ENVIRONMENT_JSON, or defaults to 'environment.json' if
that is not set.
Output some json on stdout specifying which Go version should be installed in the environment
so that autobuilding will be successful.
Build behavior:
@@ -745,8 +743,8 @@ func getVersionWhenGoModVersionNotFound(v versionInfo) (msg, version string) {
// There is no Go version installed in the environment. We have no indication which version
// was intended to be used to build this project. Go versions are generally backwards
// compatible, so we install the maximum supported version.
msg = "No version of Go installed and no `go.mod` file found. Writing an environment " +
"file specifying the maximum supported version of Go (" + maxGoVersion + ")."
msg = "No version of Go installed and no `go.mod` file found. Requesting the maximum " +
"supported version of Go (" + maxGoVersion + ")."
version = maxGoVersion
diagnostics.EmitNoGoModAndNoGoEnv(msg)
} else if outsideSupportedRange(v.goEnvVersion) {
@@ -928,39 +926,19 @@ func getVersionToInstall(v versionInfo) (msg, version string) {
return getVersionWhenGoModVersionSupported(v)
}
// Write an environment file to the current directory. If `version` is the empty string then
// write an empty environment file, otherwise write an environment file specifying the version
// of Go to install. The path to the environment file is specified by the
// CODEQL_EXTRACTOR_ENVIRONMENT_JSON environment variable, or defaults to `environment.json`.
func writeEnvironmentFile(version string) {
// Output some JSON to stdout specifying the version of Go to install, unless `version` is the
// empty string.
func outputEnvironmentJson(version string) {
var content string
if version == "" {
content = `{ "include": [] }`
} else {
content = `{ "include": [ { "go": { "version": "` + version + `" } } ] }`
}
_, err := fmt.Fprint(os.Stdout, content)
filename, ok := os.LookupEnv("CODEQL_EXTRACTOR_ENVIRONMENT_JSON")
if !ok {
filename = "environment.json"
}
targetFile, err := os.Create(filename)
if err != nil {
log.Println("Failed to create environment file " + filename + ": ")
log.Println(err)
return
}
defer func() {
if err := targetFile.Close(); err != nil {
log.Println("Failed to close environment file " + filename + ":")
log.Println(err)
}
}()
_, err = targetFile.WriteString(content)
if err != nil {
log.Println("Failed to write to environment file " + filename + ": ")
log.Println("Failed to write environment json to stdout: ")
log.Println(err)
}
}
@@ -984,7 +962,7 @@ func isGoInstalled() bool {
return err == nil
}
// Get the version of Go to install and write it to an environment file.
// Get the version of Go to install and output it to stdout as json.
func identifyEnvironment() {
var v versionInfo
depMode := getDepMode()
@@ -998,7 +976,7 @@ func identifyEnvironment() {
msg, versionToInstall := getVersionToInstall(v)
log.Println(msg)
writeEnvironmentFile(versionToInstall)
outputEnvironmentJson(versionToInstall)
}
func main() {

View File

@@ -36,45 +36,37 @@ func TestParseGoVersion(t *testing.T) {
func TestGetVersionToInstall(t *testing.T) {
tests := map[versionInfo]string{
// checkForUnsupportedVersions()
// go.mod version below minGoVersion
{"0.0", true, "1.20.3", true}: "",
{"0.0", true, "9999.0", true}: "",
{"0.0", true, "1.2.2", true}: "",
{"0.0", true, "", false}: "",
// go.mod version above maxGoVersion
{"9999.0", true, "1.20.3", true}: "",
{"9999.0", true, "9999.0.1", true}: "",
{"9999.0", true, "1.1", true}: "",
{"9999.0", true, "", false}: "",
// Go installation found with version below minGoVersion
{"1.20", true, "1.2.2", true}: "1.20",
{"1.11", true, "1.2.2", true}: "1.11",
// getVersionWhenGoModVersionNotFound()
{"", false, "", false}: maxGoVersion,
{"", false, "1.2.2", true}: maxGoVersion,
// Go installation found with version above maxGoVersion
{"", false, "9999.0.1", true}: maxGoVersion,
{"", false, "1.11.13", true}: "",
{"", false, "1.20.3", true}: "",
// getVersionWhenGoModVersionTooHigh()
{"9999.0", true, "", false}: maxGoVersion,
{"9999.0", true, "9999.0.1", true}: "",
{"9999.0", true, "1.1", true}: maxGoVersion,
{"9999.0", true, minGoVersion, false}: maxGoVersion,
{"9999.0", true, maxGoVersion, true}: "",
// getVersionWhenGoModVersionTooLow()
{"0.0", true, "", false}: minGoVersion,
{"0.0", true, "9999.0", true}: minGoVersion,
{"0.0", true, "1.2.2", true}: minGoVersion,
{"0.0", true, "1.20.3", true}: "",
// getVersionWhenGoModVersionSupported()
{"1.20", true, "", false}: "1.20",
{"1.11", true, "", false}: "1.11",
{"1.20", true, "1.2.2", true}: "1.20",
{"1.11", true, "1.2.2", true}: "1.11",
{"1.20", true, "9999.0.1", true}: "1.20",
{"1.11", true, "9999.0.1", true}: "1.11",
{"", false, "9999.0.1", true}: maxGoVersion,
// checkForVersionsNotFound()
// Go installation not found, go.mod version in supported range
{"1.20", true, "", false}: "1.20",
{"1.11", true, "", false}: "1.11",
// Go installation not found, go.mod not found
{"", false, "", false}: maxGoVersion,
// Go installation found with version in supported range, go.mod not found
{"", false, "1.11.13", true}: "",
{"", false, "1.20.3", true}: "",
// compareVersions()
// Go installation found with version in supported range, go.mod version in supported range and go.mod version > go installation version
// go.mod version > go installation version
{"1.20", true, "1.11.13", true}: "1.20",
{"1.20", true, "1.12", true}: "1.20",
// Go installation found with version in supported range, go.mod version in supported range and go.mod version <= go installation version
// (Note comparisons ignore the patch version)
// go.mod version <= go installation version (Note comparisons ignore the patch version)
{"1.11", true, "1.20", true}: "",
{"1.11", true, "1.20.3", true}: "",
{"1.20", true, "1.20.3", true}: "",

View File

@@ -35,7 +35,7 @@ module HeuristicNames {
*/
string maybePassword() {
result = "(?is).*pass(wd|word|code|phrase)(?!.*question).*" or
result = "(?is).*(auth(entication|ori[sz]ation)?)key.*"
result = "(?is).*(auth(entication|ori[sz]ation)?|api)key.*"
}
/**

View File

@@ -36,7 +36,10 @@ predicate escapes(DataFlow::Node nd) {
exists(SendStmt s | nd.asExpr() = s.getValue())
or
// if `nd` is passed to a function, then it escapes
nd instanceof DataFlow::ArgumentNode
nd = any(DataFlow::CallNode c).getASyntacticArgument()
or
// if `nd` is the receiver of a function, then it escapes
nd = any(DataFlow::MethodCallNode c).getReceiver()
or
// if `nd` has its address taken, then it escapes
exists(AddressExpr ae | nd.asExpr() = ae.getOperand())

View File

@@ -0,0 +1,8 @@
func bad() interface{} {
name := os.Args[1:]
// This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name)
db, _ := sql.Open("mysql", dbDSN)
return db
}

View File

@@ -0,0 +1,12 @@
func good() (interface{}, error) {
name := os.Args[1]
hasBadChar, _ := regexp.MatchString(".*[?].*", name)
if hasBadChar {
return nil, errors.New("Bad input")
}
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name)
db, _ := sql.Open("mysql", dbDSN)
return db, nil
}

View File

@@ -0,0 +1,38 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>If a Data-Source Name (DSN) is built using untrusted user input without proper sanitization,
the system may be vulnerable to DSN injection vulnerabilities.</p>
</overview>
<recommendation>
<p>If user input must be included in a DSN, additional steps should be taken to sanitize
untrusted data, such as checking for special characters included in user input.</p>
</recommendation>
<example>
<p>In the following examples, the code accepts the db name from the user,
which it then uses to build a DSN string.</p>
<p>The following example uses the unsanitized user input directly
in the process of constructing a DSN name.
A malicious user could provide special characters to change the meaning of this string, and
carry out unexpected database operations.</p>
<sample src="DsnBad.go" />
<p>In the following example, the input provided by the user is sanitized before it is included
in the DSN string.
This ensures the meaning of the DSN string cannot be changed by a malicious user.</p>
<sample src="DsnGood.go" />
</example>
<references>
<li>
CVE-2022-3023: <a href="https://nvd.nist.gov/vuln/detail/CVE-2022-3023/">Data Source Name Injection in pingcap/tidb.</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,22 @@
/**
* @name SQL Data-source URI built from user-controlled sources
* @description Building an SQL data-source URI from untrusted sources can allow attacker to compromise security
* @kind path-problem
* @problem.severity error
* @id go/dsn-injection
* @tags security
* experimental
* external/cwe/cwe-134
*/
import go
import DataFlow::PathGraph
import DsnInjectionCustomizations
/** An untrusted flow source taken as a source for the `DsnInjection` taint-flow configuration. */
private class UntrustedFlowAsSource extends Source instanceof UntrustedFlowSource { }
from DsnInjection cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "This query depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -0,0 +1,46 @@
/** Provides a taint-tracking model to reason about Data-Source name injection vulnerabilities. */
import go
import DataFlow::PathGraph
import semmle.go.dataflow.barrierguardutil.RegexpCheck
/** A source for `DsnInjection` taint-flow configuration. */
abstract class Source extends DataFlow::Node { }
/** A taint-tracking configuration to reason about Data Source Name injection vulnerabilities. */
class DsnInjection extends TaintTracking::Configuration {
DsnInjection() { this = "DsnInjection" }
override predicate isSource(DataFlow::Node node) { node instanceof Source }
override predicate isSink(DataFlow::Node node) {
exists(Function f | f.hasQualifiedName("database/sql", "Open") |
node = f.getACall().getArgument(1)
)
}
override predicate isSanitizer(DataFlow::Node node) { node instanceof RegexpCheckBarrier }
}
/** A model of a function which decodes or unmarshals a tainted input, propagating taint from any argument to either the method receiver or return value. */
private class DecodeFunctionModel extends TaintTracking::FunctionModel {
DecodeFunctionModel() {
// This matches any function with a name like `Decode`,`Unmarshal` or `Parse`.
// This is done to allow taints stored in encoded forms, such as in toml or json to flow freely.
this.getName().regexpMatch("(?i).*(parse|decode|unmarshal).*")
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(_) and
(output.isResult(0) or output.isReceiver())
}
}
/** A model of `flag.Parse`, propagating tainted input passed via CLI flags to `Parse`'s result. */
private class FlagSetFunctionModel extends TaintTracking::FunctionModel {
FlagSetFunctionModel() { this.hasQualifiedName("flag", "Parse") }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and output.isResult()
}
}

View File

@@ -0,0 +1,24 @@
/**
* @name SQL Data-source URI built from local user-controlled sources
* @description Building an SQL data-source URI from untrusted sources can allow attacker to compromise security
* @kind path-problem
* @problem.severity error
* @id go/dsn-injection-local
* @tags security
* experimental
* external/cwe/cwe-134
*/
import go
import DataFlow::PathGraph
import DsnInjectionCustomizations
/** An argument passed via the command line taken as a source for the `DsnInjection` taint-flow configuration. */
private class OsArgsSource extends Source {
OsArgsSource() { this = any(Variable c | c.hasQualifiedName("os", "Args")).getARead() }
}
from DsnInjection cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "This query depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -0,0 +1,36 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
Using a non-constant time comparision to compare sensitive information can lead to auth
vulnerabilities.
</p>
</overview>
<recommendation>
<p>Use of a constant time comparision function such as <code>crypto/subtle</code> package's <code>
ConstantTimeCompare</code> function can prevent this vulnerability. </p>
</recommendation>
<example>
<p>In the following examples, the code accepts a secret via a HTTP header in variable <code>
secretHeader</code> and a secret from the user in the <code>headerSecret</code> variable, which
are then compared with a system stored secret to perform authentication.</p>
<sample src="timingBad.go" />
<p>In the following example, the input provided by the user is compared using the <code>
ConstantTimeComapre</code> function. This ensures that timing attacks are not possible in this
case.</p>
<sample src="timingGood.go" />
</example>
<references>
<li>National Vulnerability Database: <a href="https://nvd.nist.gov/vuln/detail/CVE-2022-24912">
CVE-2022-24912</a>.</li>
<li>Verbose Logging:<a href="https://verboselogging.com/2012/08/20/a-timing-attack-in-action"> A
timing attack in action </a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,72 @@
/**
* @name Timing attacks due to comparison of sensitive secrets
* @description using a non-constant time comparison method to compare secrets can lead to authoriztion vulnerabilities
* @kind path-problem
* @problem.severity warning
* @id go/timing-attack
* @tags security
* experimental
* external/cwe/cwe-203
*/
import go
import DataFlow::PathGraph
import semmle.go.security.SensitiveActions
private predicate isBadResult(DataFlow::Node e) {
exists(string path | path = e.asExpr().getFile().getAbsolutePath().toLowerCase() |
path.matches(["%fake%", "%dummy%", "%test%", "%example%"]) and not path.matches("%ql/test%")
)
}
/**
* A data flow sink for timing attack vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
/** A taint-tracking sink which models comparisons of sensitive variables. */
private class SensitiveCompareSink extends Sink {
ComparisonExpr c;
SensitiveCompareSink() {
// We select a comparison where a secret or password is tested.
exists(SensitiveVariableAccess op1, Expr op2 |
op1.getClassification() = [SensitiveExpr::secret(), SensitiveExpr::password()] and
// exclude grant to avoid FP from OAuth
not op1.getClassification().matches("%grant%") and
op1 = c.getAnOperand() and
op2 = c.getAnOperand() and
not op1 = op2 and
not (
// Comparisons with `nil` should be excluded.
op2 = Builtin::nil().getAReference()
or
// Comparisons with empty string should also be excluded.
op2.getStringValue().length() = 0
)
|
// It is important to note that the name of both the operands need not be
// `sensitive`. Even if one of the operands appears to be sensitive, we consider it a potential sink.
c.getAnOperand() = this.asExpr()
)
}
DataFlow::Node getOtherOperand() { result.asExpr() = c.getAnOperand() and not result = this }
}
class SecretTracking extends TaintTracking::Configuration {
SecretTracking() { this = "SecretTracking" }
override predicate isSource(DataFlow::Node source) {
source instanceof UntrustedFlowSource and not isBadResult(source)
}
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink and not isBadResult(sink) }
}
from SecretTracking cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where
cfg.hasFlowPath(source, sink) and
not cfg.hasFlowTo(sink.getNode().(SensitiveCompareSink).getOtherOperand())
select sink.getNode(), source, sink, "$@ may be vulnerable to timing attacks.", source.getNode(),
"Hardcoded String"

View File

@@ -0,0 +1,11 @@
func bad(w http.ResponseWriter, req *http.Request, []byte secret) (interface{}, error) {
secretHeader := "X-Secret"
headerSecret := req.Header.Get(secretHeader)
secretStr := string(secret)
if len(secret) != 0 && headerSecret != secretStr {
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
}
return nil, nil
}

View File

@@ -0,0 +1,10 @@
func good(w http.ResponseWriter, req *http.Request, []byte secret) (interface{}, error) {
secretHeader := "X-Secret"
headerSecret := req.Header.Get(secretHeader)
if len(secret) != 0 && subtle.ConstantTimeCompare(secret, []byte(headerSecret)) != 1 {
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
}
return nil, nil
}

View File

@@ -78,7 +78,7 @@ class InlineFlowTest extends InlineExpectationsTest {
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasValueFlow" and
exists(DataFlow::Node sink | getValueFlowConfig().hasFlowTo(sink) |
exists(DataFlow::Node sink | this.getValueFlowConfig().hasFlowTo(sink) |
sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and
element = sink.toString() and
@@ -87,7 +87,8 @@ class InlineFlowTest extends InlineExpectationsTest {
or
tag = "hasTaintFlow" and
exists(DataFlow::Node src, DataFlow::Node sink |
getTaintFlowConfig().hasFlow(src, sink) and not getValueFlowConfig().hasFlow(src, sink)
this.getTaintFlowConfig().hasFlow(src, sink) and
not this.getValueFlowConfig().hasFlow(src, sink)
|
sink.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and

View File

@@ -0,0 +1,77 @@
package main
import (
"database/sql"
"errors"
"fmt"
"net/http"
"os"
"regexp"
)
func good() (interface{}, error) {
name := os.Args[1]
hasBadChar, _ := regexp.MatchString(".*[?].*", name)
if hasBadChar {
return nil, errors.New("bad input")
}
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name)
db, _ := sql.Open("mysql", dbDSN)
return db, nil
}
func bad() interface{} {
name2 := os.Args[1:]
// This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name2[0])
db, _ := sql.Open("mysql", dbDSN)
return db
}
func good2(w http.ResponseWriter, req *http.Request) (interface{}, error) {
name := req.FormValue("name")
hasBadChar, _ := regexp.MatchString(".*[?].*", name)
if hasBadChar {
return nil, errors.New("bad input")
}
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name)
db, _ := sql.Open("mysql", dbDSN)
return db, nil
}
func bad2(w http.ResponseWriter, req *http.Request) interface{} {
name := req.FormValue("name")
// This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, name)
db, _ := sql.Open("mysql", dbDSN)
return db
}
type Config struct {
dsn string
}
func NewConfig() *Config { return &Config{dsn: ""} }
func (Config) Parse([]string) error { return nil }
func RegexFuncModelTest(w http.ResponseWriter, req *http.Request) (interface{}, error) {
cfg := NewConfig()
err := cfg.Parse(os.Args[1:]) // This is bad. `name` can be something like `test?allowAllFiles=true&` which will allow an attacker to access local files.
if err != nil {
return nil, err
}
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", "username", "password", "127.0.0.1", 3306, cfg.dsn)
db, _ := sql.Open("mysql", dbDSN)
return db, nil
}
func main() {
bad2(nil, nil)
good()
bad()
good2(nil, nil)
}

View File

@@ -0,0 +1,8 @@
edges
| Dsn.go:47:10:47:30 | call to FormValue | Dsn.go:50:29:50:33 | dbDSN |
nodes
| Dsn.go:47:10:47:30 | call to FormValue | semmle.label | call to FormValue |
| Dsn.go:50:29:50:33 | dbDSN | semmle.label | dbDSN |
subpaths
#select
| Dsn.go:50:29:50:33 | dbDSN | Dsn.go:47:10:47:30 | call to FormValue | Dsn.go:50:29:50:33 | dbDSN | This query depends on a $@. | Dsn.go:47:10:47:30 | call to FormValue | user-provided value |

View File

@@ -0,0 +1 @@
experimental/CWE-134/DsnInjection.ql

View File

@@ -0,0 +1,27 @@
edges
| Dsn.go:26:11:26:17 | selection of Args | Dsn.go:29:29:29:33 | dbDSN |
| Dsn.go:62:2:62:4 | definition of cfg [pointer] | Dsn.go:63:9:63:11 | cfg [pointer] |
| Dsn.go:62:2:62:4 | definition of cfg [pointer] | Dsn.go:67:102:67:104 | cfg [pointer] |
| Dsn.go:63:9:63:11 | cfg [pointer] | Dsn.go:63:9:63:11 | implicit dereference |
| Dsn.go:63:9:63:11 | implicit dereference | Dsn.go:62:2:62:4 | definition of cfg [pointer] |
| Dsn.go:63:9:63:11 | implicit dereference | Dsn.go:63:9:63:11 | implicit dereference |
| Dsn.go:63:9:63:11 | implicit dereference | Dsn.go:68:29:68:33 | dbDSN |
| Dsn.go:63:19:63:25 | selection of Args | Dsn.go:63:9:63:11 | implicit dereference |
| Dsn.go:63:19:63:25 | selection of Args | Dsn.go:68:29:68:33 | dbDSN |
| Dsn.go:67:102:67:104 | cfg [pointer] | Dsn.go:67:102:67:104 | implicit dereference |
| Dsn.go:67:102:67:104 | implicit dereference | Dsn.go:63:9:63:11 | implicit dereference |
| Dsn.go:67:102:67:104 | implicit dereference | Dsn.go:68:29:68:33 | dbDSN |
nodes
| Dsn.go:26:11:26:17 | selection of Args | semmle.label | selection of Args |
| Dsn.go:29:29:29:33 | dbDSN | semmle.label | dbDSN |
| Dsn.go:62:2:62:4 | definition of cfg [pointer] | semmle.label | definition of cfg [pointer] |
| Dsn.go:63:9:63:11 | cfg [pointer] | semmle.label | cfg [pointer] |
| Dsn.go:63:9:63:11 | implicit dereference | semmle.label | implicit dereference |
| Dsn.go:63:19:63:25 | selection of Args | semmle.label | selection of Args |
| Dsn.go:67:102:67:104 | cfg [pointer] | semmle.label | cfg [pointer] |
| Dsn.go:67:102:67:104 | implicit dereference | semmle.label | implicit dereference |
| Dsn.go:68:29:68:33 | dbDSN | semmle.label | dbDSN |
subpaths
#select
| Dsn.go:29:29:29:33 | dbDSN | Dsn.go:26:11:26:17 | selection of Args | Dsn.go:29:29:29:33 | dbDSN | This query depends on a $@. | Dsn.go:26:11:26:17 | selection of Args | user-provided value |
| Dsn.go:68:29:68:33 | dbDSN | Dsn.go:63:19:63:25 | selection of Args | Dsn.go:68:29:68:33 | dbDSN | This query depends on a $@. | Dsn.go:63:19:63:25 | selection of Args | user-provided value |

View File

@@ -0,0 +1 @@
experimental/CWE-134/DsnInjectionLocal.ql

View File

@@ -0,0 +1,10 @@
edges
| timing.go:14:18:14:27 | selection of Header | timing.go:14:18:14:45 | call to Get |
| timing.go:14:18:14:45 | call to Get | timing.go:16:25:16:36 | headerSecret |
nodes
| timing.go:14:18:14:27 | selection of Header | semmle.label | selection of Header |
| timing.go:14:18:14:45 | call to Get | semmle.label | call to Get |
| timing.go:16:25:16:36 | headerSecret | semmle.label | headerSecret |
subpaths
#select
| timing.go:16:25:16:36 | headerSecret | timing.go:14:18:14:27 | selection of Header | timing.go:16:25:16:36 | headerSecret | $@ may be vulnerable to timing attacks. | timing.go:14:18:14:27 | selection of Header | Hardcoded String |

View File

@@ -0,0 +1 @@
experimental/CWE-203/Timing.ql

View File

@@ -0,0 +1,37 @@
package main
import (
"crypto/subtle"
"fmt"
"net/http"
)
func bad(w http.ResponseWriter, req *http.Request) (interface{}, error) {
secret := "MySuperSecretPasscode"
secretHeader := "X-Secret"
headerSecret := req.Header.Get(secretHeader)
secretStr := string(secret)
if len(secret) != 0 && headerSecret != secretStr {
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
}
return nil, nil
}
func good(w http.ResponseWriter, req *http.Request) (interface{}, error) {
secret := []byte("MySuperSecretPasscode")
secretHeader := "X-Secret"
headerSecret := req.Header.Get(secretHeader)
if len(secret) != 0 && subtle.ConstantTimeCompare(secret, []byte(headerSecret)) != 1 {
return nil, fmt.Errorf("header %s=%s did not match expected secret", secretHeader, headerSecret)
}
return nil, nil
}
func main() {
bad(nil, nil)
good(nil, nil)
}

View File

@@ -92,6 +92,7 @@ org.apache.commons.net,9,12,,,,,,,,,,,,,,,,6,,3,,,,,,,,,,,,,,,,,,,12,,
org.apache.commons.ognl,6,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,
org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,220,52
org.apache.directory.ldap.client.api,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,
org.apache.hadoop.fs,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,
org.apache.hadoop.hive.metastore,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,,,,,
org.apache.hc.client5.http.async.methods,84,,,,,,,,,,,,,,,,,84,,,,,,,,,,,,,,,,,,,,,,,
org.apache.hc.client5.http.classic.methods,37,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,,,,,,,,,,
@@ -133,7 +134,7 @@ org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13
org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
org.springframework.data.repository,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1
org.springframework.http,14,,71,,,,,,,,,,,,,,,14,,,,,,,,,,,,,,,,,,,,,,61,10
org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,,
org.springframework.jdbc.core,19,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,,,,,,,,,,,,
org.springframework.jdbc.datasource,4,,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,
org.springframework.jndi,1,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1 package sink source summary sink:bean-validation sink:create-file sink:fragment-injection sink:groovy sink:header-splitting sink:information-leak sink:intent-start sink:jdbc-url sink:jexl sink:jndi-injection sink:ldap sink:logging sink:mvel sink:ognl-injection sink:open-url sink:pending-intent-sent sink:read-file sink:regex-use sink:regex-use[-1] sink:regex-use[0] sink:regex-use[] sink:regex-use[f-1] sink:regex-use[f1] sink:regex-use[f] sink:set-hostname-verifier sink:sql sink:ssti sink:url-redirect sink:write-file sink:xpath sink:xslt sink:xss source:android-external-storage-dir source:android-widget source:contentprovider source:remote summary:taint summary:value
92 org.apache.commons.ognl 6 6
93 org.apache.commons.text 272 220 52
94 org.apache.directory.ldap.client.api 1 1
95 org.apache.hadoop.fs 10 10
96 org.apache.hadoop.hive.metastore 3 3
97 org.apache.hc.client5.http.async.methods 84 84
98 org.apache.hc.client5.http.classic.methods 37 37
134 org.springframework.context 3 3
135 org.springframework.data.repository 1 1
136 org.springframework.http 14 71 14 61 10
137 org.springframework.jdbc.core 10 19 10 19
138 org.springframework.jdbc.datasource 4 4
139 org.springframework.jdbc.object 9 9
140 org.springframework.jndi 1 1

View File

@@ -21,7 +21,7 @@ Java framework & library support
Java Standard Library,``java.*``,3,679,168,39,,9,,,13
Java extensions,"``javax.*``, ``jakarta.*``",63,611,34,1,4,,1,1,2
Kotlin Standard Library,``kotlin*``,,1843,16,11,,,,,2
`Spring <https://spring.io/>`_,``org.springframework.*``,29,483,104,2,,19,14,,29
Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.hubspot.jinjava``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.thoughtworks.xstream``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.util``, ``hudson``, ``io.jsonwebtoken``, ``io.netty.bootstrap``, ``io.netty.buffer``, ``io.netty.channel``, ``io.netty.handler.codec``, ``io.netty.handler.ssl``, ``io.netty.handler.stream``, ``io.netty.resolver``, ``io.netty.util``, ``javafx.scene.web``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.net``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.cargo.container.installer``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.eclipse.jetty.client``, ``org.geogebra.web.full.main``, ``org.hibernate``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.kohsuke.stapler``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",89,817,515,26,,18,18,,181
Totals,,246,9109,1957,174,10,113,33,1,361
`Spring <https://spring.io/>`_,``org.springframework.*``,29,483,113,2,,28,14,,29
Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.hubspot.jinjava``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.thoughtworks.xstream``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.util``, ``hudson``, ``io.jsonwebtoken``, ``io.netty.bootstrap``, ``io.netty.buffer``, ``io.netty.channel``, ``io.netty.handler.codec``, ``io.netty.handler.ssl``, ``io.netty.handler.stream``, ``io.netty.resolver``, ``io.netty.util``, ``javafx.scene.web``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.net``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.fs``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.cargo.container.installer``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.eclipse.jetty.client``, ``org.geogebra.web.full.main``, ``org.hibernate``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.kohsuke.stapler``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",89,827,515,26,,18,18,,181
Totals,,246,9119,1966,174,10,122,33,1,361

View File

@@ -50,13 +50,9 @@ import com.semmle.util.trap.dependencies.TrapSet;
import com.semmle.util.trap.pathtransformers.PathTransformer;
public class OdasaOutput {
// either these are set ...
private final File trapFolder;
private final File sourceArchiveFolder;
// ... or this one is set
private final PopulationSpecFile specFile;
private File currentSourceFile;
private TrapSet trapsCreated;
private TrapDependencies trapDependenciesForSource;
@@ -72,29 +68,21 @@ public class OdasaOutput {
OdasaOutput(File outputRoot, Logger log) {
this.trapFolder = new File(outputRoot, "trap");
this.sourceArchiveFolder = new File(outputRoot, "src_archive");
this.specFile = null;
this.trackClassOrigins = false;
this.log = log;
}
public OdasaOutput(boolean trackClassOrigins, Logger log) {
String trapFolderVar = Env.systemEnv().getFirstNonEmpty("CODEQL_EXTRACTOR_JAVA_TRAP_DIR", Var.TRAP_FOLDER.name());
if (trapFolderVar != null) {
String sourceArchiveVar = Env.systemEnv().getFirstNonEmpty("CODEQL_EXTRACTOR_JAVA_SOURCE_ARCHIVE_DIR", Var.SOURCE_ARCHIVE.name());
if (sourceArchiveVar == null)
throw new ResourceError(Var.TRAP_FOLDER + " was set to '" + trapFolderVar + "', but "
+ Var.SOURCE_ARCHIVE + " was not set");
this.trapFolder = new File(trapFolderVar);
this.sourceArchiveFolder = new File(sourceArchiveVar);
this.specFile = null;
} else {
this.trapFolder = null;
this.sourceArchiveFolder = null;
String specFileVar = Env.systemEnv().get(Var.ODASA_JAVA_LAYOUT);
if (specFileVar == null)
throw new ResourceError("Neither " + Var.TRAP_FOLDER + " nor " + Var.ODASA_JAVA_LAYOUT + " was set");
this.specFile = new PopulationSpecFile(new File(specFileVar));
if (trapFolderVar == null) {
throw new ResourceError("CODEQL_EXTRACTOR_JAVA_TRAP_DIR was not set");
}
String sourceArchiveVar = Env.systemEnv().getFirstNonEmpty("CODEQL_EXTRACTOR_JAVA_SOURCE_ARCHIVE_DIR", Var.SOURCE_ARCHIVE.name());
if (sourceArchiveVar == null) {
throw new ResourceError("CODEQL_EXTRACTOR_JAVA_SOURCE_ARCHIVE_DIR was not set");
}
this.trapFolder = new File(trapFolderVar);
this.sourceArchiveFolder = new File(sourceArchiveVar);
this.trackClassOrigins = trackClassOrigins;
this.log = log;
}
@@ -123,11 +111,8 @@ public class OdasaOutput {
/** The output paths for that file, or null if it shouldn't be included */
private SpecFileEntry entryFor() {
if (specFile != null)
return specFile.getEntryFor(currentSourceFile);
else
return new SpecFileEntry(trapFolder, sourceArchiveFolder,
Arrays.asList(PathTransformer.std().fileAsDatabaseString(currentSourceFile)));
return new SpecFileEntry(trapFolder, sourceArchiveFolder,
Arrays.asList(PathTransformer.std().fileAsDatabaseString(currentSourceFile)));
}
/*

View File

@@ -239,8 +239,6 @@ open class KotlinUsesExtractor(
return UseClassInstanceResult(classTypeResult, extractClass)
}
private fun isArray(t: IrSimpleType) = t.isBoxedArray || t.isPrimitiveArray()
private fun extractClassLaterIfExternal(c: IrClass) {
if (isExternalDeclaration(c)) {
extractExternalClassLater(c)
@@ -551,6 +549,22 @@ open class KotlinUsesExtractor(
)
}
/*
Kotlin arrays can be broken down as:
isArray(t)
|- t.isBoxedArray
| |- t.isArray() e.g. Array<Boolean>, Array<Boolean?>
| |- t.isNullableArray() e.g. Array<Boolean>?, Array<Boolean?>?
|- t.isPrimitiveArray() e.g. BooleanArray
For the corresponding Java types:
Boxed arrays are represented as e.g. java.lang.Boolean[].
Primitive arrays are represented as e.g. boolean[].
*/
private fun isArray(t: IrType) = t.isBoxedArray || t.isPrimitiveArray()
data class ArrayInfo(val elementTypeResults: TypeResults,
val componentTypeResults: TypeResults,
val dimensions: Int)
@@ -565,7 +579,7 @@ open class KotlinUsesExtractor(
*/
private fun useArrayType(t: IrType, isPrimitiveArray: Boolean): ArrayInfo {
if (!t.isBoxedArray && !t.isPrimitiveArray()) {
if (!isArray(t)) {
val nullableT = if (t.isPrimitiveType() && !isPrimitiveArray) t.makeNullable() else t
val typeResults = useType(nullableT)
return ArrayInfo(typeResults, typeResults, 0)
@@ -1141,13 +1155,13 @@ open class KotlinUsesExtractor(
}
} else {
t.classOrNull?.let { tCls ->
if (t.isArray() || t.isNullableArray()) {
if (t.isBoxedArray) {
(t.arguments.singleOrNull() as? IrTypeProjection)?.let { elementTypeArg ->
val elementType = elementTypeArg.type
val replacedElementType = kClassToJavaClass(elementType)
if (replacedElementType !== elementType) {
val newArg = makeTypeProjection(replacedElementType, elementTypeArg.variance)
return tCls.typeWithArguments(listOf(newArg)).codeQlWithHasQuestionMark(t.isNullableArray())
return tCls.typeWithArguments(listOf(newArg)).codeQlWithHasQuestionMark(t.isNullable())
}
}
}
@@ -1578,7 +1592,7 @@ open class KotlinUsesExtractor(
}
if (owner is IrClass) {
if (t.isArray() || t.isNullableArray()) {
if (t.isBoxedArray) {
val elementType = t.getArrayElementType(pluginContext.irBuiltIns)
val erasedElementType = erase(elementType)
return owner.typeWith(erasedElementType).codeQlWithHasQuestionMark(t.isNullable())

View File

@@ -8,6 +8,17 @@ if "JAVA_HOME_8_X64" in os.environ:
sep = ";" if platform.system() == "Windows" else ":"
os.environ["PATH"] = "".join([os.path.join(os.environ["JAVA_HOME"], "bin"), sep, os.environ["PATH"]])
run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None)
# Ensure the autobuilder *doesn't* see Java 11 or 17, which it could switch to in order to build the project:
for k in ["JAVA_HOME_11_X64", "JAVA_HOME_17_X64"]:
if k in os.environ:
del os.environ[k]
# Use a custom, empty toolchains.xml file so the autobuilder doesn't see any Java versions that may be
# in a system-level toolchains file
toolchains_path = os.path.join(os.getcwd(), 'toolchains.xml')
run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None, extra_env={
'LGTM_INDEX_MAVEN_TOOLCHAINS_FILE': toolchains_path
})
check_diagnostics()

View File

@@ -0,0 +1,5 @@
<?xml version="1.0"?>
<toolchains xmlns="https://maven.apache.org/TOOLCHAINS/1.1.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/TOOLCHAINS/1.1.0 https://maven.apache.org/xsd/toolchains-1.1.0.xsd">
</toolchains>

View File

@@ -2,6 +2,10 @@
### Minor Analysis Improvements
* Added SQL injection sinks for Spring JDBC's `NamedParameterJdbcOperations`.
* Added models for the following packages:
* org.apache.hadoop.fs
* Added the `ArithmeticCommon.qll` library to provide predicates for reasoning about arithmetic operations.
* Added the `ArithmeticTaintedLocalQuery.qll` library to provide the `ArithmeticTaintedLocalOverflowFlow` and `ArithmeticTaintedLocalUnderflowFlow` taint-tracking modules to reason about arithmetic with unvalidated user input.
* Added the `ArithmeticTaintedQuery.qll` library to provide the `RemoteUserInputOverflow` and `RemoteUserInputUnderflow` taint-tracking modules to reason about arithmetic with unvalidated user input.

View File

@@ -2,6 +2,10 @@
### Minor Analysis Improvements
* Added SQL injection sinks for Spring JDBC's `NamedParameterJdbcOperations`.
* Added models for the following packages:
* org.apache.hadoop.fs
* Added the `ArithmeticCommon.qll` library to provide predicates for reasoning about arithmetic operations.
* Added the `ArithmeticTaintedLocalQuery.qll` library to provide the `ArithmeticTaintedLocalOverflowFlow` and `ArithmeticTaintedLocalUnderflowFlow` taint-tracking modules to reason about arithmetic with unvalidated user input.
* Added the `ArithmeticTaintedQuery.qll` library to provide the `RemoteUserInputOverflow` and `RemoteUserInputUnderflow` taint-tracking modules to reason about arithmetic with unvalidated user input.

View File

@@ -29,3 +29,4 @@ extensions:
- ["groovy.lang", "GroovyShell", False, "run", "(String,String,String[])", "", "Argument[0]", "groovy", "manual"]
- ["groovy.lang", "GroovyShell", False, "run", "(URI,List)", "", "Argument[0]", "groovy", "manual"]
- ["groovy.lang", "GroovyShell", False, "run", "(URI,String[])", "", "Argument[0]", "groovy", "manual"]
- ["groovy.text", "TemplateEngine", True, "createTemplate", "", "", "Argument[0]", "groovy", "manual"]

View File

@@ -0,0 +1,15 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: summaryModel
data:
- ["org.apache.hadoop.fs", "Path", True, "Path", "(Path,Path)", "", "Argument[0]", "Argument[this]", "taint", "ai-manual"]
- ["org.apache.hadoop.fs", "Path", True, "Path", "(Path,Path)", "", "Argument[1]", "Argument[this]", "taint", "ai-manual"]
- ["org.apache.hadoop.fs", "Path", True, "Path", "(Path,String)", "", "Argument[0]", "Argument[this]", "taint", "ai-manual"]
- ["org.apache.hadoop.fs", "Path", True, "Path", "(Path,String)", "", "Argument[1]", "Argument[this]", "taint", "ai-manual"]
- ["org.apache.hadoop.fs", "Path", True, "Path", "(String,String,String)", "", "Argument[1]", "Argument[this]", "taint", "ai-manual"]
- ["org.apache.hadoop.fs", "Path", True, "Path", "(String,String,String)", "", "Argument[2]", "Argument[this]", "taint", "ai-manual"]
- ["org.apache.hadoop.fs", "Path", True, "Path", "(String,String)", "", "Argument[0]", "Argument[this]", "taint", "ai-manual"]
- ["org.apache.hadoop.fs", "Path", True, "Path", "(String,String)", "", "Argument[1]", "Argument[this]", "taint", "ai-manual"]
- ["org.apache.hadoop.fs", "Path", True, "Path", "(String)", "", "Argument[0]", "Argument[this]", "taint", "ai-manual"]
- ["org.apache.hadoop.fs", "Path", True, "Path", "(URI)", "", "Argument[0]", "Argument[this]", "taint", "ai-manual"]

View File

@@ -0,0 +1,14 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: sinkModel
data:
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "batchUpdate", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "execute", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "query", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "queryForList", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "queryForMap", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "queryForObject", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "queryForRowSet", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "queryForStream", "", "", "Argument[0]", "sql", "manual"]
- ["org.springframework.jdbc.core.namedparam", "NamedParameterJdbcOperations", True, "update", "", "", "Argument[0]", "sql", "manual"]

View File

@@ -104,6 +104,17 @@ private predicate constantBooleanExpr(Expr e, boolean val) {
CalcConstants::calculateBooleanValue(e) = val
}
pragma[nomagic]
private predicate constantStringExpr(Expr e, string val) {
e.(CompileTimeConstantExpr).getStringValue() = val
or
exists(SsaExplicitUpdate v, Expr src |
e = v.getAUse() and
src = v.getDefiningExpr().(VariableAssign).getSource() and
constantStringExpr(src, val)
)
}
private boolean getBoolValue(Expr e) { constantBooleanExpr(e, result) }
private int getIntValue(Expr e) { constantIntegerExpr(e, result) }
@@ -126,6 +137,14 @@ class ConstantBooleanExpr extends Expr {
boolean getBooleanValue() { constantBooleanExpr(this, result) }
}
/** An expression that always has the same string value. */
class ConstantStringExpr extends Expr {
ConstantStringExpr() { constantStringExpr(this, _) }
/** Get the string value of this expression. */
string getStringValue() { constantStringExpr(this, result) }
}
/**
* Gets an expression that equals `v - d`.
*/

View File

@@ -27,8 +27,8 @@ deprecated class CamelToURI = CamelToUri;
class CamelToBeanUri extends CamelToUri {
CamelToBeanUri() {
// A `<to>` element references a bean if the URI starts with "bean:", or there is no scheme.
matches("bean:%") or
not exists(indexOf(":"))
this.matches("bean:%") or
not exists(this.indexOf(":"))
}
/**
@@ -38,13 +38,13 @@ class CamelToBeanUri extends CamelToUri {
* parameter parts are optional.
*/
string getBeanIdentifier() {
if not exists(indexOf(":"))
if not exists(this.indexOf(":"))
then result = this
else
exists(int start | start = indexOf(":", 0, 0) + 1 |
if not exists(indexOf("?"))
then result = suffix(start)
else result = substring(start, indexOf("?", 0, 0))
exists(int start | start = this.indexOf(":", 0, 0) + 1 |
if not exists(this.indexOf("?"))
then result = this.suffix(start)
else result = this.substring(start, this.indexOf("?", 0, 0))
)
}

View File

@@ -0,0 +1,90 @@
/** Provides XML definitions related to the `org.apache.commons` package. */
import java
private import semmle.code.java.dataflow.RangeUtils
private import semmle.code.java.security.XmlParsers
/**
* The classes `org.apache.commons.digester3.Digester`, `org.apache.commons.digester.Digester` or `org.apache.tomcat.util.digester.Digester`.
*/
private class Digester extends RefType {
Digester() {
this.hasQualifiedName([
"org.apache.commons.digester3", "org.apache.commons.digester",
"org.apache.tomcat.util.digester"
], "Digester")
}
}
/** A call to `Digester.parse`. */
private class DigesterParse extends XmlParserCall {
DigesterParse() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof Digester and
m.hasName("parse")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { SafeDigesterFlow::flowToExpr(this.getQualifier()) }
}
/** A `ParserConfig` that is specific to `Digester`. */
private class DigesterConfig extends ParserConfig {
DigesterConfig() {
exists(Method m |
m = this.getMethod() and
m.getDeclaringType() instanceof Digester and
m.hasName("setFeature")
)
}
}
/**
* A safely configured `Digester`.
*/
private class SafeDigester extends VarAccess {
SafeDigester() {
exists(Variable v | v = this.getVariable() |
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config.enables(singleSafeConfig())
)
or
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-general-entities"
))
) and
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() = "http://xml.org/sax/features/external-parameter-entities"
))
) and
exists(DigesterConfig config | config.getQualifier() = v.getAnAccess() |
config
.disables(any(ConstantStringExpr s |
s.getStringValue() =
"http://apache.org/xml/features/nonvalidating/load-external-dtd"
))
)
)
}
}
private module SafeDigesterFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeDigester }
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and ma.getMethod().getDeclaringType() instanceof Digester
)
}
int fieldFlowBranchLimit() { result = 0 }
}
private module SafeDigesterFlow = DataFlow::Global<SafeDigesterFlowConfig>;

View File

@@ -0,0 +1,64 @@
/** Provides definitions related to the `javax.xml` package. */
import java
private import semmle.code.java.security.XmlParsers
/** A call to `Validator.validate`. */
private class ValidatorValidate extends XmlParserCall {
ValidatorValidate() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof Validator and
m.hasName("validate")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { SafeValidatorFlow::flowToExpr(this.getQualifier()) }
}
/** A `TransformerConfig` specific to `Validator`. */
private class ValidatorConfig extends TransformerConfig {
ValidatorConfig() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof Validator and
m.hasName("setProperty")
)
}
}
/** The class `javax.xml.validation.Validator`. */
private class Validator extends RefType {
Validator() { this.hasQualifiedName("javax.xml.validation", "Validator") }
}
/** A safely configured `Validator`. */
private class SafeValidator extends VarAccess {
SafeValidator() {
exists(Variable v | v = this.getVariable() |
exists(ValidatorConfig config | config.getQualifier() = v.getAnAccess() |
config.disables(configAccessExternalDtd())
) and
exists(ValidatorConfig config | config.getQualifier() = v.getAnAccess() |
config.disables(configAccessExternalSchema())
)
)
}
}
private module SafeValidatorFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeValidator }
predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
sink.asExpr() = ma.getQualifier() and
ma.getMethod().getDeclaringType() instanceof Validator
)
}
int fieldFlowBranchLimit() { result = 0 }
}
private module SafeValidatorFlow = DataFlow::Global<SafeValidatorFlowConfig>;

View File

@@ -0,0 +1,24 @@
/** Provides definitions related to the `java.beans` package. */
import java
private import semmle.code.java.security.XmlParsers
/** The class `java.beans.XMLDecoder`. */
private class XmlDecoder extends RefType {
XmlDecoder() { this.hasQualifiedName("java.beans", "XMLDecoder") }
}
/** A call to `XMLDecoder.readObject`. */
private class XmlDecoderReadObject extends XmlParserCall {
XmlDecoderReadObject() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType() instanceof XmlDecoder and
m.hasName("readObject")
)
}
override Expr getSink() { result = this.getQualifier() }
override predicate isSafe() { none() }
}

View File

@@ -0,0 +1,19 @@
/** Provides definitions related to XML parsing in Rundeck. */
import java
private import semmle.code.java.security.XmlParsers
/** A call to `ParserHelper.loadDocument`. */
private class ParserHelperLoadDocument extends XmlParserCall {
ParserHelperLoadDocument() {
exists(Method m |
this.getMethod() = m and
m.getDeclaringType().hasQualifiedName("org.rundeck.api.parser", "ParserHelper") and
m.hasName("loadDocument")
)
}
override Expr getSink() { result = this.getArgument(0) }
override predicate isSafe() { none() }
}

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