mirror of
https://github.com/github/codeql.git
synced 2026-04-29 02:35:15 +02:00
Merge branch 'main' into scinit
This commit is contained in:
7
.bazelrc
7
.bazelrc
@@ -30,6 +30,13 @@ common --registry=https://bcr.bazel.build
|
||||
|
||||
common --@rules_dotnet//dotnet/settings:strict_deps=false
|
||||
|
||||
# we only configure a nightly toolchain
|
||||
common --@rules_rust//rust/toolchain/channel=nightly
|
||||
|
||||
# rust does not like the gold linker, while bazel does by default, so let's avoid using it
|
||||
common:linux --linkopt=-fuse-ld=lld
|
||||
common:macos --linkopt=-fuse-ld=lld
|
||||
|
||||
# Reduce this eventually to empty, once we've fixed all our usages of java, and https://github.com/bazel-contrib/rules_go/issues/4193 is fixed
|
||||
common --incompatible_autoload_externally="+@rules_java,+@rules_shell"
|
||||
|
||||
|
||||
51
MODULE.bazel
51
MODULE.bazel
@@ -15,7 +15,7 @@ local_path_override(
|
||||
# see https://registry.bazel.build/ for a list of available packages
|
||||
|
||||
bazel_dep(name = "platforms", version = "0.0.11")
|
||||
bazel_dep(name = "rules_go", version = "0.50.1")
|
||||
bazel_dep(name = "rules_go", version = "0.56.1")
|
||||
bazel_dep(name = "rules_pkg", version = "1.0.1")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.2.0-codeql.1")
|
||||
bazel_dep(name = "rules_python", version = "0.40.0")
|
||||
@@ -28,7 +28,7 @@ bazel_dep(name = "rules_kotlin", version = "2.1.3-codeql.1")
|
||||
bazel_dep(name = "gazelle", version = "0.40.0")
|
||||
bazel_dep(name = "rules_dotnet", version = "0.17.4")
|
||||
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
|
||||
bazel_dep(name = "rules_rust", version = "0.58.0")
|
||||
bazel_dep(name = "rules_rust", version = "0.63.0")
|
||||
bazel_dep(name = "zstd", version = "1.5.5.bcr.1")
|
||||
|
||||
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
|
||||
@@ -38,7 +38,10 @@ bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True
|
||||
RUST_EDITION = "2024"
|
||||
|
||||
# run buildutils-internal/scripts/fill-rust-sha256s.py when updating (internal repo)
|
||||
RUST_VERSION = "1.86.0"
|
||||
# a nightly toolchain is required to enable experimental_use_cc_common_link, which we require internally
|
||||
# we prefer to run the same version as internally, even if experimental_use_cc_common_link is not really
|
||||
# required in this repo
|
||||
RUST_VERSION = "nightly/2025-08-01"
|
||||
|
||||
rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")
|
||||
rust.toolchain(
|
||||
@@ -50,26 +53,26 @@ rust.toolchain(
|
||||
],
|
||||
# generated by buildutils-internal/scripts/fill-rust-sha256s.py (internal repo)
|
||||
sha256s = {
|
||||
"rustc-1.86.0-x86_64-unknown-linux-gnu.tar.xz": "4438b809ce4a083af31ed17aeeedcc8fc60ccffc0625bef1926620751b6989d7",
|
||||
"rustc-1.86.0-x86_64-apple-darwin.tar.xz": "42b76253626febb7912541a30d3379f463dec89581aad4cb72c6c04fb5a71dc5",
|
||||
"rustc-1.86.0-aarch64-apple-darwin.tar.xz": "23b8f52102249a47ab5bc859d54c9a3cb588a3259ba3f00f557d50edeca4fde9",
|
||||
"rustc-1.86.0-x86_64-pc-windows-msvc.tar.xz": "fdde839fea274529a31e51eb85c6df1782cc8479c9d1bc24e2914d66a0de41ab",
|
||||
"clippy-1.86.0-x86_64-unknown-linux-gnu.tar.xz": "02aaff2c1407d2da8dba19aa4970dd873e311902b120a66cbcdbe51eb8836edf",
|
||||
"clippy-1.86.0-x86_64-apple-darwin.tar.xz": "bb85efda7bbffaf124867f5ca36d50932b1e8f533c62ee923438afb32ff8fe9a",
|
||||
"clippy-1.86.0-aarch64-apple-darwin.tar.xz": "239fa3a604b124f0312f2af08537874a1227dba63385484b468cca62e7c4f2f2",
|
||||
"clippy-1.86.0-x86_64-pc-windows-msvc.tar.xz": "d00498f47d49219f032e2c5eeebdfc3d32317c0dc3d3fd7125327445bc482cb4",
|
||||
"cargo-1.86.0-x86_64-unknown-linux-gnu.tar.xz": "c5c1590f7e9246ad9f4f97cfe26ffa92707b52a769726596a9ef81565ebd908b",
|
||||
"cargo-1.86.0-x86_64-apple-darwin.tar.xz": "af163eb02d1a178044d1b4f2375960efd47130f795f6e33d09e345454bb26f4e",
|
||||
"cargo-1.86.0-aarch64-apple-darwin.tar.xz": "3cb13873d48c3e1e4cc684d42c245226a11fba52af6b047c3346ed654e7a05c0",
|
||||
"cargo-1.86.0-x86_64-pc-windows-msvc.tar.xz": "e57a9d89619b5604899bac443e68927bdd371e40f2e03e18950b6ceb3eb67966",
|
||||
"llvm-tools-1.86.0-x86_64-unknown-linux-gnu.tar.xz": "282145ab7a63c98b625856f44b905b4dc726b497246b824632a5790debe95a78",
|
||||
"llvm-tools-1.86.0-x86_64-apple-darwin.tar.xz": "b55706e92f7da989207c50c13c7add483a9fedd233bc431b106eca2a8f151ec9",
|
||||
"llvm-tools-1.86.0-aarch64-apple-darwin.tar.xz": "04d3618c686845853585f036e3211eb9e18f2d290f4610a7a78bdc1fcce1ebd9",
|
||||
"llvm-tools-1.86.0-x86_64-pc-windows-msvc.tar.xz": "721a17cc8dc219177e4277a3592253934ef08daa1e1b12eda669a67d15fad8dd",
|
||||
"rust-std-1.86.0-x86_64-unknown-linux-gnu.tar.xz": "67be7184ea388d8ce0feaf7fdea46f1775cfc2970930264343b3089898501d37",
|
||||
"rust-std-1.86.0-x86_64-apple-darwin.tar.xz": "3b1140d54870a080080e84700143f4a342fbd02a410a319b05d9c02e7dcf44cc",
|
||||
"rust-std-1.86.0-aarch64-apple-darwin.tar.xz": "0fb121fb3b8fa9027d79ff598500a7e5cd086ddbc3557482ed3fdda00832c61b",
|
||||
"rust-std-1.86.0-x86_64-pc-windows-msvc.tar.xz": "3d5354b7b9cb950b58bff3fce18a652aa374bb30c8f70caebd3bd0b43cb41a33",
|
||||
"2025-08-01/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "9bbeaf5d3fc7247d31463a9083aa251c995cc50662c8219e7a2254d76a72a9a4",
|
||||
"2025-08-01/rustc-nightly-x86_64-apple-darwin.tar.xz": "c9ea539a8eff0d5d162701f99f9e1aabe14dd0dfb420d62362817a5d09219de7",
|
||||
"2025-08-01/rustc-nightly-aarch64-apple-darwin.tar.xz": "ae83feebbc39cfd982e4ecc8297731fe79c185173aee138467b334c5404b3773",
|
||||
"2025-08-01/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "9f170c30d802a349be60cf52ec46260802093cb1013ad667fc0d528b7b10152f",
|
||||
"2025-08-01/clippy-nightly-x86_64-unknown-linux-gnu.tar.xz": "9ae5f3cd8f557c4f6df522597c69d14398cf604cfaed2b83e767c4b77a7eaaf6",
|
||||
"2025-08-01/clippy-nightly-x86_64-apple-darwin.tar.xz": "983cb9ee0b6b968188e04ab2d33743d54764b2681ce565e1b3f2b9135c696a3e",
|
||||
"2025-08-01/clippy-nightly-aarch64-apple-darwin.tar.xz": "ed2219dbc49d088225e1b7c5c4390fa295066e071fddaa2714018f6bb39ddbf0",
|
||||
"2025-08-01/clippy-nightly-x86_64-pc-windows-msvc.tar.xz": "911f40ab5cbdd686f40e00965271fe47c4805513a308ed01f30eafb25b448a50",
|
||||
"2025-08-01/cargo-nightly-x86_64-unknown-linux-gnu.tar.xz": "106463c284e48e4904c717471eeec2be5cc83a9d2cae8d6e948b52438cad2e69",
|
||||
"2025-08-01/cargo-nightly-x86_64-apple-darwin.tar.xz": "6ad35c40efc41a8c531ea43235058347b6902d98a9693bf0aed7fc16d5590cef",
|
||||
"2025-08-01/cargo-nightly-aarch64-apple-darwin.tar.xz": "dd28c365e9d298abc3154c797720ad36a0058f131265c9978b4c8e4e37012c8a",
|
||||
"2025-08-01/cargo-nightly-x86_64-pc-windows-msvc.tar.xz": "7b431286e12d6b3834b038f078389a00cac73f351e8c3152b2504a3c06420b3b",
|
||||
"2025-08-01/llvm-tools-nightly-x86_64-unknown-linux-gnu.tar.xz": "e342e305d7927cc288d386983b2bc253cfad3776b113386e903d0b302648ef47",
|
||||
"2025-08-01/llvm-tools-nightly-x86_64-apple-darwin.tar.xz": "e44dd3506524d85c37b3a54bcc91d01378fd2c590b2db5c5974d12f05c1b84d1",
|
||||
"2025-08-01/llvm-tools-nightly-aarch64-apple-darwin.tar.xz": "0c1b5f46dd81be4a9227b10283a0fcaa39c14fea7e81aea6fd6d9887ff6cdc41",
|
||||
"2025-08-01/llvm-tools-nightly-x86_64-pc-windows-msvc.tar.xz": "423e5fd11406adccbc31b8456ceb7375ce055cdf45e90d2c3babeb2d7f58383f",
|
||||
"2025-08-01/rust-std-nightly-x86_64-unknown-linux-gnu.tar.xz": "3c0ceb46a252647a1d4c7116d9ccae684fa5e42aaf3296419febd2c962c3b41d",
|
||||
"2025-08-01/rust-std-nightly-x86_64-apple-darwin.tar.xz": "3be416003cab10f767390a753d1d16ae4d26c7421c03c98992cf1943e5b0efe8",
|
||||
"2025-08-01/rust-std-nightly-aarch64-apple-darwin.tar.xz": "4046ac0ef951cb056b5028a399124f60999fa37792eab69d008d8d7965f389b4",
|
||||
"2025-08-01/rust-std-nightly-x86_64-pc-windows-msvc.tar.xz": "191ed9d8603c3a4fe5a7bbbc2feb72049078dae2df3d3b7d5dedf3abbf823e6e",
|
||||
},
|
||||
versions = [RUST_VERSION],
|
||||
)
|
||||
@@ -260,7 +263,7 @@ use_repo(
|
||||
)
|
||||
|
||||
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
|
||||
go_sdk.download(version = "1.24.0")
|
||||
go_sdk.download(version = "1.25.0")
|
||||
|
||||
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
|
||||
go_deps.from_file(go_mod = "//go/extractor:go.mod")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
private import actions
|
||||
private import codeql.actions.TaintTracking
|
||||
private import codeql.actions.dataflow.ExternalFlow
|
||||
private import codeql.actions.security.ControlChecks
|
||||
import codeql.actions.dataflow.FlowSources
|
||||
import codeql.actions.DataFlow
|
||||
|
||||
@@ -65,6 +66,16 @@ class ArgumentInjectionFromMaDSink extends ArgumentInjectionSink {
|
||||
override string getCommand() { result = "unknown" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the event that is relevant for the given node in the context of argument injection.
|
||||
*
|
||||
* This is used to highlight the event in the query results when an alert is raised.
|
||||
*/
|
||||
Event getRelevantEventInPrivilegedContext(DataFlow::Node node) {
|
||||
inPrivilegedContext(node.asExpr(), result) and
|
||||
not exists(ControlCheck check | check.protects(node.asExpr(), result, "argument-injection"))
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for unsafe user input
|
||||
* that is used to construct and evaluate a code script.
|
||||
@@ -88,6 +99,16 @@ private module ArgumentInjectionConfig implements DataFlow::ConfigSig {
|
||||
run.getScript().getAnEnvReachingArgumentInjectionSink(var, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getLocation()
|
||||
or
|
||||
result = getRelevantEventInPrivilegedContext(sink).getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/** Tracks flow of unsafe user input that is used to construct and evaluate a code script. */
|
||||
|
||||
@@ -4,6 +4,7 @@ import codeql.actions.DataFlow
|
||||
import codeql.actions.dataflow.FlowSources
|
||||
import codeql.actions.security.PoisonableSteps
|
||||
import codeql.actions.security.UntrustedCheckoutQuery
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
string unzipRegexp() { result = "(unzip|tar)\\s+.*" }
|
||||
|
||||
@@ -292,6 +293,16 @@ class ArtifactPoisoningSink extends DataFlow::Node {
|
||||
string getPath() { result = download.getPath() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the event that is relevant for the given node in the context of artifact poisoning.
|
||||
*
|
||||
* This is used to highlight the event in the query results when an alert is raised.
|
||||
*/
|
||||
Event getRelevantEventInPrivilegedContext(DataFlow::Node node) {
|
||||
inPrivilegedContext(node.asExpr(), result) and
|
||||
not exists(ControlCheck check | check.protects(node.asExpr(), result, "artifact-poisoning"))
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for unsafe artifacts
|
||||
* that is used may lead to artifact poisoning
|
||||
@@ -318,6 +329,16 @@ private module ArtifactPoisoningConfig implements DataFlow::ConfigSig {
|
||||
exists(run.getScript().getAFileReadCommand())
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getLocation()
|
||||
or
|
||||
result = getRelevantEventInPrivilegedContext(sink).getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/** Tracks flow of unsafe artifacts that is used in an insecure way. */
|
||||
|
||||
@@ -3,6 +3,8 @@ private import codeql.actions.TaintTracking
|
||||
private import codeql.actions.dataflow.ExternalFlow
|
||||
import codeql.actions.dataflow.FlowSources
|
||||
import codeql.actions.DataFlow
|
||||
import codeql.actions.security.ControlChecks
|
||||
import codeql.actions.security.CachePoisoningQuery
|
||||
|
||||
class CodeInjectionSink extends DataFlow::Node {
|
||||
CodeInjectionSink() {
|
||||
@@ -11,6 +13,46 @@ class CodeInjectionSink extends DataFlow::Node {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relevant event for the sink in CodeInjectionCritical.ql.
|
||||
*/
|
||||
Event getRelevantCriticalEventForSink(DataFlow::Node sink) {
|
||||
inPrivilegedContext(sink.asExpr(), result) and
|
||||
not exists(ControlCheck check | check.protects(sink.asExpr(), result, "code-injection")) and
|
||||
// exclude cases where the sink is a JS script and the expression uses toJson
|
||||
not exists(UsesStep script |
|
||||
script.getCallee() = "actions/github-script" and
|
||||
script.getArgumentExpr("script") = sink.asExpr() and
|
||||
exists(getAToJsonReferenceExpression(sink.asExpr().(Expression).getExpression(), _))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relevant event for the sink in CachePoisoningViaCodeInjection.ql.
|
||||
*/
|
||||
Event getRelevantCachePoisoningEventForSink(DataFlow::Node sink) {
|
||||
exists(LocalJob job |
|
||||
job = sink.asExpr().getEnclosingJob() and
|
||||
job.getATriggerEvent() = result and
|
||||
// job can be triggered by an external user
|
||||
result.isExternallyTriggerable() and
|
||||
// excluding privileged workflows since they can be exploited in easier circumstances
|
||||
// which is covered by `actions/code-injection/critical`
|
||||
not job.isPrivilegedExternallyTriggerable(result) and
|
||||
(
|
||||
// the workflow runs in the context of the default branch
|
||||
runsOnDefaultBranch(result)
|
||||
or
|
||||
// the workflow caller runs in the context of the default branch
|
||||
result.getName() = "workflow_call" and
|
||||
exists(ExternalJob caller |
|
||||
caller.getCallee() = job.getLocation().getFile().getRelativePath() and
|
||||
runsOnDefaultBranch(caller.getATriggerEvent())
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for unsafe user input
|
||||
* that is used to construct and evaluate a code script.
|
||||
@@ -35,6 +77,18 @@ private module CodeInjectionConfig implements DataFlow::ConfigSig {
|
||||
exists(run.getScript().getAFileReadCommand())
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getLocation()
|
||||
or
|
||||
result = getRelevantCriticalEventForSink(sink).getLocation()
|
||||
or
|
||||
result = getRelevantCachePoisoningEventForSink(sink).getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/** Tracks flow of unsafe user input that is used to construct and evaluate a code script. */
|
||||
|
||||
@@ -3,11 +3,20 @@ private import codeql.actions.TaintTracking
|
||||
private import codeql.actions.dataflow.ExternalFlow
|
||||
import codeql.actions.dataflow.FlowSources
|
||||
import codeql.actions.DataFlow
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
private class CommandInjectionSink extends DataFlow::Node {
|
||||
CommandInjectionSink() { madSink(this, "command-injection") }
|
||||
}
|
||||
|
||||
/** Get the relevant event for the sink in CommandInjectionCritical.ql. */
|
||||
Event getRelevantEventInPrivilegedContext(DataFlow::Node sink) {
|
||||
inPrivilegedContext(sink.asExpr(), result) and
|
||||
not exists(ControlCheck check |
|
||||
check.protects(sink.asExpr(), result, ["command-injection", "code-injection"])
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for unsafe user input
|
||||
* that is used to construct and evaluate a system command.
|
||||
@@ -16,6 +25,16 @@ private module CommandInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof CommandInjectionSink }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getLocation()
|
||||
or
|
||||
result = getRelevantEventInPrivilegedContext(sink).getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/** Tracks flow of unsafe user input that is used to construct and evaluate a system command. */
|
||||
|
||||
@@ -72,6 +72,25 @@ class EnvPathInjectionFromMaDSink extends EnvPathInjectionSink {
|
||||
EnvPathInjectionFromMaDSink() { madSink(this, "envpath-injection") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relevant event for a sink in EnvPathInjectionCritical.ql where the source type is "artifact".
|
||||
*/
|
||||
Event getRelevantArtifactEventInPrivilegedContext(DataFlow::Node sink) {
|
||||
inPrivilegedContext(sink.asExpr(), result) and
|
||||
not exists(ControlCheck check |
|
||||
check.protects(sink.asExpr(), result, ["untrusted-checkout", "artifact-poisoning"])
|
||||
) and
|
||||
sink instanceof EnvPathInjectionFromFileReadSink
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relevant event for a sink in EnvPathInjectionCritical.ql where the source type is not "artifact".
|
||||
*/
|
||||
Event getRelevantNonArtifactEventInPrivilegedContext(DataFlow::Node sink) {
|
||||
inPrivilegedContext(sink.asExpr(), result) and
|
||||
not exists(ControlCheck check | check.protects(sink.asExpr(), result, "code-injection"))
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for unsafe user input
|
||||
* that is used to construct and evaluate an environment variable.
|
||||
@@ -108,6 +127,18 @@ private module EnvPathInjectionConfig implements DataFlow::ConfigSig {
|
||||
exists(run.getScript().getAFileReadCommand())
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getLocation()
|
||||
or
|
||||
result = getRelevantArtifactEventInPrivilegedContext(sink).getLocation()
|
||||
or
|
||||
result = getRelevantNonArtifactEventInPrivilegedContext(sink).getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/** Tracks flow of unsafe user input that is used to construct and evaluate the PATH environment variable. */
|
||||
|
||||
@@ -126,6 +126,32 @@ class EnvVarInjectionFromMaDSink extends EnvVarInjectionSink {
|
||||
EnvVarInjectionFromMaDSink() { madSink(this, "envvar-injection") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relevant event for a sink in EnvVarInjectionCritical.ql where the source type is "artifact".
|
||||
*/
|
||||
Event getRelevantArtifactEventInPrivilegedContext(DataFlow::Node sink) {
|
||||
inPrivilegedContext(sink.asExpr(), result) and
|
||||
not exists(ControlCheck check |
|
||||
check
|
||||
.protects(sink.asExpr(), result,
|
||||
["envvar-injection", "untrusted-checkout", "artifact-poisoning"])
|
||||
) and
|
||||
(
|
||||
sink instanceof EnvVarInjectionFromFileReadSink or
|
||||
madSink(sink, "envvar-injection")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relevant event for a sink in EnvVarInjectionCritical.ql where the source type is not "artifact".
|
||||
*/
|
||||
Event getRelevantNonArtifactEventInPrivilegedContext(DataFlow::Node sink) {
|
||||
inPrivilegedContext(sink.asExpr(), result) and
|
||||
not exists(ControlCheck check |
|
||||
check.protects(sink.asExpr(), result, ["envvar-injection", "code-injection"])
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for unsafe user input
|
||||
* that is used to construct and evaluate an environment variable.
|
||||
@@ -163,6 +189,18 @@ private module EnvVarInjectionConfig implements DataFlow::ConfigSig {
|
||||
exists(run.getScript().getAFileReadCommand())
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getLocation()
|
||||
or
|
||||
result = getRelevantArtifactEventInPrivilegedContext(sink).getLocation()
|
||||
or
|
||||
result = getRelevantNonArtifactEventInPrivilegedContext(sink).getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/** Tracks flow of unsafe user input that is used to construct and evaluate an environment variable. */
|
||||
|
||||
@@ -21,18 +21,12 @@ import codeql.actions.security.ControlChecks
|
||||
from EnvPathInjectionFlow::PathNode source, EnvPathInjectionFlow::PathNode sink, Event event
|
||||
where
|
||||
EnvPathInjectionFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event) and
|
||||
(
|
||||
not source.getNode().(RemoteFlowSource).getSourceType() = "artifact" and
|
||||
not exists(ControlCheck check |
|
||||
check.protects(sink.getNode().asExpr(), event, "code-injection")
|
||||
)
|
||||
event = getRelevantNonArtifactEventInPrivilegedContext(sink.getNode())
|
||||
or
|
||||
source.getNode().(RemoteFlowSource).getSourceType() = "artifact" and
|
||||
not exists(ControlCheck check |
|
||||
check.protects(sink.getNode().asExpr(), event, ["untrusted-checkout", "artifact-poisoning"])
|
||||
) and
|
||||
sink.getNode() instanceof EnvPathInjectionFromFileReadSink
|
||||
event = getRelevantArtifactEventInPrivilegedContext(sink.getNode())
|
||||
)
|
||||
select sink.getNode(), source, sink,
|
||||
"Potential PATH environment variable injection in $@, which may be controlled by an external user ($@).",
|
||||
|
||||
@@ -22,26 +22,15 @@ import codeql.actions.security.ControlChecks
|
||||
from EnvVarInjectionFlow::PathNode source, EnvVarInjectionFlow::PathNode sink, Event event
|
||||
where
|
||||
EnvVarInjectionFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event) and
|
||||
// exclude paths to file read sinks from non-artifact sources
|
||||
(
|
||||
// source is text
|
||||
not source.getNode().(RemoteFlowSource).getSourceType() = "artifact" and
|
||||
not exists(ControlCheck check |
|
||||
check.protects(sink.getNode().asExpr(), event, ["envvar-injection", "code-injection"])
|
||||
)
|
||||
event = getRelevantNonArtifactEventInPrivilegedContext(sink.getNode())
|
||||
or
|
||||
// source is an artifact or a file from an untrusted checkout
|
||||
source.getNode().(RemoteFlowSource).getSourceType() = "artifact" and
|
||||
not exists(ControlCheck check |
|
||||
check
|
||||
.protects(sink.getNode().asExpr(), event,
|
||||
["envvar-injection", "untrusted-checkout", "artifact-poisoning"])
|
||||
) and
|
||||
(
|
||||
sink.getNode() instanceof EnvVarInjectionFromFileReadSink or
|
||||
madSink(sink.getNode(), "envvar-injection")
|
||||
)
|
||||
event = getRelevantArtifactEventInPrivilegedContext(sink.getNode())
|
||||
)
|
||||
select sink.getNode(), source, sink,
|
||||
"Potential environment variable injection in $@, which may be controlled by an external user ($@).",
|
||||
|
||||
@@ -22,15 +22,8 @@ import codeql.actions.security.ControlChecks
|
||||
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink, Event event
|
||||
where
|
||||
CodeInjectionFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event) and
|
||||
source.getNode().(RemoteFlowSource).getEventName() = event.getName() and
|
||||
not exists(ControlCheck check | check.protects(sink.getNode().asExpr(), event, "code-injection")) and
|
||||
// exclude cases where the sink is a JS script and the expression uses toJson
|
||||
not exists(UsesStep script |
|
||||
script.getCallee() = "actions/github-script" and
|
||||
script.getArgumentExpr("script") = sink.getNode().asExpr() and
|
||||
exists(getAToJsonReferenceExpression(sink.getNode().asExpr().(Expression).getExpression(), _))
|
||||
)
|
||||
event = getRelevantCriticalEventForSink(sink.getNode()) and
|
||||
source.getNode().(RemoteFlowSource).getEventName() = event.getName()
|
||||
select sink.getNode(), source, sink,
|
||||
"Potential code injection in $@, which may be controlled by an external user ($@).", sink,
|
||||
sink.getNode().asExpr().(Expression).getRawExpression(), event, event.getName()
|
||||
|
||||
@@ -18,30 +18,13 @@ import codeql.actions.security.CachePoisoningQuery
|
||||
import CodeInjectionFlow::PathGraph
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink, LocalJob job, Event event
|
||||
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink, Event event
|
||||
where
|
||||
CodeInjectionFlow::flowPath(source, sink) and
|
||||
job = sink.getNode().asExpr().getEnclosingJob() and
|
||||
job.getATriggerEvent() = event and
|
||||
// job can be triggered by an external user
|
||||
event.isExternallyTriggerable() and
|
||||
event = getRelevantCachePoisoningEventForSink(sink.getNode()) and
|
||||
// the checkout is not controlled by an access check
|
||||
not exists(ControlCheck check |
|
||||
check.protects(source.getNode().asExpr(), event, "code-injection")
|
||||
) and
|
||||
// excluding privileged workflows since they can be exploited in easier circumstances
|
||||
// which is covered by `actions/code-injection/critical`
|
||||
not job.isPrivilegedExternallyTriggerable(event) and
|
||||
(
|
||||
// the workflow runs in the context of the default branch
|
||||
runsOnDefaultBranch(event)
|
||||
or
|
||||
// the workflow caller runs in the context of the default branch
|
||||
event.getName() = "workflow_call" and
|
||||
exists(ExternalJob caller |
|
||||
caller.getCallee() = job.getLocation().getFile().getRelativePath() and
|
||||
runsOnDefaultBranch(caller.getATriggerEvent())
|
||||
)
|
||||
)
|
||||
select sink.getNode(), source, sink,
|
||||
"Unprivileged code injection in $@, which may lead to cache poisoning ($@).", sink,
|
||||
|
||||
@@ -19,10 +19,7 @@ import codeql.actions.security.ControlChecks
|
||||
from ArtifactPoisoningFlow::PathNode source, ArtifactPoisoningFlow::PathNode sink, Event event
|
||||
where
|
||||
ArtifactPoisoningFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event) and
|
||||
not exists(ControlCheck check |
|
||||
check.protects(sink.getNode().asExpr(), event, "artifact-poisoning")
|
||||
)
|
||||
event = getRelevantEventInPrivilegedContext(sink.getNode())
|
||||
select sink.getNode(), source, sink,
|
||||
"Potential artifact poisoning in $@, which may be controlled by an external user ($@).", sink,
|
||||
sink.getNode().toString(), event, event.getName()
|
||||
|
||||
@@ -21,10 +21,7 @@ import codeql.actions.security.ControlChecks
|
||||
from CommandInjectionFlow::PathNode source, CommandInjectionFlow::PathNode sink, Event event
|
||||
where
|
||||
CommandInjectionFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event) and
|
||||
not exists(ControlCheck check |
|
||||
check.protects(sink.getNode().asExpr(), event, ["command-injection", "code-injection"])
|
||||
)
|
||||
event = getRelevantEventInPrivilegedContext(sink.getNode())
|
||||
select sink.getNode(), source, sink,
|
||||
"Potential command injection in $@, which may be controlled by an external user ($@).", sink,
|
||||
sink.getNode().asExpr().(Expression).getRawExpression(), event, event.getName()
|
||||
|
||||
@@ -20,10 +20,7 @@ import codeql.actions.security.ControlChecks
|
||||
from ArgumentInjectionFlow::PathNode source, ArgumentInjectionFlow::PathNode sink, Event event
|
||||
where
|
||||
ArgumentInjectionFlow::flowPath(source, sink) and
|
||||
inPrivilegedContext(sink.getNode().asExpr(), event) and
|
||||
not exists(ControlCheck check |
|
||||
check.protects(sink.getNode().asExpr(), event, "argument-injection")
|
||||
)
|
||||
event = getRelevantEventInPrivilegedContext(sink.getNode())
|
||||
select sink.getNode(), source, sink,
|
||||
"Potential argument injection in $@ command, which may be controlled by an external user ($@).",
|
||||
sink, sink.getNode().(ArgumentInjectionSink).getCommand(), event, event.getName()
|
||||
|
||||
4
cpp/ql/lib/change-notes/2025-08-13-guards.md
Normal file
4
cpp/ql/lib/change-notes/2025-08-13-guards.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The guards libraries (`semmle.code.cpp.controlflow.Guards` and `semmle.code.cpp.controlflow.IRGuards`) have been improved to recognize more guards.
|
||||
@@ -936,6 +936,77 @@ private module Cached {
|
||||
ValueNumber getUnary() { result.getAnInstruction() = instr.getUnary() }
|
||||
}
|
||||
|
||||
signature predicate sinkSig(Instruction instr);
|
||||
|
||||
private module BooleanInstruction<sinkSig/1 isSink> {
|
||||
/**
|
||||
* Holds if `i1` flows to `i2` in a single step and `i2` is not an
|
||||
* instruction that produces a value of Boolean type.
|
||||
*/
|
||||
private predicate stepToNonBoolean(Instruction i1, Instruction i2) {
|
||||
not i2.getResultIRType() instanceof IRBooleanType and
|
||||
(
|
||||
i2.(CopyInstruction).getSourceValue() = i1
|
||||
or
|
||||
i2.(ConvertInstruction).getUnary() = i1
|
||||
or
|
||||
i2.(BuiltinExpectCallInstruction).getArgument(0) = i1
|
||||
)
|
||||
}
|
||||
|
||||
private predicate rev(Instruction instr) {
|
||||
isSink(instr)
|
||||
or
|
||||
exists(Instruction instr1 |
|
||||
rev(instr1) and
|
||||
stepToNonBoolean(instr, instr1)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate hasBooleanType(Instruction instr) {
|
||||
instr.getResultIRType() instanceof IRBooleanType
|
||||
}
|
||||
|
||||
private predicate fwd(Instruction instr) {
|
||||
rev(instr) and
|
||||
(
|
||||
hasBooleanType(instr)
|
||||
or
|
||||
exists(Instruction instr0 |
|
||||
fwd(instr0) and
|
||||
stepToNonBoolean(instr0, instr)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate prunedStep(Instruction i1, Instruction i2) {
|
||||
fwd(i1) and
|
||||
fwd(i2) and
|
||||
stepToNonBoolean(i1, i2)
|
||||
}
|
||||
|
||||
private predicate stepsPlus(Instruction i1, Instruction i2) =
|
||||
doublyBoundedFastTC(prunedStep/2, hasBooleanType/1, isSink/1)(i1, i2)
|
||||
|
||||
/**
|
||||
* Gets the Boolean-typed instruction that defines `instr` before any
|
||||
* integer conversions are applied, if any.
|
||||
*/
|
||||
Instruction get(Instruction instr) {
|
||||
isSink(instr) and
|
||||
(
|
||||
result = instr
|
||||
or
|
||||
stepsPlus(result, instr)
|
||||
) and
|
||||
hasBooleanType(result)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate isUnaryComparesEqLeft(Instruction instr) {
|
||||
unary_compares_eq(_, instr.getAUse(), 0, _, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `left == right + k` is `areEqual` given that test is `testIsTrue`.
|
||||
*
|
||||
@@ -966,14 +1037,19 @@ private module Cached {
|
||||
)
|
||||
or
|
||||
compares_eq(test.(BuiltinExpectCallValueNumber).getCondition(), left, right, k, areEqual, value)
|
||||
}
|
||||
|
||||
private predicate isConvertedBool(Instruction instr) {
|
||||
instr.getResultIRType() instanceof IRBooleanType
|
||||
or
|
||||
isConvertedBool(instr.(ConvertInstruction).getUnary())
|
||||
or
|
||||
isConvertedBool(instr.(BuiltinExpectCallInstruction).getCondition())
|
||||
exists(Operand l, BooleanValue bv |
|
||||
// 1. test = value -> int(l) = 0 is !bv
|
||||
unary_compares_eq(test, l, 0, bv.getValue().booleanNot(), value) and
|
||||
// 2. l = bv -> left + right is areEqual
|
||||
compares_eq(valueNumber(BooleanInstruction<isUnaryComparesEqLeft/1>::get(l.getDef())), left,
|
||||
right, k, areEqual, bv)
|
||||
// We want this to hold:
|
||||
// `test = value -> left + right is areEqual`
|
||||
// Applying 2 we need to show:
|
||||
// `test = value -> l = bv`
|
||||
// And `l = bv` holds by `int(l) = 0 is !bv`
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1006,19 +1082,11 @@ private module Cached {
|
||||
k = k1 + k2
|
||||
)
|
||||
or
|
||||
exists(CompareValueNumber cmp, Operand left, Operand right, AbstractValue v |
|
||||
test = cmp and
|
||||
pragma[only_bind_into](cmp)
|
||||
.hasOperands(pragma[only_bind_into](left), pragma[only_bind_into](right)) and
|
||||
isConvertedBool(left.getDef()) and
|
||||
int_value(right.getDef()) = 0 and
|
||||
unary_compares_eq(valueNumberOfOperand(left), op, k, areEqual, v)
|
||||
|
|
||||
cmp instanceof CompareNEValueNumber and
|
||||
v = value
|
||||
or
|
||||
cmp instanceof CompareEQValueNumber and
|
||||
v.getDualValue() = value
|
||||
// See argument for why this is correct in compares_eq
|
||||
exists(Operand l, BooleanValue bv |
|
||||
unary_compares_eq(test, l, 0, bv.getValue().booleanNot(), value) and
|
||||
unary_compares_eq(valueNumber(BooleanInstruction<isUnaryComparesEqLeft/1>::get(l.getDef())),
|
||||
op, k, areEqual, bv)
|
||||
)
|
||||
or
|
||||
unary_compares_eq(test.(BuiltinExpectCallValueNumber).getCondition(), op, k, areEqual, value)
|
||||
@@ -1116,70 +1184,26 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isBuiltInExpectArg(Instruction instr) {
|
||||
instr = any(BuiltinExpectCallInstruction buildinExpect).getArgument(0)
|
||||
}
|
||||
|
||||
/** A call to the builtin operation `__builtin_expect`. */
|
||||
private class BuiltinExpectCallInstruction extends CallInstruction {
|
||||
BuiltinExpectCallInstruction() { this.getStaticCallTarget().hasName("__builtin_expect") }
|
||||
|
||||
/** Gets the condition of this call. */
|
||||
Instruction getCondition() { result = this.getConditionOperand().getDef() }
|
||||
|
||||
Operand getConditionOperand() {
|
||||
// The first parameter of `__builtin_expect` has type `long`. So we skip
|
||||
// the conversion when inferring guards.
|
||||
result = this.getArgument(0).(ConvertInstruction).getUnaryOperand()
|
||||
Instruction getCondition() {
|
||||
result = BooleanInstruction<isBuiltInExpectArg/1>::get(this.getArgument(0))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `left == right + k` is `areEqual` if `cmp` evaluates to `value`,
|
||||
* and `cmp` is an instruction that compares the value of
|
||||
* `__builtin_expect(left == right + k, _)` to `0`.
|
||||
*/
|
||||
private predicate builtin_expect_eq(
|
||||
CompareValueNumber cmp, Operand left, Operand right, int k, boolean areEqual,
|
||||
AbstractValue value
|
||||
) {
|
||||
exists(BuiltinExpectCallValueNumber call, Instruction const, AbstractValue innerValue |
|
||||
int_value(const) = 0 and
|
||||
cmp.hasOperands(call.getAUse(), const.getAUse()) and
|
||||
compares_eq(call.getCondition(), left, right, k, areEqual, innerValue)
|
||||
|
|
||||
cmp instanceof CompareNEValueNumber and
|
||||
value = innerValue
|
||||
or
|
||||
cmp instanceof CompareEQValueNumber and
|
||||
value.getDualValue() = innerValue
|
||||
)
|
||||
}
|
||||
|
||||
private predicate complex_eq(
|
||||
ValueNumber cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
|
||||
) {
|
||||
sub_eq(cmp, left, right, k, areEqual, value)
|
||||
or
|
||||
add_eq(cmp, left, right, k, areEqual, value)
|
||||
or
|
||||
builtin_expect_eq(cmp, left, right, k, areEqual, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op == k` is `areEqual` if `cmp` evaluates to `value`, and `cmp` is
|
||||
* an instruction that compares the value of `__builtin_expect(op == k, _)` to `0`.
|
||||
*/
|
||||
private predicate unary_builtin_expect_eq(
|
||||
CompareValueNumber cmp, Operand op, int k, boolean areEqual, AbstractValue value
|
||||
) {
|
||||
exists(BuiltinExpectCallValueNumber call, Instruction const, AbstractValue innerValue |
|
||||
int_value(const) = 0 and
|
||||
cmp.hasOperands(call.getAUse(), const.getAUse()) and
|
||||
unary_compares_eq(call.getCondition(), op, k, areEqual, innerValue)
|
||||
|
|
||||
cmp instanceof CompareNEValueNumber and
|
||||
value = innerValue
|
||||
or
|
||||
cmp instanceof CompareEQValueNumber and
|
||||
value.getDualValue() = innerValue
|
||||
)
|
||||
}
|
||||
|
||||
private predicate unary_complex_eq(
|
||||
@@ -1188,8 +1212,6 @@ private module Cached {
|
||||
unary_sub_eq(test, op, k, areEqual, value)
|
||||
or
|
||||
unary_add_eq(test, op, k, areEqual, value)
|
||||
or
|
||||
unary_builtin_expect_eq(test, op, k, areEqual, value)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1215,6 +1237,15 @@ private module Cached {
|
||||
exists(AbstractValue dual | value = dual.getDualValue() |
|
||||
compares_lt(test.(LogicalNotValueNumber).getUnary(), left, right, k, isLt, dual)
|
||||
)
|
||||
or
|
||||
compares_lt(test.(BuiltinExpectCallValueNumber).getCondition(), left, right, k, isLt, value)
|
||||
or
|
||||
// See argument for why this is correct in compares_eq
|
||||
exists(Operand l, BooleanValue bv |
|
||||
unary_compares_eq(test, l, 0, bv.getValue().booleanNot(), value) and
|
||||
compares_lt(valueNumber(BooleanInstruction<isUnaryComparesEqLeft/1>::get(l.getDef())), left,
|
||||
right, k, isLt, bv)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `op < k` evaluates to `isLt` given that `test` evaluates to `value`. */
|
||||
@@ -1234,6 +1265,15 @@ private module Cached {
|
||||
int_value(const) = k1 and
|
||||
k = k1 + k2
|
||||
)
|
||||
or
|
||||
compares_lt(test.(BuiltinExpectCallValueNumber).getCondition(), op, k, isLt, value)
|
||||
or
|
||||
// See argument for why this is correct in compares_eq
|
||||
exists(Operand l, BooleanValue bv |
|
||||
unary_compares_eq(test, l, 0, bv.getValue().booleanNot(), value) and
|
||||
compares_lt(valueNumber(BooleanInstruction<isUnaryComparesEqLeft/1>::get(l.getDef())), op, k,
|
||||
isLt, bv)
|
||||
)
|
||||
}
|
||||
|
||||
/** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */
|
||||
|
||||
@@ -14,6 +14,9 @@ import semmle.code.cpp.ConfigurationTestFile
|
||||
from GlobalVariable gv
|
||||
where
|
||||
gv.getName().length() <= 3 and
|
||||
// We will give an alert for the TemplateVariable, so we don't
|
||||
// need to also give one for each instantiation
|
||||
not gv instanceof VariableTemplateInstantiation and
|
||||
not gv.isStatic() and
|
||||
not gv.getFile() instanceof ConfigurationTestFile // variables in files generated during configuration are likely false positives
|
||||
select gv,
|
||||
|
||||
@@ -82,6 +82,16 @@ module OverflowDestinationConfig implements DataFlow::ConfigSig {
|
||||
nodeIsBarrierEqualityCandidate(node, access, checkedVar)
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(FunctionCall fc | result = fc.getLocation() |
|
||||
sourceSized(fc, sink.asIndirectConvertedExpr())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module OverflowDestination = TaintTracking::Global<OverflowDestinationConfig>;
|
||||
|
||||
@@ -168,6 +168,19 @@ module NonConstFlowConfig implements DataFlow::ConfigSig {
|
||||
cannotContainString(t)
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getLocation()
|
||||
or
|
||||
exists(FormattingFunctionCall call, Expr formatString | result = call.getLocation() |
|
||||
isSinkImpl(sink, formatString) and
|
||||
call.getArgument(call.getFormatParameterIndex()) = formatString
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module NonConstFlow = TaintTracking::Global<NonConstFlowConfig>;
|
||||
|
||||
@@ -215,6 +215,10 @@ private module LeapYearCheckConfig implements DataFlow::ConfigSig {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(ChecksForLeapYearFunctionCall fc | sink.asExpr() = fc.getAnArgument())
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
none() // only used negatively in UncheckedLeapYearAfterYearModification.ql
|
||||
}
|
||||
}
|
||||
|
||||
module LeapYearCheckFlow = DataFlow::Global<LeapYearCheckConfig>;
|
||||
@@ -285,6 +289,14 @@ private module PossibleYearArithmeticOperationCheckConfig implements DataFlow::C
|
||||
aexpr.getLValue() = fa
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) {
|
||||
result = source.asExpr().getLocation()
|
||||
}
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) { result = sink.asExpr().getLocation() }
|
||||
}
|
||||
|
||||
module PossibleYearArithmeticOperationCheckFlow =
|
||||
|
||||
@@ -93,6 +93,12 @@ module TaintedPathConfig implements DataFlow::ConfigSig {
|
||||
// make sinks barriers so that we only report the closest instance
|
||||
isSink(node)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.asIndirectArgument().getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
module TaintedPath = TaintTracking::Global<TaintedPathConfig>;
|
||||
|
||||
@@ -150,6 +150,17 @@ module ExecTaintConfig implements DataFlow::StateConfigSig {
|
||||
predicate isBarrierOut(DataFlow::Node node) {
|
||||
isSink(node, _) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(DataFlow::Node concatResult, Expr command, ExecState state |
|
||||
result = [concatResult.getLocation(), command.getLocation()] and
|
||||
isSink(sink, state) and
|
||||
isSinkImpl(sink, command, _) and
|
||||
concatResult = state.getOutgoingNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module ExecTaint = TaintTracking::GlobalWithState<ExecTaintConfig>;
|
||||
|
||||
@@ -39,6 +39,12 @@ module Config implements DataFlow::ConfigSig {
|
||||
or
|
||||
node.asCertainDefinition().getUnspecifiedType() instanceof ArithmeticType
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) {
|
||||
exists(QueryString query | result = query.getLocation() | query = source.asIndirectExpr())
|
||||
}
|
||||
}
|
||||
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
@@ -54,6 +54,12 @@ module SqlTaintedConfig implements DataFlow::ConfigSig {
|
||||
sql.barrierSqlArgument(input, _)
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(Expr taintedArg | result = taintedArg.getLocation() | taintedArg = asSinkExpr(sink))
|
||||
}
|
||||
}
|
||||
|
||||
module SqlTainted = TaintTracking::Global<SqlTaintedConfig>;
|
||||
|
||||
@@ -124,6 +124,12 @@ module Config implements DataFlow::ConfigSig {
|
||||
// Block flow if the node is guarded by any <, <= or = operations.
|
||||
node = DataFlow::BarrierGuard<lessThanOrEqual/3>::getABarrierNode()
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(BufferWrite bw | result = bw.getLocation() | isSink(sink, bw, _))
|
||||
}
|
||||
}
|
||||
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
@@ -43,6 +43,12 @@ private module Config implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(VariableAccess va | result = va.getLocation() | isSink(sink, va))
|
||||
}
|
||||
}
|
||||
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
@@ -106,6 +106,12 @@ module Config implements DataFlow::ConfigSig {
|
||||
not iTo instanceof PointerArithmeticInstruction
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(Expr e | result = e.getLocation() | isSink(sink, _, e))
|
||||
}
|
||||
}
|
||||
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
@@ -120,6 +120,12 @@ module UncontrolledArithConfig implements DataFlow::ConfigSig {
|
||||
// block unintended flow to pointers
|
||||
node.asExpr().getUnspecifiedType() instanceof PointerType
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) {
|
||||
result = getExpr(source).getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
module UncontrolledArith = TaintTracking::Global<UncontrolledArithConfig>;
|
||||
|
||||
@@ -113,6 +113,12 @@ module Config implements DataFlow::ConfigSig {
|
||||
not iTo instanceof PointerArithmeticInstruction
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(VariableAccess va | result = va.getLocation() | isSink(sink, va, _))
|
||||
}
|
||||
}
|
||||
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
@@ -91,6 +91,12 @@ module TaintedAllocationSizeConfig implements DataFlow::ConfigSig {
|
||||
// to duplicate results)
|
||||
any(HeuristicAllocationFunction f).getAParameter() = node.asParameter()
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(Expr alloc | result = alloc.getLocation() | allocSink(alloc, sink))
|
||||
}
|
||||
}
|
||||
|
||||
module TaintedAllocationSize = TaintTracking::Global<TaintedAllocationSizeConfig>;
|
||||
|
||||
@@ -72,6 +72,12 @@ module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isSource(source, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(Expr condition | result = condition.getLocation() | isSink(sink, condition))
|
||||
}
|
||||
}
|
||||
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
@@ -31,6 +31,14 @@ module VerifyResultConfig implements DataFlow::ConfigSig {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(GuardCondition guard | guard.getAChild*() = sink.asExpr())
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(GuardCondition guard | result = guard.getLocation() |
|
||||
guard.comparesEq(sink.asExpr(), _, 0, false, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module VerifyResult = DataFlow::Global<VerifyResultConfig>;
|
||||
|
||||
@@ -47,6 +47,12 @@ module ToBufferConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(SensitiveBufferWrite w | result = w.getLocation() | isSinkImpl(sink, w))
|
||||
}
|
||||
}
|
||||
|
||||
module ToBufferFlow = TaintTracking::Global<ToBufferConfig>;
|
||||
|
||||
@@ -31,6 +31,16 @@ module FromSensitiveConfig implements DataFlow::ConfigSig {
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node sourceNode) {
|
||||
exists(SensitiveExpr source | result = source.getLocation() | isSourceImpl(sourceNode, source))
|
||||
}
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(FileWrite w | result = w.getLocation() | isSinkImpl(sink, w, _))
|
||||
}
|
||||
}
|
||||
|
||||
module FromSensitiveFlow = TaintTracking::Global<FromSensitiveConfig>;
|
||||
|
||||
@@ -245,6 +245,14 @@ module FromSensitiveConfig implements DataFlow::ConfigSig {
|
||||
// sources to not get path duplication.
|
||||
isSource(node)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(NetworkSendRecv networkSendRecv | result = networkSendRecv.getLocation() |
|
||||
isSinkSendRecv(sink, networkSendRecv)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module FromSensitiveFlow = TaintTracking::Global<FromSensitiveConfig>;
|
||||
@@ -266,6 +274,10 @@ module ToEncryptionConfig implements DataFlow::ConfigSig {
|
||||
// sources to not get path duplication.
|
||||
isSource(node)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
none() // only used negatively
|
||||
}
|
||||
}
|
||||
|
||||
module ToEncryptionFlow = TaintTracking::Global<ToEncryptionConfig>;
|
||||
@@ -281,6 +293,10 @@ module FromEncryptionConfig implements DataFlow::ConfigSig {
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
none() // only used negatively
|
||||
}
|
||||
}
|
||||
|
||||
module FromEncryptionFlow = TaintTracking::Global<FromEncryptionConfig>;
|
||||
|
||||
@@ -123,6 +123,20 @@ module FromSensitiveConfig implements DataFlow::ConfigSig {
|
||||
content.(DataFlow::FieldContent).getField() = getRecField(t.stripType())
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) {
|
||||
exists(SensitiveExpr sensitive | result = sensitive.getLocation() |
|
||||
isSourceImpl(source, sensitive)
|
||||
)
|
||||
}
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(SqliteFunctionCall sqliteCall | result = sqliteCall.getLocation() |
|
||||
isSinkImpl(sink, sqliteCall, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module FromSensitiveFlow = TaintTracking::Global<FromSensitiveConfig>;
|
||||
|
||||
@@ -87,6 +87,14 @@ module HttpStringToUrlOpenConfig implements DataFlow::ConfigSig {
|
||||
sink.asIndirectExpr() = fc.getArgument(3)
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) {
|
||||
result = source.asIndirectExpr().getLocation()
|
||||
}
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) { none() }
|
||||
}
|
||||
|
||||
module HttpStringToUrlOpen = TaintTracking::Global<HttpStringToUrlOpenConfig>;
|
||||
|
||||
@@ -44,6 +44,12 @@ module KeyStrengthFlowConfig implements DataFlow::ConfigSig {
|
||||
exists(getMinimumKeyStrength(name, param))
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(FunctionCall fc | result = fc.getLocation() | sink.asExpr() = fc.getArgument(_))
|
||||
}
|
||||
}
|
||||
|
||||
module KeyStrengthFlow = DataFlow::Global<KeyStrengthFlowConfig>;
|
||||
|
||||
@@ -145,6 +145,18 @@ module Config implements DataFlow::StateConfigSig {
|
||||
// ```
|
||||
result instanceof DataFlow::FeatureHasSinkCallContext
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(DataFlow::Node mid, FlowState state | result = mid.getLocation() |
|
||||
destroyedToBeginSink(sink) and
|
||||
isSink(sink, state) and
|
||||
state = Config::DestroyedToBegin(mid)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module Flow = DataFlow::GlobalWithState<Config>;
|
||||
|
||||
@@ -62,6 +62,16 @@ module NullAppNameCreateProcessFunctionConfig implements DataFlow::ConfigSig {
|
||||
val = call.getArgument(call.getApplicationNameArgumentId())
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(CreateProcessFunctionCall call | result = call.getLocation() |
|
||||
sink.asExpr() = call.getArgument(call.getApplicationNameArgumentId())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module NullAppNameCreateProcessFunction = DataFlow::Global<NullAppNameCreateProcessFunctionConfig>;
|
||||
@@ -82,6 +92,16 @@ module QuotedCommandInCreateProcessFunctionConfig implements DataFlow::ConfigSig
|
||||
val = call.getArgument(call.getCommandLineArgumentId())
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(CreateProcessFunctionCall call | result = call.getLocation() |
|
||||
sink.asExpr() = call.getArgument(call.getCommandLineArgumentId())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module QuotedCommandInCreateProcessFunction =
|
||||
|
||||
@@ -37,6 +37,16 @@ module NullDaclConfig implements DataFlow::ConfigSig {
|
||||
val = call.getArgument(2)
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(SetSecurityDescriptorDaclFunctionCall call | result = call.getLocation() |
|
||||
sink.asExpr() = call.getArgument(2)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module NullDaclFlow = DataFlow::Global<NullDaclConfig>;
|
||||
@@ -68,6 +78,10 @@ module NonNullDaclConfig implements DataFlow::ConfigSig {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(SetSecurityDescriptorDaclFunctionCall call | sink.asExpr() = call.getArgument(2))
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
none() // only used negatively
|
||||
}
|
||||
}
|
||||
|
||||
module NonNullDaclFlow = DataFlow::Global<NonNullDaclConfig>;
|
||||
|
||||
@@ -65,6 +65,16 @@ module Config implements DataFlow::ConfigSig {
|
||||
iFrom1 != iFrom2
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getLocation()
|
||||
or
|
||||
exists(Expr raise | result = raise.getLocation() |
|
||||
sensitiveCondition([sink.asExpr(), sink.asIndirectExpr()], raise)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
@@ -178,6 +178,10 @@ module Config implements DataFlow::ConfigSig {
|
||||
predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(UnsafeCast cast).getUnconverted() }
|
||||
|
||||
int fieldFlowBranchLimit() { result = 0 }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
none() // used both positively and negatively
|
||||
}
|
||||
}
|
||||
|
||||
module Flow = DataFlow::Global<Config>;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/short-global-name` query will no longer give alerts for instantiations of template variables, only for the template itself.
|
||||
@@ -183,6 +183,20 @@ module ArrayAddressToDerefConfig implements DataFlow::StateConfigSig {
|
||||
pointerArithOverflow(pai, _)
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) {
|
||||
exists(Variable v | result = v.getLocation() | isSourceImpl(source, v))
|
||||
}
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(PointerArithmeticInstruction pai, Instruction deref |
|
||||
result = [pai, deref].getLocation() and
|
||||
isInvalidPointerDerefSink2(sink, deref, _) and
|
||||
isSink(sink, ArrayAddressToDerefConfig::TOverflowArithmetic(pai))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module ArrayAddressToDerefFlow = DataFlow::GlobalWithState<ArrayAddressToDerefConfig>;
|
||||
|
||||
@@ -28,6 +28,14 @@ module DecompressionTaintConfig implements DataFlow::ConfigSig {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
any(DecompressionFlowStep s).isAdditionalFlowStep(node1, node2)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(FunctionCall fc | result = [sink.getLocation(), fc.getLocation()] | isSink(fc, sink))
|
||||
}
|
||||
}
|
||||
|
||||
module DecompressionTaint = TaintTracking::Global<DecompressionTaintConfig>;
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
| test.c:198:8:198:8 | b |
|
||||
| test.c:206:7:206:8 | ! ... |
|
||||
| test.c:206:8:206:8 | c |
|
||||
| test.c:215:6:215:18 | call to __builtin_expect |
|
||||
| test.c:219:9:219:22 | call to __builtin_expect |
|
||||
| test.cpp:18:8:18:10 | call to get |
|
||||
| test.cpp:31:7:31:13 | ... == ... |
|
||||
| test.cpp:42:13:42:20 | call to getABool |
|
||||
@@ -92,3 +94,15 @@
|
||||
| test.cpp:241:9:241:43 | ... && ... |
|
||||
| test.cpp:241:22:241:30 | ... == ... |
|
||||
| test.cpp:241:35:241:43 | ... == ... |
|
||||
| test.cpp:247:6:247:18 | ... == ... |
|
||||
| test.cpp:253:6:253:18 | ... != ... |
|
||||
| test.cpp:260:6:260:18 | ... == ... |
|
||||
| test.cpp:266:6:266:18 | ... != ... |
|
||||
| test.cpp:273:6:273:17 | ... == ... |
|
||||
| test.cpp:279:6:279:17 | ... != ... |
|
||||
| test.cpp:287:6:287:19 | ... == ... |
|
||||
| test.cpp:293:6:293:19 | ... != ... |
|
||||
| test.cpp:300:6:300:19 | ... == ... |
|
||||
| test.cpp:306:6:306:19 | ... != ... |
|
||||
| test.cpp:312:6:312:18 | ... == ... |
|
||||
| test.cpp:318:6:318:18 | ... != ... |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,4 +38,4 @@ where
|
||||
|
|
||||
msg = left + op + k + " when " + guard + " is " + value
|
||||
)
|
||||
select guard.getLocation().getStartLine(), msg
|
||||
select guard, msg
|
||||
|
||||
@@ -1,165 +1,196 @@
|
||||
| test.c:7:9:7:13 | ... > ... | false | 10 | 11 |
|
||||
| test.c:7:9:7:13 | ... > ... | true | 7 | 9 |
|
||||
| test.c:17:8:17:12 | ... < ... | true | 17 | 17 |
|
||||
| test.c:17:8:17:12 | ... < ... | true | 18 | 18 |
|
||||
| test.c:17:8:17:21 | ... && ... | true | 18 | 18 |
|
||||
| test.c:17:17:17:21 | ... > ... | true | 18 | 18 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 2 | 2 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 31 | 34 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 34 | 34 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 39 | 42 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 42 | 42 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 42 | 44 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 45 | 45 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 45 | 47 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 51 | 53 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 56 | 58 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 58 | 58 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 58 | 66 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 62 | 62 |
|
||||
| test.c:26:11:26:15 | ... > ... | true | 26 | 28 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 2 | 2 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 39 | 42 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 42 | 42 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 42 | 44 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 45 | 45 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 45 | 47 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 51 | 53 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 56 | 58 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 58 | 58 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 58 | 66 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 62 | 62 |
|
||||
| test.c:34:16:34:21 | ... < ... | true | 34 | 34 |
|
||||
| test.c:42:16:42:21 | ... < ... | true | 42 | 42 |
|
||||
| test.c:42:16:42:21 | ... < ... | true | 42 | 44 |
|
||||
| test.c:42:16:42:21 | ... < ... | true | 45 | 45 |
|
||||
| test.c:42:16:42:21 | ... < ... | true | 45 | 47 |
|
||||
| test.c:42:16:42:21 | ... < ... | true | 51 | 53 |
|
||||
| test.c:44:12:44:16 | ... > ... | false | 42 | 42 |
|
||||
| test.c:44:12:44:16 | ... > ... | false | 51 | 53 |
|
||||
| test.c:44:12:44:16 | ... > ... | true | 45 | 45 |
|
||||
| test.c:44:12:44:16 | ... > ... | true | 45 | 47 |
|
||||
| test.c:45:16:45:20 | ... > ... | true | 45 | 47 |
|
||||
| test.c:58:9:58:14 | ... == ... | false | 58 | 58 |
|
||||
| test.c:58:9:58:14 | ... == ... | false | 62 | 62 |
|
||||
| test.c:58:9:58:23 | ... \|\| ... | false | 62 | 62 |
|
||||
| test.c:58:19:58:23 | ... < ... | false | 62 | 62 |
|
||||
| test.c:75:9:75:14 | ... == ... | false | 78 | 79 |
|
||||
| test.c:75:9:75:14 | ... == ... | true | 75 | 77 |
|
||||
| test.c:85:8:85:13 | ... == ... | true | 85 | 85 |
|
||||
| test.c:85:8:85:13 | ... == ... | true | 86 | 86 |
|
||||
| test.c:85:8:85:23 | ... && ... | true | 86 | 86 |
|
||||
| test.c:85:18:85:23 | ... != ... | true | 86 | 86 |
|
||||
| test.c:94:11:94:16 | ... != ... | false | 70 | 70 |
|
||||
| test.c:94:11:94:16 | ... != ... | false | 99 | 102 |
|
||||
| test.c:94:11:94:16 | ... != ... | false | 102 | 102 |
|
||||
| test.c:94:11:94:16 | ... != ... | false | 107 | 109 |
|
||||
| test.c:94:11:94:16 | ... != ... | false | 109 | 109 |
|
||||
| test.c:94:11:94:16 | ... != ... | false | 109 | 117 |
|
||||
| test.c:94:11:94:16 | ... != ... | false | 113 | 113 |
|
||||
| test.c:94:11:94:16 | ... != ... | true | 94 | 96 |
|
||||
| test.c:102:16:102:21 | ... < ... | false | 70 | 70 |
|
||||
| test.c:102:16:102:21 | ... < ... | false | 107 | 109 |
|
||||
| test.c:102:16:102:21 | ... < ... | false | 109 | 109 |
|
||||
| test.c:102:16:102:21 | ... < ... | false | 109 | 117 |
|
||||
| test.c:102:16:102:21 | ... < ... | false | 113 | 113 |
|
||||
| test.c:102:16:102:21 | ... < ... | true | 102 | 102 |
|
||||
| test.c:109:9:109:14 | ... == ... | false | 109 | 109 |
|
||||
| test.c:109:9:109:14 | ... == ... | false | 113 | 113 |
|
||||
| test.c:109:9:109:23 | ... \|\| ... | false | 113 | 113 |
|
||||
| test.c:109:19:109:23 | ... < ... | false | 113 | 113 |
|
||||
| test.c:126:7:126:7 | 1 | true | 126 | 126 |
|
||||
| test.c:126:7:126:7 | 1 | true | 126 | 128 |
|
||||
| test.c:126:7:126:7 | 1 | true | 131 | 131 |
|
||||
| test.c:126:7:126:7 | 1 | true | 131 | 132 |
|
||||
| test.c:126:7:126:7 | 1 | true | 134 | 123 |
|
||||
| test.c:126:7:126:28 | ... && ... | true | 126 | 128 |
|
||||
| test.c:126:12:126:26 | call to test3_condition | true | 126 | 128 |
|
||||
| test.c:131:7:131:7 | b | true | 131 | 132 |
|
||||
| test.c:137:7:137:7 | 0 | false | 142 | 136 |
|
||||
| test.c:146:7:146:8 | ! ... | true | 146 | 147 |
|
||||
| test.c:146:8:146:8 | x | false | 146 | 147 |
|
||||
| test.c:152:8:152:8 | p | true | 152 | 154 |
|
||||
| test.c:158:8:158:9 | ! ... | true | 158 | 160 |
|
||||
| test.c:158:9:158:9 | p | false | 158 | 160 |
|
||||
| test.c:164:8:164:8 | s | true | 164 | 166 |
|
||||
| test.c:170:8:170:9 | ! ... | true | 170 | 172 |
|
||||
| test.c:170:9:170:9 | s | false | 170 | 172 |
|
||||
| test.c:176:8:176:15 | ! ... | true | 176 | 178 |
|
||||
| test.c:176:10:176:14 | ... < ... | false | 176 | 178 |
|
||||
| test.c:182:8:182:34 | ! ... | true | 182 | 184 |
|
||||
| test.c:182:10:182:20 | ... >= ... | true | 181 | 182 |
|
||||
| test.c:182:10:182:20 | ... >= ... | true | 182 | 182 |
|
||||
| test.c:182:10:182:33 | ... && ... | false | 182 | 184 |
|
||||
| test.c:182:10:182:33 | ... && ... | true | 181 | 182 |
|
||||
| test.c:182:25:182:33 | ... < ... | true | 181 | 182 |
|
||||
| test.c:190:7:190:8 | ! ... | true | 190 | 192 |
|
||||
| test.c:190:8:190:8 | c | false | 190 | 192 |
|
||||
| test.c:198:7:198:8 | ! ... | true | 198 | 200 |
|
||||
| test.c:198:8:198:8 | b | false | 198 | 200 |
|
||||
| test.c:206:7:206:8 | ! ... | true | 206 | 208 |
|
||||
| test.c:206:8:206:8 | c | false | 206 | 208 |
|
||||
| test.cpp:18:8:18:10 | call to get | true | 19 | 19 |
|
||||
| test.cpp:31:7:31:13 | ... == ... | false | 30 | 30 |
|
||||
| test.cpp:31:7:31:13 | ... == ... | false | 34 | 34 |
|
||||
| test.cpp:31:7:31:13 | ... == ... | true | 30 | 30 |
|
||||
| test.cpp:31:7:31:13 | ... == ... | true | 31 | 32 |
|
||||
| test.cpp:42:13:42:20 | call to getABool | true | 43 | 45 |
|
||||
| test.cpp:61:10:61:10 | i | Case[0] | 62 | 64 |
|
||||
| test.cpp:61:10:61:10 | i | Case[1] | 65 | 66 |
|
||||
| test.cpp:74:10:74:10 | i | Case[0..10] | 75 | 77 |
|
||||
| test.cpp:74:10:74:10 | i | Case[11..20] | 78 | 79 |
|
||||
| test.cpp:93:6:93:6 | c | true | 93 | 94 |
|
||||
| test.cpp:99:6:99:6 | f | true | 99 | 100 |
|
||||
| test.cpp:105:6:105:14 | ... != ... | true | 105 | 106 |
|
||||
| test.cpp:111:6:111:14 | ... != ... | true | 111 | 112 |
|
||||
| test.cpp:122:9:122:9 | b | true | 123 | 125 |
|
||||
| test.cpp:122:9:122:9 | b | true | 125 | 125 |
|
||||
| test.cpp:125:13:125:20 | ! ... | true | 125 | 125 |
|
||||
| test.cpp:125:14:125:17 | call to safe | false | 125 | 125 |
|
||||
| test.cpp:131:6:131:21 | call to __builtin_expect | true | 131 | 132 |
|
||||
| test.cpp:135:6:135:21 | call to __builtin_expect | true | 135 | 136 |
|
||||
| test.cpp:141:6:141:21 | call to __builtin_expect | true | 141 | 142 |
|
||||
| test.cpp:145:6:145:21 | call to __builtin_expect | true | 145 | 146 |
|
||||
| test.cpp:152:7:152:8 | ! ... | true | 152 | 153 |
|
||||
| test.cpp:152:8:152:8 | b | false | 152 | 153 |
|
||||
| test.cpp:160:7:160:8 | ! ... | true | 160 | 162 |
|
||||
| test.cpp:160:8:160:8 | c | false | 160 | 162 |
|
||||
| test.cpp:168:7:168:8 | ! ... | true | 168 | 170 |
|
||||
| test.cpp:168:8:168:8 | b | false | 168 | 170 |
|
||||
| test.cpp:176:7:176:8 | ! ... | true | 176 | 178 |
|
||||
| test.cpp:176:8:176:8 | c | false | 176 | 178 |
|
||||
| test.cpp:182:6:182:16 | ! ... | false | 185 | 188 |
|
||||
| test.cpp:182:6:182:16 | ! ... | true | 182 | 184 |
|
||||
| test.cpp:182:8:182:9 | b1 | true | 181 | 182 |
|
||||
| test.cpp:182:8:182:9 | b1 | true | 182 | 182 |
|
||||
| test.cpp:182:8:182:15 | ... && ... | false | 182 | 184 |
|
||||
| test.cpp:182:8:182:15 | ... && ... | true | 181 | 182 |
|
||||
| test.cpp:182:8:182:15 | ... && ... | true | 185 | 188 |
|
||||
| test.cpp:182:14:182:15 | b2 | true | 181 | 182 |
|
||||
| test.cpp:193:6:193:16 | ! ... | false | 197 | 199 |
|
||||
| test.cpp:193:6:193:16 | ! ... | true | 193 | 196 |
|
||||
| test.cpp:193:8:193:9 | b1 | false | 192 | 193 |
|
||||
| test.cpp:193:8:193:9 | b1 | false | 193 | 193 |
|
||||
| test.cpp:193:8:193:15 | ... \|\| ... | false | 192 | 193 |
|
||||
| test.cpp:193:8:193:15 | ... \|\| ... | false | 193 | 196 |
|
||||
| test.cpp:193:8:193:15 | ... \|\| ... | true | 197 | 199 |
|
||||
| test.cpp:193:14:193:15 | b2 | false | 192 | 193 |
|
||||
| test.cpp:211:9:211:15 | ... == ... | true | 211 | 212 |
|
||||
| test.cpp:214:9:214:17 | ... == ... | true | 214 | 215 |
|
||||
| test.cpp:217:9:217:15 | ... == ... | true | 217 | 218 |
|
||||
| test.cpp:220:9:220:14 | ... == ... | true | 220 | 221 |
|
||||
| test.cpp:223:9:223:16 | ... == ... | true | 223 | 224 |
|
||||
| test.cpp:226:9:226:14 | ... == ... | true | 226 | 227 |
|
||||
| test.cpp:229:9:229:14 | ... == ... | true | 229 | 230 |
|
||||
| test.cpp:232:9:232:18 | ... == ... | true | 232 | 233 |
|
||||
| test.cpp:235:9:235:17 | ... == ... | true | 235 | 236 |
|
||||
| test.cpp:238:9:238:17 | ... == ... | true | 238 | 239 |
|
||||
| test.cpp:241:9:241:17 | ... == ... | true | 241 | 241 |
|
||||
| test.cpp:241:9:241:17 | ... == ... | true | 241 | 242 |
|
||||
| test.cpp:241:9:241:30 | ... && ... | true | 241 | 241 |
|
||||
| test.cpp:241:9:241:30 | ... && ... | true | 241 | 242 |
|
||||
| test.cpp:241:9:241:43 | ... && ... | true | 241 | 242 |
|
||||
| test.cpp:241:22:241:30 | ... == ... | true | 241 | 241 |
|
||||
| test.cpp:241:22:241:30 | ... == ... | true | 241 | 242 |
|
||||
| test.cpp:241:35:241:43 | ... == ... | true | 241 | 242 |
|
||||
| test.c:7:9:7:13 | ... > ... | false | test.c:10:12:11:14 | { ... } |
|
||||
| test.c:7:9:7:13 | ... > ... | true | test.c:7:16:9:14 | { ... } |
|
||||
| test.c:17:8:17:12 | ... < ... | true | test.c:17:17:17:21 | y |
|
||||
| test.c:17:8:17:12 | ... < ... | true | test.c:18:9:18:14 | ExprStmt |
|
||||
| test.c:17:8:17:21 | ... && ... | true | test.c:18:9:18:14 | ExprStmt |
|
||||
| test.c:17:17:17:21 | ... > ... | true | test.c:18:9:18:14 | ExprStmt |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:2:5:2:8 | test |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:31:5:34:13 | ExprStmt |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:34:16:34:21 | j |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:34:29:34:26 | { ... } |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:39:5:42:13 | ExprStmt |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:42:5:42:26 | label ...: |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:42:16:42:21 | j |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:42:29:44:16 | { ... } |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:45:13:45:20 | if (...) ... |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:45:23:47:22 | { ... } |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:51:14:53:21 | { ... } |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:56:5:58:14 | label ...: |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:58:19:58:23 | y |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:58:26:66:12 | { ... } |
|
||||
| test.c:26:11:26:15 | ... > ... | false | test.c:62:9:62:16 | return ... |
|
||||
| test.c:26:11:26:15 | ... > ... | true | test.c:26:18:28:11 | { ... } |
|
||||
| test.c:34:16:34:21 | ... < ... | false | test.c:2:5:2:8 | test |
|
||||
| test.c:34:16:34:21 | ... < ... | false | test.c:39:5:42:13 | ExprStmt |
|
||||
| test.c:34:16:34:21 | ... < ... | false | test.c:42:5:42:26 | label ...: |
|
||||
| test.c:34:16:34:21 | ... < ... | false | test.c:42:16:42:21 | j |
|
||||
| test.c:34:16:34:21 | ... < ... | false | test.c:42:29:44:16 | { ... } |
|
||||
| test.c:34:16:34:21 | ... < ... | false | test.c:45:13:45:20 | if (...) ... |
|
||||
| test.c:34:16:34:21 | ... < ... | false | test.c:45:23:47:22 | { ... } |
|
||||
| test.c:34:16:34:21 | ... < ... | false | test.c:51:14:53:21 | { ... } |
|
||||
| test.c:34:16:34:21 | ... < ... | false | test.c:56:5:58:14 | label ...: |
|
||||
| test.c:34:16:34:21 | ... < ... | false | test.c:58:19:58:23 | y |
|
||||
| test.c:34:16:34:21 | ... < ... | false | test.c:58:26:66:12 | { ... } |
|
||||
| test.c:34:16:34:21 | ... < ... | false | test.c:62:9:62:16 | return ... |
|
||||
| test.c:34:16:34:21 | ... < ... | true | test.c:34:29:34:26 | { ... } |
|
||||
| test.c:42:16:42:21 | ... < ... | true | test.c:42:5:42:26 | label ...: |
|
||||
| test.c:42:16:42:21 | ... < ... | true | test.c:42:29:44:16 | { ... } |
|
||||
| test.c:42:16:42:21 | ... < ... | true | test.c:45:13:45:20 | if (...) ... |
|
||||
| test.c:42:16:42:21 | ... < ... | true | test.c:45:23:47:22 | { ... } |
|
||||
| test.c:42:16:42:21 | ... < ... | true | test.c:51:14:53:21 | { ... } |
|
||||
| test.c:44:12:44:16 | ... > ... | false | test.c:42:5:42:26 | label ...: |
|
||||
| test.c:44:12:44:16 | ... > ... | false | test.c:51:14:53:21 | { ... } |
|
||||
| test.c:44:12:44:16 | ... > ... | true | test.c:45:13:45:20 | if (...) ... |
|
||||
| test.c:44:12:44:16 | ... > ... | true | test.c:45:23:47:22 | { ... } |
|
||||
| test.c:45:16:45:20 | ... > ... | true | test.c:45:23:47:22 | { ... } |
|
||||
| test.c:58:9:58:14 | ... == ... | false | test.c:58:19:58:23 | y |
|
||||
| test.c:58:9:58:14 | ... == ... | false | test.c:62:9:62:16 | return ... |
|
||||
| test.c:58:9:58:23 | ... \|\| ... | false | test.c:62:9:62:16 | return ... |
|
||||
| test.c:58:19:58:23 | ... < ... | false | test.c:62:9:62:16 | return ... |
|
||||
| test.c:75:9:75:14 | ... == ... | false | test.c:78:12:79:14 | { ... } |
|
||||
| test.c:75:9:75:14 | ... == ... | true | test.c:75:17:77:14 | { ... } |
|
||||
| test.c:85:8:85:13 | ... == ... | true | test.c:85:18:85:23 | y |
|
||||
| test.c:85:8:85:13 | ... == ... | true | test.c:86:9:86:14 | ExprStmt |
|
||||
| test.c:85:8:85:23 | ... && ... | true | test.c:86:9:86:14 | ExprStmt |
|
||||
| test.c:85:18:85:23 | ... != ... | true | test.c:86:9:86:14 | ExprStmt |
|
||||
| test.c:94:11:94:16 | ... != ... | false | test.c:70:5:70:9 | test2 |
|
||||
| test.c:94:11:94:16 | ... != ... | false | test.c:99:5:102:13 | ExprStmt |
|
||||
| test.c:94:11:94:16 | ... != ... | false | test.c:102:16:102:21 | j |
|
||||
| test.c:94:11:94:16 | ... != ... | false | test.c:102:29:102:26 | { ... } |
|
||||
| test.c:94:11:94:16 | ... != ... | false | test.c:107:5:109:14 | ExprStmt |
|
||||
| test.c:94:11:94:16 | ... != ... | false | test.c:109:19:109:23 | y |
|
||||
| test.c:94:11:94:16 | ... != ... | false | test.c:109:26:117:12 | { ... } |
|
||||
| test.c:94:11:94:16 | ... != ... | false | test.c:113:9:113:16 | return ... |
|
||||
| test.c:94:11:94:16 | ... != ... | true | test.c:94:19:96:11 | { ... } |
|
||||
| test.c:102:16:102:21 | ... < ... | false | test.c:70:5:70:9 | test2 |
|
||||
| test.c:102:16:102:21 | ... < ... | false | test.c:107:5:109:14 | ExprStmt |
|
||||
| test.c:102:16:102:21 | ... < ... | false | test.c:109:19:109:23 | y |
|
||||
| test.c:102:16:102:21 | ... < ... | false | test.c:109:26:117:12 | { ... } |
|
||||
| test.c:102:16:102:21 | ... < ... | false | test.c:113:9:113:16 | return ... |
|
||||
| test.c:102:16:102:21 | ... < ... | true | test.c:102:29:102:26 | { ... } |
|
||||
| test.c:109:9:109:14 | ... == ... | false | test.c:109:19:109:23 | y |
|
||||
| test.c:109:9:109:14 | ... == ... | false | test.c:113:9:113:16 | return ... |
|
||||
| test.c:109:9:109:23 | ... \|\| ... | false | test.c:113:9:113:16 | return ... |
|
||||
| test.c:109:19:109:23 | ... < ... | false | test.c:113:9:113:16 | return ... |
|
||||
| test.c:126:7:126:7 | 1 | true | test.c:126:12:126:26 | call to test3_condition |
|
||||
| test.c:126:7:126:7 | 1 | true | test.c:126:31:128:16 | { ... } |
|
||||
| test.c:126:7:126:7 | 1 | true | test.c:131:3:131:7 | if (...) ... |
|
||||
| test.c:126:7:126:7 | 1 | true | test.c:131:10:132:16 | { ... } |
|
||||
| test.c:126:7:126:7 | 1 | true | test.c:134:1:123:10 | return ... |
|
||||
| test.c:126:7:126:28 | ... && ... | true | test.c:126:31:128:16 | { ... } |
|
||||
| test.c:126:12:126:26 | call to test3_condition | true | test.c:126:31:128:16 | { ... } |
|
||||
| test.c:131:7:131:7 | b | true | test.c:131:10:132:16 | { ... } |
|
||||
| test.c:137:7:137:7 | 0 | false | test.c:142:3:136:10 | return ... |
|
||||
| test.c:146:7:146:8 | ! ... | true | test.c:146:11:147:9 | { ... } |
|
||||
| test.c:146:8:146:8 | x | false | test.c:146:11:147:9 | { ... } |
|
||||
| test.c:152:8:152:8 | p | true | test.c:152:11:154:5 | { ... } |
|
||||
| test.c:158:8:158:9 | ! ... | true | test.c:158:12:160:5 | { ... } |
|
||||
| test.c:158:9:158:9 | p | false | test.c:158:12:160:5 | { ... } |
|
||||
| test.c:164:8:164:8 | s | true | test.c:164:11:166:5 | { ... } |
|
||||
| test.c:170:8:170:9 | ! ... | true | test.c:170:12:172:5 | { ... } |
|
||||
| test.c:170:9:170:9 | s | false | test.c:170:12:172:5 | { ... } |
|
||||
| test.c:176:8:176:15 | ! ... | true | test.c:176:18:178:5 | { ... } |
|
||||
| test.c:176:10:176:14 | ... < ... | false | test.c:176:18:178:5 | { ... } |
|
||||
| test.c:182:8:182:34 | ! ... | true | test.c:182:37:184:5 | { ... } |
|
||||
| test.c:182:10:182:20 | ... >= ... | true | test.c:181:25:182:20 | { ... } |
|
||||
| test.c:182:10:182:20 | ... >= ... | true | test.c:182:25:182:33 | foo |
|
||||
| test.c:182:10:182:33 | ... && ... | false | test.c:182:37:184:5 | { ... } |
|
||||
| test.c:182:10:182:33 | ... && ... | true | test.c:181:25:182:20 | { ... } |
|
||||
| test.c:182:25:182:33 | ... < ... | true | test.c:181:25:182:20 | { ... } |
|
||||
| test.c:190:7:190:8 | ! ... | true | test.c:190:11:192:3 | { ... } |
|
||||
| test.c:190:8:190:8 | c | false | test.c:190:11:192:3 | { ... } |
|
||||
| test.c:198:7:198:8 | ! ... | true | test.c:198:11:200:3 | { ... } |
|
||||
| test.c:198:8:198:8 | b | false | test.c:198:11:200:3 | { ... } |
|
||||
| test.c:206:7:206:8 | ! ... | true | test.c:206:11:208:3 | { ... } |
|
||||
| test.c:206:8:206:8 | c | false | test.c:206:11:208:3 | { ... } |
|
||||
| test.c:215:6:215:18 | call to __builtin_expect | true | test.c:215:21:217:5 | { ... } |
|
||||
| test.c:219:9:219:22 | call to __builtin_expect | true | test.c:219:25:221:5 | { ... } |
|
||||
| test.cpp:18:8:18:10 | call to get | true | test.cpp:19:5:19:14 | ExprStmt |
|
||||
| test.cpp:31:7:31:13 | ... == ... | false | test.cpp:30:6:30:16 | doSomething |
|
||||
| test.cpp:31:7:31:13 | ... == ... | false | test.cpp:34:1:34:1 | return ... |
|
||||
| test.cpp:31:7:31:13 | ... == ... | true | test.cpp:30:6:30:16 | doSomething |
|
||||
| test.cpp:31:7:31:13 | ... == ... | true | test.cpp:31:16:32:21 | { ... } |
|
||||
| test.cpp:42:13:42:20 | call to getABool | true | test.cpp:43:9:45:23 | { ... } |
|
||||
| test.cpp:61:10:61:10 | i | Case[0] | test.cpp:62:5:64:12 | case ...: |
|
||||
| test.cpp:61:10:61:10 | i | Case[1] | test.cpp:65:5:66:10 | case ...: |
|
||||
| test.cpp:74:10:74:10 | i | Case[0..10] | test.cpp:75:5:77:12 | case ...: |
|
||||
| test.cpp:74:10:74:10 | i | Case[11..20] | test.cpp:78:5:79:10 | case ...: |
|
||||
| test.cpp:93:6:93:6 | c | true | test.cpp:93:9:94:7 | { ... } |
|
||||
| test.cpp:99:6:99:6 | f | true | test.cpp:99:9:100:7 | { ... } |
|
||||
| test.cpp:105:6:105:14 | ... != ... | true | test.cpp:105:17:106:7 | { ... } |
|
||||
| test.cpp:111:6:111:14 | ... != ... | true | test.cpp:111:17:112:7 | { ... } |
|
||||
| test.cpp:122:9:122:9 | b | true | test.cpp:123:5:125:20 | { ... } |
|
||||
| test.cpp:122:9:122:9 | b | true | test.cpp:125:23:125:29 | return ... |
|
||||
| test.cpp:125:13:125:20 | ! ... | true | test.cpp:125:23:125:29 | return ... |
|
||||
| test.cpp:125:14:125:17 | call to safe | false | test.cpp:125:23:125:29 | return ... |
|
||||
| test.cpp:131:6:131:21 | call to __builtin_expect | true | test.cpp:131:40:132:9 | { ... } |
|
||||
| test.cpp:135:6:135:21 | call to __builtin_expect | true | test.cpp:135:40:136:9 | { ... } |
|
||||
| test.cpp:141:6:141:21 | call to __builtin_expect | true | test.cpp:141:36:142:9 | { ... } |
|
||||
| test.cpp:145:6:145:21 | call to __builtin_expect | true | test.cpp:145:36:146:9 | { ... } |
|
||||
| test.cpp:152:7:152:8 | ! ... | true | test.cpp:152:11:153:9 | { ... } |
|
||||
| test.cpp:152:8:152:8 | b | false | test.cpp:152:11:153:9 | { ... } |
|
||||
| test.cpp:160:7:160:8 | ! ... | true | test.cpp:160:11:162:3 | { ... } |
|
||||
| test.cpp:160:8:160:8 | c | false | test.cpp:160:11:162:3 | { ... } |
|
||||
| test.cpp:168:7:168:8 | ! ... | true | test.cpp:168:11:170:3 | { ... } |
|
||||
| test.cpp:168:8:168:8 | b | false | test.cpp:168:11:170:3 | { ... } |
|
||||
| test.cpp:176:7:176:8 | ! ... | true | test.cpp:176:11:178:3 | { ... } |
|
||||
| test.cpp:176:8:176:8 | c | false | test.cpp:176:11:178:3 | { ... } |
|
||||
| test.cpp:182:6:182:16 | ! ... | false | test.cpp:185:10:188:7 | { ... } |
|
||||
| test.cpp:182:6:182:16 | ! ... | true | test.cpp:182:19:184:7 | { ... } |
|
||||
| test.cpp:182:8:182:9 | b1 | true | test.cpp:181:41:182:9 | { ... } |
|
||||
| test.cpp:182:8:182:9 | b1 | true | test.cpp:182:14:182:15 | b2 |
|
||||
| test.cpp:182:8:182:15 | ... && ... | false | test.cpp:182:19:184:7 | { ... } |
|
||||
| test.cpp:182:8:182:15 | ... && ... | true | test.cpp:181:41:182:9 | { ... } |
|
||||
| test.cpp:182:8:182:15 | ... && ... | true | test.cpp:185:10:188:7 | { ... } |
|
||||
| test.cpp:182:14:182:15 | b2 | true | test.cpp:181:41:182:9 | { ... } |
|
||||
| test.cpp:193:6:193:16 | ! ... | false | test.cpp:197:10:199:7 | { ... } |
|
||||
| test.cpp:193:6:193:16 | ! ... | true | test.cpp:193:19:196:7 | { ... } |
|
||||
| test.cpp:193:8:193:9 | b1 | false | test.cpp:192:40:193:9 | { ... } |
|
||||
| test.cpp:193:8:193:9 | b1 | false | test.cpp:193:14:193:15 | b2 |
|
||||
| test.cpp:193:8:193:15 | ... \|\| ... | false | test.cpp:192:40:193:9 | { ... } |
|
||||
| test.cpp:193:8:193:15 | ... \|\| ... | false | test.cpp:193:19:196:7 | { ... } |
|
||||
| test.cpp:193:8:193:15 | ... \|\| ... | true | test.cpp:197:10:199:7 | { ... } |
|
||||
| test.cpp:193:14:193:15 | b2 | false | test.cpp:192:40:193:9 | { ... } |
|
||||
| test.cpp:211:9:211:15 | ... == ... | true | test.cpp:211:18:212:13 | { ... } |
|
||||
| test.cpp:214:9:214:17 | ... == ... | true | test.cpp:214:20:215:13 | { ... } |
|
||||
| test.cpp:217:9:217:15 | ... == ... | true | test.cpp:217:18:218:13 | { ... } |
|
||||
| test.cpp:220:9:220:14 | ... == ... | true | test.cpp:220:17:221:13 | { ... } |
|
||||
| test.cpp:223:9:223:16 | ... == ... | true | test.cpp:223:19:224:13 | { ... } |
|
||||
| test.cpp:226:9:226:14 | ... == ... | true | test.cpp:226:17:227:13 | { ... } |
|
||||
| test.cpp:229:9:229:14 | ... == ... | true | test.cpp:229:17:230:13 | { ... } |
|
||||
| test.cpp:232:9:232:18 | ... == ... | true | test.cpp:232:21:233:13 | { ... } |
|
||||
| test.cpp:235:9:235:17 | ... == ... | true | test.cpp:235:20:236:13 | { ... } |
|
||||
| test.cpp:238:9:238:17 | ... == ... | true | test.cpp:238:20:239:13 | { ... } |
|
||||
| test.cpp:241:9:241:17 | ... == ... | true | test.cpp:241:22:241:30 | ms |
|
||||
| test.cpp:241:9:241:17 | ... == ... | true | test.cpp:241:35:241:43 | ms |
|
||||
| test.cpp:241:9:241:17 | ... == ... | true | test.cpp:241:46:242:13 | { ... } |
|
||||
| test.cpp:241:9:241:30 | ... && ... | true | test.cpp:241:35:241:43 | ms |
|
||||
| test.cpp:241:9:241:30 | ... && ... | true | test.cpp:241:46:242:13 | { ... } |
|
||||
| test.cpp:241:9:241:43 | ... && ... | true | test.cpp:241:46:242:13 | { ... } |
|
||||
| test.cpp:241:22:241:30 | ... == ... | true | test.cpp:241:35:241:43 | ms |
|
||||
| test.cpp:241:22:241:30 | ... == ... | true | test.cpp:241:46:242:13 | { ... } |
|
||||
| test.cpp:241:35:241:43 | ... == ... | true | test.cpp:241:46:242:13 | { ... } |
|
||||
| test.cpp:247:6:247:18 | ... == ... | false | test.cpp:249:10:251:3 | { ... } |
|
||||
| test.cpp:247:6:247:18 | ... == ... | true | test.cpp:247:21:249:3 | { ... } |
|
||||
| test.cpp:253:6:253:18 | ... != ... | false | test.cpp:255:10:257:3 | { ... } |
|
||||
| test.cpp:253:6:253:18 | ... != ... | true | test.cpp:253:21:255:3 | { ... } |
|
||||
| test.cpp:260:6:260:18 | ... == ... | false | test.cpp:262:10:264:3 | { ... } |
|
||||
| test.cpp:260:6:260:18 | ... == ... | true | test.cpp:260:21:262:3 | { ... } |
|
||||
| test.cpp:266:6:266:18 | ... != ... | false | test.cpp:268:10:270:3 | { ... } |
|
||||
| test.cpp:266:6:266:18 | ... != ... | true | test.cpp:266:21:268:3 | { ... } |
|
||||
| test.cpp:273:6:273:17 | ... == ... | false | test.cpp:275:10:277:3 | { ... } |
|
||||
| test.cpp:273:6:273:17 | ... == ... | true | test.cpp:273:20:275:3 | { ... } |
|
||||
| test.cpp:279:6:279:17 | ... != ... | false | test.cpp:281:10:283:3 | { ... } |
|
||||
| test.cpp:279:6:279:17 | ... != ... | true | test.cpp:279:20:281:3 | { ... } |
|
||||
| test.cpp:287:6:287:19 | ... == ... | false | test.cpp:289:10:291:3 | { ... } |
|
||||
| test.cpp:287:6:287:19 | ... == ... | true | test.cpp:287:22:289:3 | { ... } |
|
||||
| test.cpp:293:6:293:19 | ... != ... | false | test.cpp:295:10:297:3 | { ... } |
|
||||
| test.cpp:293:6:293:19 | ... != ... | true | test.cpp:293:22:295:3 | { ... } |
|
||||
| test.cpp:300:6:300:19 | ... == ... | false | test.cpp:302:10:304:3 | { ... } |
|
||||
| test.cpp:300:6:300:19 | ... == ... | true | test.cpp:300:22:302:3 | { ... } |
|
||||
| test.cpp:306:6:306:19 | ... != ... | false | test.cpp:308:10:310:3 | { ... } |
|
||||
| test.cpp:306:6:306:19 | ... != ... | true | test.cpp:306:22:308:3 | { ... } |
|
||||
| test.cpp:312:6:312:18 | ... == ... | false | test.cpp:314:10:316:3 | { ... } |
|
||||
| test.cpp:312:6:312:18 | ... == ... | true | test.cpp:312:21:314:3 | { ... } |
|
||||
| test.cpp:318:6:318:18 | ... != ... | false | test.cpp:320:10:322:3 | { ... } |
|
||||
| test.cpp:318:6:318:18 | ... != ... | true | test.cpp:318:21:320:3 | { ... } |
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
from GuardCondition guard, AbstractValue value, int start, int end
|
||||
where
|
||||
exists(BasicBlock block |
|
||||
guard.valueControls(block, value) and
|
||||
block.hasLocationInfo(_, start, _, end, _)
|
||||
)
|
||||
select guard, value, start, end
|
||||
from GuardCondition guard, AbstractValue value, BasicBlock block
|
||||
where guard.valueControls(block, value)
|
||||
select guard, value, block
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,31 +8,23 @@ import cpp
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
query predicate binary(
|
||||
GuardCondition guard, Expr left, string op, Expr right, int k, int start, int end
|
||||
GuardCondition guard, Expr left, string op, Expr right, int k, BasicBlock block
|
||||
) {
|
||||
exists(BasicBlock block |
|
||||
guard.ensuresLt(left, right, k, block, true) and op = "<"
|
||||
or
|
||||
guard.ensuresLt(left, right, k, block, false) and op = ">="
|
||||
or
|
||||
guard.ensuresEq(left, right, k, block, true) and op = "=="
|
||||
or
|
||||
guard.ensuresEq(left, right, k, block, false) and op = "!="
|
||||
|
|
||||
block.hasLocationInfo(_, start, _, end, _)
|
||||
)
|
||||
guard.ensuresLt(left, right, k, block, true) and op = "<"
|
||||
or
|
||||
guard.ensuresLt(left, right, k, block, false) and op = ">="
|
||||
or
|
||||
guard.ensuresEq(left, right, k, block, true) and op = "=="
|
||||
or
|
||||
guard.ensuresEq(left, right, k, block, false) and op = "!="
|
||||
}
|
||||
|
||||
query predicate unary(GuardCondition guard, Expr left, string op, int k, int start, int end) {
|
||||
exists(BasicBlock block |
|
||||
guard.ensuresLt(left, k, block, true) and op = "<"
|
||||
or
|
||||
guard.ensuresLt(left, k, block, false) and op = ">="
|
||||
or
|
||||
guard.ensuresEq(left, k, block, true) and op = "=="
|
||||
or
|
||||
guard.ensuresEq(left, k, block, false) and op = "!="
|
||||
|
|
||||
block.hasLocationInfo(_, start, _, end, _)
|
||||
)
|
||||
query predicate unary(GuardCondition guard, Expr left, string op, int k, BasicBlock block) {
|
||||
guard.ensuresLt(left, k, block, true) and op = "<"
|
||||
or
|
||||
guard.ensuresLt(left, k, block, false) and op = ">="
|
||||
or
|
||||
guard.ensuresEq(left, k, block, true) and op = "=="
|
||||
or
|
||||
guard.ensuresEq(left, k, block, false) and op = "!="
|
||||
}
|
||||
|
||||
@@ -206,4 +206,17 @@ void test14(int a, int b) {
|
||||
if (!c) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# define likely(x) __builtin_expect(!!(x), 1)
|
||||
|
||||
void test15(int a, int b)
|
||||
{
|
||||
if (likely(a > b)) {
|
||||
|
||||
}
|
||||
|
||||
if (likely(a > 42)) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,3 +242,82 @@ int test_types(signed char sc, unsigned long ul, float f, double d, bool b, Myst
|
||||
ctr++;
|
||||
}
|
||||
}
|
||||
|
||||
void test_cmp_implies(int a, int b) {
|
||||
if((a == b) == 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
if((a == b) != 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
if((a != b) == 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
if((a != b) != 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
if((a < b) == 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
if((a < b) != 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void test_cmp_implies_unary(int a) {
|
||||
if((a == 42) == 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
if((a == 42) != 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
if((a != 42) == 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
if((a != 42) != 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
if((a < 42) == 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
if((a < 42) != 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,7 @@
|
||||
| main.cpp:3:5:3:5 | x | Poor global variable name 'x'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo). |
|
||||
| main.cpp:4:5:4:6 | ys | Poor global variable name 'ys'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo). |
|
||||
| main.cpp:9:5:9:6 | v1 | Poor global variable name 'v1'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo). |
|
||||
| main.cpp:10:5:10:6 | v2 | Poor global variable name 'v2'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo). |
|
||||
| main.cpp:12:5:12:5 | v3 | Poor global variable name 'v3'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo). |
|
||||
| main.cpp:14:5:14:5 | v4 | Poor global variable name 'v4'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo). |
|
||||
| main.cpp:16:5:16:5 | v5 | Poor global variable name 'v5'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo). |
|
||||
|
||||
@@ -5,3 +5,19 @@ int ys[1000000]; // BAD: too short
|
||||
int descriptive_name; // GOOD: sufficient
|
||||
|
||||
static int z; // GOOD: not a global
|
||||
|
||||
int v1; // BAD: too short
|
||||
int v2; // BAD: too short
|
||||
template <typename T>
|
||||
T v3; // BAD: too short
|
||||
template <typename T>
|
||||
T v4; // BAD: too short
|
||||
template <typename T>
|
||||
T v5; // BAD: too short
|
||||
|
||||
void use_some_fs() {
|
||||
v2 = 100;
|
||||
v4<int> = 200;
|
||||
v5<int> = 300;
|
||||
v5<const char *> = "string";
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
edges
|
||||
| test.c:10:31:10:32 | sscanf output argument | test.c:11:7:11:7 | x | provenance | |
|
||||
| test.cpp:34:15:34:16 | scanf output argument | test.cpp:35:7:35:7 | i | provenance | |
|
||||
| test.cpp:41:19:41:20 | scanf output argument | test.cpp:43:8:43:8 | i | provenance | |
|
||||
| test.cpp:58:19:58:20 | scanf output argument | test.cpp:60:8:60:8 | i | provenance | |
|
||||
@@ -56,6 +57,8 @@ edges
|
||||
| test.cpp:567:35:567:36 | scanf output argument | test.cpp:569:9:569:9 | i | provenance | |
|
||||
| test.cpp:575:30:575:31 | scanf output argument | test.cpp:577:9:577:9 | i | provenance | |
|
||||
nodes
|
||||
| test.c:10:31:10:32 | sscanf output argument | semmle.label | sscanf output argument |
|
||||
| test.c:11:7:11:7 | x | semmle.label | x |
|
||||
| test.cpp:34:15:34:16 | scanf output argument | semmle.label | scanf output argument |
|
||||
| test.cpp:35:7:35:7 | i | semmle.label | i |
|
||||
| test.cpp:41:19:41:20 | scanf output argument | semmle.label | scanf output argument |
|
||||
@@ -186,5 +189,3 @@ subpaths
|
||||
| test.cpp:484:9:484:9 | i | test.cpp:480:25:480:26 | scanf output argument | test.cpp:484:9:484:9 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:480:13:480:17 | call to scanf | call to scanf |
|
||||
| test.cpp:495:8:495:8 | i | test.cpp:491:25:491:26 | scanf output argument | test.cpp:495:8:495:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:491:13:491:17 | call to scanf | call to scanf |
|
||||
| test.cpp:545:8:545:8 | f | test.cpp:541:43:541:44 | sscanf output argument | test.cpp:545:8:545:8 | f | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 3. | test.cpp:541:10:541:15 | call to sscanf | call to sscanf |
|
||||
| test.cpp:569:9:569:9 | i | test.cpp:567:35:567:36 | scanf output argument | test.cpp:569:9:569:9 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:567:23:567:27 | call to scanf | call to scanf |
|
||||
| test.cpp:577:9:577:9 | i | test.cpp:575:30:575:31 | scanf output argument | test.cpp:577:9:577:9 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:575:18:575:22 | call to scanf | call to scanf |
|
||||
|
||||
13
cpp/ql/test/query-tests/Critical/MissingCheckScanf/test.c
Normal file
13
cpp/ql/test/query-tests/Critical/MissingCheckScanf/test.c
Normal file
@@ -0,0 +1,13 @@
|
||||
# define likely(x) __builtin_expect(!!(x), 1)
|
||||
int sscanf(const char *s, const char *format, ...);
|
||||
|
||||
void use(int i);
|
||||
|
||||
void test_likely(const char* s, const char* format)
|
||||
{
|
||||
int x;
|
||||
|
||||
if (likely(sscanf(s, format, &x) == 1)) {
|
||||
use(x); // GOOD
|
||||
}
|
||||
}
|
||||
@@ -566,7 +566,7 @@ void test_scanf_compared_in_conjunct_right(bool b) {
|
||||
int i;
|
||||
bool success = b && scanf("%d", &i) == 1;
|
||||
if(success) {
|
||||
use(i); // GOOD [FALSE POSITIVE]
|
||||
use(i); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,6 +574,6 @@ void test_scanf_compared_in_conjunct_left(bool b) {
|
||||
int i;
|
||||
bool success = scanf("%d", &i) == 1 && b;
|
||||
if(success) {
|
||||
use(i); // GOOD [FALSE POSITIVE]
|
||||
use(i); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,3 +6,4 @@
|
||||
| test.cpp:83:7:83:40 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:78:16:78:36 | call to SSL_get_verify_result | call to SSL_get_verify_result |
|
||||
| test.cpp:87:7:87:38 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:7:57:7:77 | call to SSL_get_verify_result | call to SSL_get_verify_result |
|
||||
| test.cpp:107:13:107:42 | ... \|\| ... | This expression conflates OK and non-OK results from $@. | test.cpp:105:16:105:36 | call to SSL_get_verify_result | call to SSL_get_verify_result |
|
||||
| test.cpp:109:7:109:8 | ok | This expression conflates OK and non-OK results from $@. | test.cpp:105:16:105:36 | call to SSL_get_verify_result | call to SSL_get_verify_result |
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
typedef unsigned long size_t;
|
||||
typedef struct sqlite3 sqlite3;
|
||||
typedef struct sqlite3_stmt sqlite3_stmt;
|
||||
typedef struct sqlite3_str sqlite3_str;
|
||||
|
||||
int snprintf(char *str, size_t size, const char *format, ...);
|
||||
int sqlite3_open(const char *filename, sqlite3 **ppDb);
|
||||
int sqlite3_close(sqlite3*);
|
||||
int sqlite3_exec(sqlite3*, const char *sql, int (*callback)(void*,int,char**,char**), void *, char **errmsg);
|
||||
int sqlite3_prepare_v2(sqlite3 *db, const char *zSql, int nByte, sqlite3_stmt **ppStmt, const char **pzTail);
|
||||
int sqlite3_step(sqlite3_stmt*);
|
||||
int sqlite3_finalize(sqlite3_stmt*);
|
||||
int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
|
||||
sqlite3_str* sqlite3_str_new(sqlite3*);
|
||||
void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...);
|
||||
char* sqlite3_str_finish(sqlite3_str*);
|
||||
|
||||
#define SQLITE_TRANSIENT ((void(*)(void*))-1)
|
||||
|
||||
// Simulate a sensitive value
|
||||
const char* getSensitivePassword() {
|
||||
return "super_secret_password";
|
||||
}
|
||||
|
||||
void storePasswordCleartext(sqlite3* db, const char* password) {
|
||||
// BAD: Storing sensitive data in cleartext
|
||||
char sql[256];
|
||||
// Unsafe: no escaping, for test purposes only
|
||||
snprintf(sql, sizeof(sql), "INSERT INTO users(password) VALUES('%s');", password); // $ Source
|
||||
char* errMsg = 0;
|
||||
sqlite3_exec(db, sql, 0, 0, &errMsg); // $ Alert
|
||||
}
|
||||
|
||||
void storePasswordWithPrepare(sqlite3* db, const char* password) {
|
||||
// BAD: Storing sensitive data in cleartext using sqlite3_prepare
|
||||
char sql[256];
|
||||
snprintf(sql, sizeof(sql), "INSERT INTO users(password) VALUES('%s');", password); // $ Source
|
||||
sqlite3_stmt* stmt = 0;
|
||||
sqlite3_prepare_v2(db, sql, -1, &stmt, 0); // $ Alert
|
||||
sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
|
||||
void storePasswordWithBind(sqlite3* db, const char* password) {
|
||||
// BAD: Storing sensitive data in cleartext using sqlite3_bind_text
|
||||
const char* sql = "INSERT INTO users(password) VALUES(?);";
|
||||
sqlite3_stmt* stmt = 0;
|
||||
sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
|
||||
sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT); // $ Alert
|
||||
sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
|
||||
void storePasswordWithAppendf(sqlite3_str* pStr, const char* password) {
|
||||
// BAD: Storing sensitive data in cleartext using sqlite3_str_appendf
|
||||
sqlite3_str_appendf(pStr, "INSERT INTO users(password) VALUES('%s');", password); // $ Alert
|
||||
}
|
||||
|
||||
// Example sanitizer: hashes the sensitive value before storage
|
||||
void hashSensitiveValue(const char* input, char* output, size_t outSize) {
|
||||
// Dummy hash for illustration (not cryptographically secure)
|
||||
unsigned int hash = 5381;
|
||||
for (const char* p = input; *p; ++p)
|
||||
hash = ((hash << 5) + hash) + (unsigned char)(*p);
|
||||
snprintf(output, outSize, "%u", hash);
|
||||
}
|
||||
|
||||
void storeSanitizedPasswordCleartext(sqlite3* db, const char* password) {
|
||||
// GOOD: Sanitizing sensitive data before storage
|
||||
char hashed[64];
|
||||
hashSensitiveValue(password, hashed, sizeof(hashed));
|
||||
char sql[256];
|
||||
snprintf(sql, sizeof(sql), "INSERT INTO users(password) VALUES('%s');", hashed);
|
||||
char* errMsg = 0;
|
||||
sqlite3_exec(db, sql, 0, 0, &errMsg);
|
||||
}
|
||||
|
||||
void storeSanitizedPasswordWithBind(sqlite3* db, const char* password) {
|
||||
// GOOD: Sanitizing sensitive data before storage with bind
|
||||
char hashed[64];
|
||||
hashSensitiveValue(password, hashed, sizeof(hashed));
|
||||
const char* sql = "INSERT INTO users(password) VALUES(?);";
|
||||
sqlite3_stmt* stmt = 0;
|
||||
sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
|
||||
sqlite3_bind_text(stmt, 1, hashed, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
|
||||
void storeSanitizedPasswordWithAppendf(sqlite3_str* pStr, const char* password) {
|
||||
// GOOD: Sanitizing sensitive data before storage with appendf
|
||||
char hashed[64];
|
||||
hashSensitiveValue(password, hashed, sizeof(hashed));
|
||||
sqlite3_str_appendf(pStr, "INSERT INTO users(password) VALUES('%s');", hashed);
|
||||
}
|
||||
|
||||
int main() {
|
||||
sqlite3* db = 0;
|
||||
sqlite3_open(":memory:", &db);
|
||||
|
||||
// Create table
|
||||
const char* createTableSQL = "CREATE TABLE users(id INTEGER PRIMARY KEY, password TEXT);";
|
||||
sqlite3_exec(db, createTableSQL, 0, 0, 0);
|
||||
|
||||
const char* sensitive = getSensitivePassword();
|
||||
|
||||
storePasswordCleartext(db, sensitive);
|
||||
storePasswordWithPrepare(db, sensitive);
|
||||
storePasswordWithBind(db, sensitive);
|
||||
storeSanitizedPasswordCleartext(db, sensitive);
|
||||
storeSanitizedPasswordWithBind(db, sensitive);
|
||||
|
||||
// If sqlite3_str is available
|
||||
sqlite3_str* pStr = sqlite3_str_new(db);
|
||||
storePasswordWithAppendf(pStr, sensitive);
|
||||
storeSanitizedPasswordWithAppendf(pStr, sensitive);
|
||||
sqlite3_str_finish(pStr);
|
||||
|
||||
sqlite3_close(db);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#select
|
||||
| CleartextSqliteDatabase.cpp:31:5:31:16 | call to sqlite3_exec | CleartextSqliteDatabase.cpp:29:77:29:84 | password | CleartextSqliteDatabase.cpp:31:22:31:24 | *sql | This SQLite call may store $@ in a non-encrypted SQLite database. | CleartextSqliteDatabase.cpp:29:77:29:84 | password | sensitive information |
|
||||
| CleartextSqliteDatabase.cpp:39:5:39:22 | call to sqlite3_prepare_v2 | CleartextSqliteDatabase.cpp:37:77:37:84 | password | CleartextSqliteDatabase.cpp:39:28:39:30 | *sql | This SQLite call may store $@ in a non-encrypted SQLite database. | CleartextSqliteDatabase.cpp:37:77:37:84 | password | sensitive information |
|
||||
| CleartextSqliteDatabase.cpp:49:5:49:21 | call to sqlite3_bind_text | CleartextSqliteDatabase.cpp:49:32:49:39 | password | CleartextSqliteDatabase.cpp:49:32:49:39 | password | This SQLite call may store $@ in a non-encrypted SQLite database. | CleartextSqliteDatabase.cpp:49:32:49:39 | password | sensitive information |
|
||||
| CleartextSqliteDatabase.cpp:56:5:56:23 | call to sqlite3_str_appendf | CleartextSqliteDatabase.cpp:56:76:56:83 | password | CleartextSqliteDatabase.cpp:56:76:56:83 | password | This SQLite call may store $@ in a non-encrypted SQLite database. | CleartextSqliteDatabase.cpp:56:76:56:83 | password | sensitive information |
|
||||
edges
|
||||
| CleartextSqliteDatabase.cpp:29:77:29:84 | password | CleartextSqliteDatabase.cpp:31:22:31:24 | *sql | provenance | TaintFunction |
|
||||
| CleartextSqliteDatabase.cpp:37:77:37:84 | password | CleartextSqliteDatabase.cpp:39:28:39:30 | *sql | provenance | TaintFunction |
|
||||
nodes
|
||||
| CleartextSqliteDatabase.cpp:29:77:29:84 | password | semmle.label | password |
|
||||
| CleartextSqliteDatabase.cpp:31:22:31:24 | *sql | semmle.label | *sql |
|
||||
| CleartextSqliteDatabase.cpp:37:77:37:84 | password | semmle.label | password |
|
||||
| CleartextSqliteDatabase.cpp:39:28:39:30 | *sql | semmle.label | *sql |
|
||||
| CleartextSqliteDatabase.cpp:49:32:49:39 | password | semmle.label | password |
|
||||
| CleartextSqliteDatabase.cpp:56:76:56:83 | password | semmle.label | password |
|
||||
subpaths
|
||||
@@ -0,0 +1,4 @@
|
||||
query: Security/CWE/CWE-313/CleartextSqliteDatabase.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -17,7 +17,7 @@ runs:
|
||||
run: |
|
||||
CODEQL_PATH=$(gh codeql version --format=json | jq -r .unpackedLocation)
|
||||
# The legacy ASP extractor is not in this repo, so take the one from the nightly build
|
||||
mv "$CODEQL_PATH/csharp/tools/extractor-asp.jar" "${{ github.workspace }}/csharp/extractor-pack/tools"
|
||||
mv "$CODEQL_PATH/csharp/tools/extractor-asp.jar" "$GITHUB_WORKSPACE/csharp/extractor-pack/tools"
|
||||
# Safe guard against using the bundled extractor
|
||||
rm -rf "$CODEQL_PATH/csharp"
|
||||
env:
|
||||
|
||||
@@ -39,6 +39,15 @@ private module ConditionalBypassConfig implements DataFlow::ConfigSig {
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getLocation()
|
||||
or
|
||||
// from ConditionalBypass.ql
|
||||
result = sink.(Sink).getSensitiveMethodCall().getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -59,6 +59,10 @@ private module TaintToObjectMethodTrackingConfig implements DataFlow::ConfigSig
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof InstanceMethodSink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
any() // used in one of the disjuncts in UnsafeDeserializationUntrustedInput.ql
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,6 +81,10 @@ private module JsonConvertTrackingConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
any() // used in one of the disjuncts in UnsafeDeserializationUntrustedInput.ql
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,6 +141,10 @@ private module TypeNameTrackingConfig implements DataFlow::ConfigSig {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
none() // Only used as secondary config in UnsafeDeserializationUntrustedInput.ql
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,6 +161,10 @@ private module TaintToConstructorOrStaticMethodTrackingConfig implements DataFlo
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof ConstructorOrStaticMethodSink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
any() // used in one of the disjuncts in UnsafeDeserializationUntrustedInput.ql
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,6 +202,10 @@ private module TaintToObjectTypeTrackingConfig implements DataFlow::ConfigSig {
|
||||
oc.getObjectType() instanceof StrongTypeDeserializer
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
none() // only used as secondary config in UnsafeDeserializationUntrustedInput.ql
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,6 +230,10 @@ private module WeakTypeCreationToUsageTrackingConfig implements DataFlow::Config
|
||||
sink.asExpr() = mc.getQualifier()
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
none() // only used as secondary config in UnsafeDeserializationUntrustedInput.ql
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,8 @@ module NotThreadSafeCryptoUsageIntoParallelInvokeConfig implements DataFlow::Con
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof ParallelSink }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
module NotThreadSafeCryptoUsageIntoParallelInvoke =
|
||||
|
||||
@@ -38,6 +38,12 @@ module ConnectionStringConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof StringFormatSanitizer }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
any(Call call | call.getAnArgument() = sink.asExpr()).getLocation() = result
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This Sphinx stylesheet adds some customizations to the default Alabaster theme.
|
||||
*
|
||||
* The source for the default stylesheet can be found at
|
||||
*
|
||||
* The source for the default stylesheet can be found at
|
||||
* https://github.com/bitprophet/alabaster/blob/master/alabaster/static/alabaster.css_t
|
||||
*
|
||||
* For the classes provided by the primer, see https://unpkg.com/@primer/css/dist/primer.css
|
||||
@@ -45,7 +45,7 @@ article ul, article ol {
|
||||
}
|
||||
|
||||
.SideNav li {
|
||||
margin: 10px 0 10px 0px;
|
||||
margin: 10px 0 10px 0px;
|
||||
}
|
||||
|
||||
.SideNav ul, .SideNav ol, .SideNav li {
|
||||
@@ -80,20 +80,20 @@ a.reference {
|
||||
}
|
||||
|
||||
a.reference:hover {
|
||||
text-decoration: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* -- ADMONITIONS ---------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Override default styling for "admonitions".
|
||||
/*
|
||||
* Override default styling for "admonitions".
|
||||
* This includes: note, tip, important, and caution.
|
||||
*
|
||||
*/
|
||||
|
||||
div.admonition p.admonition-title {
|
||||
|
||||
div.admonition p.admonition-title {
|
||||
/* Make title same size and font as body, but bold. */
|
||||
font-family: Lato, sans-serif;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -102,7 +102,7 @@ p.admonition-title:after {
|
||||
content: ""; /* Don't insert a colon after the title */
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Don't use yellow for footnote background.
|
||||
*
|
||||
*/
|
||||
@@ -111,7 +111,7 @@ p.admonition-title:after {
|
||||
background-color: unset;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Add a border with rounded corners around code blocks
|
||||
* (as in the QL language spec).
|
||||
*
|
||||
@@ -198,7 +198,7 @@ blockquote.pull-quote {
|
||||
background-color: #EEE;
|
||||
border: #CCC;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
blockquote.pull-quote:first-line {
|
||||
font-weight: bold;
|
||||
@@ -230,6 +230,11 @@ blockquote.pull-quote > :last-child {
|
||||
font-family: "monospace";
|
||||
}
|
||||
|
||||
/* Fixes a bug in "Supported languages and frameworks" where footnotes were incorrectly indented */
|
||||
aside .label {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* -- PRINT VIEW ----------------------------------------------------------------------------*/
|
||||
|
||||
@media print {
|
||||
@@ -252,14 +257,14 @@ blockquote.pull-quote > :last-child {
|
||||
|
||||
/* -- SMALL SCREEN ------------------------------------------------------------------------------- */
|
||||
|
||||
@media screen and (max-width: 875px) {
|
||||
@media screen and (max-width: 875px) {
|
||||
|
||||
/* Overrides strange behaviour caused by default styles */
|
||||
|
||||
body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
div.footer {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -79,4 +79,4 @@ JavaScript/TypeScript
|
||||
* Added taint-steps for :code:`Array.prototype.toReversed`.
|
||||
* Added taint-steps for :code:`Array.prototype.toSorted`.
|
||||
* Added support for :code:`String.prototype.matchAll`.
|
||||
* Added taint-steps for :code:`Array.prototype.reverse`.
|
||||
* Added taint-steps for :code:`Array.prototype.reverse`\
|
||||
|
||||
@@ -117,8 +117,8 @@ Java/Kotlin
|
||||
* Deleted the deprecated :code:`isLValue` and :code:`isRValue` predicates from the :code:`VarAccess` class, use :code:`isVarWrite` and :code:`isVarRead` respectively instead.
|
||||
* Deleted the deprecated :code:`getRhs` predicate from the :code:`VarWrite` class, use :code:`getASource` instead.
|
||||
* Deleted the deprecated :code:`LValue` and :code:`RValue` classes, use :code:`VarWrite` and :code:`VarRead` respectively instead.
|
||||
* Deleted a lot of deprecated classes ending in ``*Access``, use the corresponding ``*Call`` classes instead.
|
||||
* Deleted a lot of deprecated predicates ending in ``*Access``, use the corresponding ``*Call`` predicates instead.
|
||||
* Deleted a lot of deprecated classes ending in :code:`*Access`, use the corresponding :code:`*Call` classes instead.
|
||||
* Deleted a lot of deprecated predicates ending in :code:`*Access`, use the corresponding :code:`*Call` predicates instead.
|
||||
* Deleted the deprecated :code:`EnvInput` and :code:`DatabaseInput` classes from :code:`FlowSources.qll`, use the threat models feature instead.
|
||||
* Deleted some deprecated API predicates from :code:`SensitiveApi.qll`, use the Sink classes from that file instead.
|
||||
|
||||
@@ -144,7 +144,7 @@ Ruby
|
||||
* Deleted the deprecated :code:`ModelClass` and :code:`ModelInstance` classes from :code:`ActiveResource.qll`, use :code:`ModelClassNode` and :code:`ModelClassNode.getAnInstanceReference()` instead.
|
||||
* Deleted the deprecated :code:`Collection` class from :code:`ActiveResource.qll`, use :code:`CollectionSource` instead.
|
||||
* Deleted the deprecated :code:`ServiceInstantiation` and :code:`ClientInstantiation` classes from :code:`Twirp.qll`.
|
||||
* Deleted a lot of deprecated dataflow modules from ``*Query.qll`` files.
|
||||
* Deleted a lot of deprecated dataflow modules from :code:`*Query.qll` files.
|
||||
* Deleted the old deprecated TypeTracking library.
|
||||
|
||||
Swift
|
||||
|
||||
@@ -207,5 +207,5 @@ JavaScript/TypeScript
|
||||
|
||||
* Intersection :code:`&&`
|
||||
* Subtraction :code:`--`
|
||||
* :code:`\\q` quoted string
|
||||
* :code:`\q` quoted string
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ Minor Analysis Improvements
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added flow model for the :code:`SQLite` and :code:`OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
|
||||
* Added flow models for the :code:`SQLite` and :code:`OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
|
||||
|
||||
C#
|
||||
""
|
||||
|
||||
@@ -50,7 +50,7 @@ New Queries
|
||||
Golang
|
||||
""""""
|
||||
|
||||
* Query (:code:`go/html-template-escaping-bypass-xss`) has been promoted to the main query suite. This query finds potential cross-site scripting (XSS) vulnerabilities when using the :code:`html/template` package, caused by user input being cast to a type which bypasses the HTML autoescaping. It was originally contributed to the experimental query pack by @gagliardetto in `https://github.com/github/codeql-go/pull/493 <https://github.com/github/codeql-go/pull/493>`_.
|
||||
* Query (:code:`go/html-template-escaping-bypass-xss`) has been promoted to the main query suite. This query finds potential cross-site scripting (XSS) vulnerabilities when using the :code:`html/template` package, caused by user input being cast to a type which bypasses the HTML autoescaping. It was originally contributed to the experimental query pack by @gagliardetto in https://github.com/github/codeql-go/pull/493.
|
||||
|
||||
Language Libraries
|
||||
------------------
|
||||
|
||||
@@ -14,7 +14,7 @@ This is an overview of changes in the CodeQL CLI and relevant CodeQL query and l
|
||||
Security Coverage
|
||||
-----------------
|
||||
|
||||
CodeQL 2.22.1 runs a total of 449 security queries when configured with the Default suite (covering 165 CWE). The Extended suite enables an additional 129 queries (covering 33 more CWE).
|
||||
CodeQL 2.22.1 runs a total of 476 security queries when configured with the Default suite (covering 166 CWE). The Extended suite enables an additional 129 queries (covering 32 more CWE). 27 security queries have been added with this release.
|
||||
|
||||
CodeQL CLI
|
||||
----------
|
||||
@@ -38,7 +38,7 @@ Minor Analysis Improvements
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added flow model for the following libraries: :code:`madler/zlib`, :code:`google/brotli`, :code:`libidn/libidn2`, :code:`libssh2/libssh2/`, :code:`nghttp2/nghttp2`, :code:`libuv/libuv/`, and :code:`curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.
|
||||
* Added flow models for the following libraries: :code:`madler/zlib`, :code:`google/brotli`, :code:`libidn/libidn2`, :code:`libssh2/libssh2`, :code:`nghttp2/nghttp2`, :code:`libuv/libuv`, and :code:`curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.
|
||||
|
||||
C#
|
||||
""
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
.. _codeql-cli-2.22.2:
|
||||
|
||||
==========================
|
||||
CodeQL 2.22.2 (2025-07-29)
|
||||
==========================
|
||||
|
||||
.. contents:: Contents
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog <https://github.blog/tag/code-scanning/>`__, `relevant GitHub Changelog updates <https://github.blog/changelog/label/code-scanning/>`__, `changes in the CodeQL extension for Visual Studio Code <https://marketplace.visualstudio.com/items/GitHub.vscode-codeql/changelog>`__, and the `CodeQL Action changelog <https://github.com/github/codeql-action/blob/main/CHANGELOG.md>`__.
|
||||
|
||||
Security Coverage
|
||||
-----------------
|
||||
|
||||
CodeQL 2.22.2 runs a total of 474 security queries when configured with the Default suite (covering 166 CWE). The Extended suite enables an additional 130 queries (covering 32 more CWE).
|
||||
|
||||
CodeQL CLI
|
||||
----------
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
* Fixes a bug in query suites where the :code:`version` property of an :code:`import` instruction was ignored. Previously, the following query suite would *not* resolve to :code:`v1.0.19` of :code:`codeql/csharp-queries`. Instead it would resolve to the latest version. This is now fixed and the resolve pack version would be :code:`v1.0.19`.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
- from: codeql/csharp-queries
|
||||
import: codeql-suites/csharp-security-and-quality.qls
|
||||
version: 1.0.19
|
||||
|
||||
Query Packs
|
||||
-----------
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
C#
|
||||
""
|
||||
|
||||
* :code:`web.config` and :code:`web.release.config` files are now recognized regardless of case. This means queries :code:`cs/web/debug-binary` and :code:`cs/web/missing-x-frame-options` may produce more results than before.
|
||||
|
||||
Breaking Changes
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* The :code:`Type` and :code:`Symbol` classes have been deprecated and will be empty in newly extracted databases, since the TypeScript extractor no longer populates them.
|
||||
This is a breaking change for custom queries that explicitly relied on these classes.
|
||||
Such queries will still compile, but with deprecation warnings, and may have different query results due to type information no longer being available.
|
||||
We expect most custom queries will not be affected, however. If a custom query has no deprecation warnings, it should not be affected by this change.
|
||||
Uses of :code:`getType()` should be rewritten to use the new :code:`getTypeBinding()` or :code:`getNameBinding()` APIs instead.
|
||||
If the new API is not sufficient, please consider opening an issue in :code:`github/codeql` describing your use-case.
|
||||
|
||||
Major Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* The TypeScript extractor no longer relies on the TypeScript compiler for extracting type information.
|
||||
Instead, the information we need from types is now derived by an algorithm written in QL.
|
||||
This results in more robust extraction with faster extraction times, in some cases significantly faster.
|
||||
* Taint is now tracked through the React :code:`use` function.
|
||||
* Parameters of React server functions, marked with the :code:`"use server"` directive, are now seen as taint sources.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Due to changes in the :code:`FunctionWithWrappers` library (:code:`semmle.code.cpp.security.FunctionWithWrappers`) the primary alert location generated by the queries :code:`cpp/path-injection`, :code:`cpp/sql-injection`, :code:`cpp/tainted-format-string`, and :code:`cpp/command-line-injection` may have changed.
|
||||
* Added flow models for the Win32 API functions :code:`CreateThread`, :code:`CreateRemoteThread`, and :code:`CreateRemoteThreadEx`.
|
||||
* Improved support for dataflow through function objects and lambda expressions.
|
||||
* Added flow models for :code:`pthread_create` and :code:`std::thread`.
|
||||
* The :code:`cpp/incorrect-string-type-conversion` query no longer alerts on incorrect type conversions that occur in unreachable code.
|
||||
* Added flow models for the GNU C Library.
|
||||
* Fixed a number of false positives and false negatives in :code:`cpp/global-use-before-init`. Note that this query is not part of any of the default query suites.
|
||||
* The query :code:`cpp/sql-injection` now can be extended using the :code:`sql-injection` Models as Data (MaD) sink kind.
|
||||
|
||||
C#
|
||||
""
|
||||
|
||||
* Explicitly added summary models for all overloads of :code:`System.Xml.XmlDictionaryReader.CreateBinaryReader`. Added models for some of the methods and properties in :code:`System.Runtime.Serialization.SerializationInfo` and :code:`System.Runtime.Serialization.SerializationInfoEnumerator`. Updated models for :code:`System.Text.Encoding.GetBytes`, :code:`System.Text.Encoding.GetChars` and the constructor for :code:`System.IO.MemoryStream`. This generally improves the library modelling and thus reduces the number of false negatives.
|
||||
* Added explicit SQL injection Models as Data models for :code:`Microsoft.Data.SqlClient.SqlCommand` and :code:`Microsoft.Data.SqlClient.SqlDataAdapter`. This reduces false negatives for the query :code:`cs/sql-injection`.
|
||||
|
||||
Golang
|
||||
""""""
|
||||
|
||||
* :code:`filepath.IsLocal` is now recognized as a sanitizer against path-traversal and related vulnerabilities.
|
||||
|
||||
Java/Kotlin
|
||||
"""""""""""
|
||||
|
||||
* Java analysis of guards has been switched to use the new and improved shared guards library. This improves precision of a number of queries, in particular :code:`java/dereferenced-value-may-be-null`, which now has fewer false positives, and :code:`java/useless-null-check` and :code:`java/constant-comparison`, which gain additional true positives.
|
||||
|
||||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* Removed three queries from the JS qlpack, which have been superseded by newer queries that are part of the Actions qlpack:
|
||||
|
||||
* :code:`js/actions/pull-request-target` has been superseded by :code:`actions/untrusted-checkout/{medium,high,critical}`
|
||||
* :code:`js/actions/actions-artifact-leak` has been superseded by :code:`actions/secrets-in-artifacts`
|
||||
* :code:`js/actions/command-injection` has been superseded by :code:`actions/command-injection/{medium,critical}`
|
||||
|
||||
New Queries
|
||||
~~~~~~~~~~~
|
||||
|
||||
Rust
|
||||
""""
|
||||
|
||||
* Added a new query, :code:`rust/access-after-lifetime-ended`, for detecting pointer dereferences after the lifetime of the pointed-to object has ended.
|
||||
|
||||
Language Libraries
|
||||
------------------
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* The JavaScript extractor no longer ignores source files specified in the :code:`tsconfig.json` compiler options :code:`outDir` if doing so would result in excluding all source code.
|
||||
|
||||
Python
|
||||
""""""
|
||||
|
||||
* The Python parser is now able to correctly parse expressions such as :code:`match[1]` and :code:`match()` where :code:`match` is not used as a keyword.
|
||||
|
||||
GitHub Actions
|
||||
""""""""""""""
|
||||
|
||||
* The :code:`actions/artifact-poisoning/critical` and :code:`actions/artifact-poisoning/medium` queries now exclude artifacts downloaded to :code:`$[{ runner.temp }}` in addition to :code:`/tmp`.
|
||||
|
||||
Breaking Changes
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Ruby
|
||||
""""
|
||||
|
||||
* Most classes and predicates in the AST, SSA, and control-flow-graph libraries are now annotated with :code:`overlay[local]`, in preparation for incremental analysis. This could result in compiler errors for custom queries if they extend these classes. To mitigate such errors, look for ways to restructure custom QL code so it doesn't depend on changing the behavior of standard-library classes.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* The :code:`FunctionWithWrappers` library (:code:`semmle.code.cpp.security.FunctionWithWrappers`) no longer considers calls through function pointers as wrapper functions.
|
||||
* The analysis of C/C++ code targeting 64-bit Arm platforms has been improved. This includes support for the Arm-specific builtin functions, support for the :code:`arm_neon.h` header and Neon vector types, and support for the :code:`fp8` scalar type. The :code:`arm_sve.h` header and scalable vectors are only partially supported at this point.
|
||||
* Added support for :code:`__fp16 _Complex` and :code:`__bf16 _Complex` types
|
||||
* Added :code:`sql-injection` sink models for the Oracle Call Interface (OCI) database library functions :code:`OCIStmtPrepare` and :code:`OCIStmtPrepare2`.
|
||||
|
||||
Golang
|
||||
""""""
|
||||
|
||||
* Added models for the :code:`Head` function and the :code:`Client.Head` method, from the :code:`net/http` package, to the :code:`Http::ClientRequest` class. This means that they will be recognized as sinks for the query :code:`go/request-forgery` and the experimental query :code:`go/ssrf`.
|
||||
* Previously, :code:`DefinedType.getBaseType` gave the underlying type. It now gives the right hand side of the type declaration, as the documentation indicated that it should.
|
||||
|
||||
Java/Kotlin
|
||||
"""""""""""
|
||||
|
||||
* The qualifiers of a calls to :code:`readObject` on any classes that implement :code:`java.io.ObjectInput` are now recognised as sinks for :code:`java/unsafe-deserialization`. Previously this was only the case for classes which extend :code:`java.io.ObjectInputStream`.
|
||||
|
||||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* Enhanced modeling for the :code:`execa` library, adding support for command execution methods :code:`execaCommand`, :code:`execaCommandSync`, :code:`$`, and :code:`$.sync`, as well as file system operations through :code:`inputFile`, :code:`pipeStdout`, :code:`pipeAll`, and :code:`pipeStderr`.
|
||||
|
||||
Python
|
||||
""""""
|
||||
|
||||
* Type annotations such as :code:`foo : Bar` are now treated by the call graph as an indication that :code:`foo` may be an instance of :code:`Bar`.
|
||||
|
||||
Rust
|
||||
""""
|
||||
|
||||
* Type inference has been extended to support pattern matching.
|
||||
* Call resolution for calls to associated functions has been improved, so it now disambiguates the targets based on type information at the call sites (either type information about the arguments or about the expected return types).
|
||||
* Type inference has been improved for :code:`for` loops and range expressions, which improves call resolution and may ultimately lead to more query results.
|
||||
* Implemented support for data flow through trait functions. For the purpose of data flow, calls to trait functions dispatch to all possible implementations.
|
||||
* :code:`AssocItem` and :code:`ExternItem` are now proper subclasses of :code:`Item`.
|
||||
* Added type inference for :code:`for` loops and array expressions.
|
||||
|
||||
Deprecated APIs
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* The :code:`UnknownDefaultLocation`, :code:`UnknownExprLocation`, and :code:`UnknownStmtLocation` classes have been deprecated. Use :code:`UnknownLocation` instead.
|
||||
|
||||
Golang
|
||||
""""""
|
||||
|
||||
* The class :code:`BuiltinType` is now deprecated. Use the new replacement :code:`BuiltinTypeEntity` instead.
|
||||
* The class :code:`DeclaredType` is now deprecated. Use the new replacement :code:`DeclaredTypeEntity` instead.
|
||||
|
||||
Java/Kotlin
|
||||
"""""""""""
|
||||
|
||||
* The module :code:`semmle.code.java.frameworks.Castor` has been deprecated and will be removed in a future release.
|
||||
* The module :code:`semmle.code.java.frameworks.JYaml` has been deprecated and will be removed in a future release.
|
||||
* The classes :code:`UnsafeHessianInputReadObjectMethod` and :code:`BurlapInputReadObjectMethod` in the module :code:`semmle.code.java.frameworks.HessianBurlap` have been deprecated and will be removed in a future release.
|
||||
* The class :code:`YamlBeansReaderReadMethod` in the module :code:`semmle.code.java.frameworks.YamlBeans` has been deprecated and will be removed in a future release.
|
||||
* The class :code:`MethodApacheSerializationUtilsDeserialize` in the module :code:`semmle.code.java.frameworks.apache.Lang` has been deprecated and will be removed in a future release.
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added a :code:`isFinalValueOfParameter` predicate to :code:`DataFlow::Node` which holds when a dataflow node represents the final value of an output parameter of a function.
|
||||
|
||||
C#
|
||||
""
|
||||
|
||||
* Added a new predicate, :code:`getASuperType()`, to get a direct supertype of this type.
|
||||
|
||||
Java/Kotlin
|
||||
"""""""""""
|
||||
|
||||
* You can now add sinks for the query "Deserialization of user-controlled data" (:code:`java/unsafe-deserialization`) using `data extensions <https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-java-and-kotlin/#extensible-predicates-used-to-create-custom-models-in-java-and-kotlin>`__ by extending :code:`sinkModel` and using the kind "unsafe-deserialization". The existing sinks that do not require extra logic to determine if they are unsafe are now defined in this way.
|
||||
|
||||
Shared Libraries
|
||||
----------------
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Concepts
|
||||
""""""""
|
||||
|
||||
* Initial release. Moves the shared concepts library into its own qlpack.
|
||||
@@ -0,0 +1,101 @@
|
||||
.. _codeql-cli-2.22.3:
|
||||
|
||||
==========================
|
||||
CodeQL 2.22.3 (2025-08-06)
|
||||
==========================
|
||||
|
||||
.. contents:: Contents
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog <https://github.blog/tag/code-scanning/>`__, `relevant GitHub Changelog updates <https://github.blog/changelog/label/code-scanning/>`__, `changes in the CodeQL extension for Visual Studio Code <https://marketplace.visualstudio.com/items/GitHub.vscode-codeql/changelog>`__, and the `CodeQL Action changelog <https://github.com/github/codeql-action/blob/main/CHANGELOG.md>`__.
|
||||
|
||||
Security Coverage
|
||||
-----------------
|
||||
|
||||
CodeQL 2.22.3 runs a total of 476 security queries when configured with the Default suite (covering 169 CWE). The Extended suite enables an additional 130 queries (covering 32 more CWE). 2 security queries have been added with this release.
|
||||
|
||||
CodeQL CLI
|
||||
----------
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* The :code:`codeql database cleanup` command now takes the :code:`--cache-cleanup=overlay` option, which trims the cache to just the data that will be useful when evaluating against an overlay.
|
||||
|
||||
Query Packs
|
||||
-----------
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* The "Initialization code not run" query (:code:`cpp/initialization-not-run`) no longer reports an alert on static global variables that have no dereference.
|
||||
|
||||
Rust
|
||||
""""
|
||||
|
||||
* Type inference now supports closures, calls to closures, and trait bounds using the :code:`FnOnce` trait.
|
||||
* Type inference now supports trait objects, i.e., :code:`dyn Trait` types.
|
||||
* Type inference now supports tuple types.
|
||||
|
||||
New Queries
|
||||
~~~~~~~~~~~
|
||||
|
||||
Rust
|
||||
""""
|
||||
|
||||
* Added a new query, :code:`rust/hard-coded-cryptographic-value`, for detecting use of hardcoded keys, passwords, salts and initialization vectors.
|
||||
|
||||
Language Libraries
|
||||
------------------
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* The :code:`cpp/overrun-write` query now recognizes more bound checks and thus produces fewer false positives.
|
||||
|
||||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* The regular expressions in :code:`SensitiveDataHeuristics.qll` have been extended to find more instances of sensitive data such as secrets used in authentication, finance and health information, and device data. The heuristics have also been refined to find fewer false positive matches. This will improve results for queries related to sensitive information.
|
||||
|
||||
Python
|
||||
""""""
|
||||
|
||||
* The regular expressions in :code:`SensitiveDataHeuristics.qll` have been extended to find more instances of sensitive data such as secrets used in authentication, finance and health information, and device data. The heuristics have also been refined to find fewer false positive matches. This will improve results for queries related to sensitive information.
|
||||
|
||||
Ruby
|
||||
""""
|
||||
|
||||
* The regular expressions in :code:`SensitiveDataHeuristics.qll` have been extended to find more instances of sensitive data such as secrets used in authentication, finance and health information, and device data. The heuristics have also been refined to find fewer false positive matches. This will improve results for queries related to sensitive information.
|
||||
|
||||
Swift
|
||||
"""""
|
||||
|
||||
* The regular expressions in :code:`SensitiveDataHeuristics.qll` have been extended to find more instances of sensitive data such as secrets used in authentication, finance and health information, and device data. The heuristics have also been refined to find fewer false positive matches. This will improve results for queries related to sensitive information.
|
||||
|
||||
Rust
|
||||
""""
|
||||
|
||||
* Removed deprecated dataflow extensible predicates :code:`sourceModelDeprecated`, :code:`sinkModelDeprecated`, and :code:`summaryModelDeprecated`, along with their associated classes.
|
||||
* The regular expressions in :code:`SensitiveDataHeuristics.qll` have been extended to find more instances of sensitive data such as secrets used in authentication, finance and health information, and device data. The heuristics have also been refined to find fewer false positive matches. This will improve results for queries related to sensitive information.
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Exposed various SSA-related classes (:code:`Definition`, :code:`PhiNode`, :code:`ExplicitDefinition`, :code:`DirectExplicitDefinition`, and :code:`IndirectExplicitDefinition`) which were previously only usable inside the internal dataflow directory.
|
||||
|
||||
Java/Kotlin
|
||||
"""""""""""
|
||||
|
||||
* Kotlin versions up to 2.2.2\ *x* are now supported.
|
||||
@@ -11,6 +11,8 @@ A list of queries for each suite and language `is available here <https://docs.g
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
codeql-cli-2.22.3
|
||||
codeql-cli-2.22.2
|
||||
codeql-cli-2.22.1
|
||||
codeql-cli-2.22.0
|
||||
codeql-cli-2.21.4
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
.NET 5, .NET 6, .NET 7, .NET 8, .NET 9","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``"
|
||||
GitHub Actions,"Not applicable",Not applicable,"``.github/workflows/*.yml``, ``.github/workflows/*.yaml``, ``**/action.yml``, ``**/action.yaml``"
|
||||
Go (aka Golang), "Go up to 1.24", "Go 1.11 or more recent", ``.go``
|
||||
Go (aka Golang), "Go up to 1.25", "Go 1.11 or more recent", ``.go``
|
||||
Java,"Java 7 to 24 [6]_","javac (OpenJDK and Oracle JDK),
|
||||
|
||||
Eclipse compiler for Java (ECJ) [7]_",``.java``
|
||||
|
||||
@@ -4,7 +4,7 @@ inputs:
|
||||
go-test-version:
|
||||
description: Which Go version to use for running the tests
|
||||
required: false
|
||||
default: "~1.24.0"
|
||||
default: "~1.25.0"
|
||||
run-code-checks:
|
||||
description: Whether to run formatting, code and qhelp generation checks
|
||||
required: false
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
var minGoVersion = util.NewSemVer("1.11")
|
||||
var maxGoVersion = util.NewSemVer("1.24")
|
||||
var maxGoVersion = util.NewSemVer("1.25")
|
||||
|
||||
type versionInfo struct {
|
||||
goModVersion util.SemVer // The version of Go found in the go directive in the `go.mod` file.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
module github.com/github/codeql-go/extractor
|
||||
|
||||
go 1.24
|
||||
go 1.25
|
||||
|
||||
toolchain go1.24.0
|
||||
toolchain go1.25.0
|
||||
|
||||
// when updating this, run
|
||||
// bazel run @rules_go//go -- mod tidy
|
||||
|
||||
@@ -56,6 +56,17 @@ module AllocationSizeOverflow {
|
||||
succ = c
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getLocation()
|
||||
or
|
||||
exists(DataFlow::Node allocsz |
|
||||
isSinkWithAllocationSize(sink, allocsz) and
|
||||
result = allocsz.getLocation()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Tracks taint flow to find allocation-size overflows. */
|
||||
|
||||
@@ -24,6 +24,8 @@ module CommandInjection {
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,6 +82,8 @@ module CommandInjection {
|
||||
node instanceof Sanitizer or
|
||||
node = any(ArgumentArrayWithDoubleDash array).getASanitizedElement()
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -186,6 +186,8 @@ private module UntrustedDataConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,6 +30,8 @@ module HardcodedCredentials {
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
/** Tracks taint flow for reasoning about hardcoded credentials. */
|
||||
|
||||
@@ -440,6 +440,12 @@ private module ConversionWithoutBoundsCheckConfig implements DataFlow::StateConf
|
||||
state2 = node2.(FlowStateTransformer).transform(state1) and
|
||||
DataFlow::simpleLocalFlowStep(node1, node2, _)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getASuccessor().getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,6 +39,10 @@ module InsecureRandomness {
|
||||
n2.getType() instanceof IntegerType
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
none() // Can't have accurate sink location override because of secondary use of `flowPath` in select.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,14 @@ module ReflectedXss {
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getLocation()
|
||||
or
|
||||
result = sink.(SharedXss::Sink).getAssociatedLoc().getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/** Tracks taint flow from untrusted data to XSS attack vectors. */
|
||||
|
||||
@@ -31,6 +31,14 @@ module RequestForgery {
|
||||
w.writesField(v.getAUse(), f, pred) and succ = v.getAUse()
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.getLocation()
|
||||
or
|
||||
result = sink.(Sink).getARequest().getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/** Tracks taint flow from untrusted data to request forgery attack vectors. */
|
||||
|
||||
@@ -36,6 +36,10 @@ module SafeUrlFlow {
|
||||
or
|
||||
node instanceof SanitizerEdge
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
none() // only used as secondary configuration
|
||||
}
|
||||
}
|
||||
|
||||
/** Tracks taint flow for reasoning about safe URLs. */
|
||||
|
||||
@@ -128,6 +128,14 @@ module UnhandledFileCloseConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isWritableFileHandle(source, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isCloseSink(sink, _) }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) {
|
||||
exists(DataFlow::CallNode openCall | result = openCall.getLocation() |
|
||||
isWritableFileHandle(source, openCall)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -68,6 +68,8 @@ module Config implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { writeIsSink(sink, _) }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -123,6 +123,17 @@ module Config implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof OpenUrlRedirect::Sink }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) {
|
||||
result = source.getLocation()
|
||||
or
|
||||
exists(DataFlow::Node check |
|
||||
isCheckedSource(source, check) and
|
||||
result = check.getLocation()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module Flow = TaintTracking::Global<Config>;
|
||||
|
||||
@@ -116,6 +116,12 @@ private module BoolToGinSetCookieTrackingConfig implements DataFlow::ConfigSig {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
any() // Merged with other flows in CookieWithoutHttpOnly.ql
|
||||
}
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -59,6 +59,14 @@ private module Config implements DataFlow::ConfigSig {
|
||||
not c.isPotentialFalsePositive()
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
exists(ComparisonExpr comp | result = comp.getLocation() | sink.asExpr() = comp.getAnOperand())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,10 @@ module Config implements DataFlow::ConfigSig {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(ComparisonExpr c | c.getAnOperand() = sink.asExpr())
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() {
|
||||
none() // can't override the locations accurately because of secondary use of config.
|
||||
}
|
||||
}
|
||||
|
||||
/** Tracks taint flow for reasoning about conditional bypass. */
|
||||
|
||||
@@ -30,6 +30,14 @@ module ServerSideRequestForgery {
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) { node instanceof SanitizerEdge }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
|
||||
|
||||
Location getASelectedSinkLocation(DataFlow::Node sink) {
|
||||
result = sink.(Sink).getARequest().getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/** Tracks taint flow for reasoning about request forgery vulnerabilities. */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user