mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
Merge branch 'main' into js/shared-dataflow-merge-main
This commit is contained in:
2
.github/workflows/go-tests.yml
vendored
2
.github/workflows/go-tests.yml
vendored
@@ -3,6 +3,7 @@ on:
|
||||
push:
|
||||
paths:
|
||||
- "go/**"
|
||||
- "shared/**"
|
||||
- .github/workflows/go-tests.yml
|
||||
- .github/actions/**
|
||||
- codeql-workspace.yml
|
||||
@@ -12,6 +13,7 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "go/**"
|
||||
- "shared/**"
|
||||
- .github/workflows/go-tests.yml
|
||||
- .github/actions/**
|
||||
- codeql-workspace.yml
|
||||
|
||||
60
Cargo.lock
generated
60
Cargo.lock
generated
@@ -265,7 +265,7 @@ dependencies = [
|
||||
"chalk-ir",
|
||||
"ena",
|
||||
"indexmap 2.5.0",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"petgraph",
|
||||
"rustc-hash",
|
||||
"tracing",
|
||||
@@ -374,6 +374,7 @@ dependencies = [
|
||||
"clap",
|
||||
"codeql-extractor",
|
||||
"figment",
|
||||
"itertools 0.13.0",
|
||||
"log",
|
||||
"num-traits",
|
||||
"ra_ap_base_db",
|
||||
@@ -381,6 +382,7 @@ dependencies = [
|
||||
"ra_ap_hir_def",
|
||||
"ra_ap_ide_db",
|
||||
"ra_ap_load-cargo",
|
||||
"ra_ap_parser",
|
||||
"ra_ap_paths",
|
||||
"ra_ap_project_model",
|
||||
"ra_ap_syntax",
|
||||
@@ -679,6 +681,16 @@ version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a"
|
||||
|
||||
[[package]]
|
||||
name = "generate-schema"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools 0.10.5",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"ungrammar",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
@@ -848,6 +860,15 @@ version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
@@ -857,6 +878,15 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
@@ -1333,7 +1363,7 @@ checksum = "c7c38520eb4770af561c34b908431f4e548c3282093cf3daf3c6e566d99a2937"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"either",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"ra_ap_base_db",
|
||||
"ra_ap_cfg",
|
||||
"ra_ap_hir_def",
|
||||
@@ -1365,7 +1395,7 @@ dependencies = [
|
||||
"fst",
|
||||
"hashbrown 0.14.5",
|
||||
"indexmap 2.5.0",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"la-arena",
|
||||
"ra-ap-rustc_abi",
|
||||
"ra-ap-rustc_parse_format",
|
||||
@@ -1395,7 +1425,7 @@ dependencies = [
|
||||
"cov-mark",
|
||||
"either",
|
||||
"hashbrown 0.14.5",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"la-arena",
|
||||
"ra_ap_base_db",
|
||||
"ra_ap_cfg",
|
||||
@@ -1430,7 +1460,7 @@ dependencies = [
|
||||
"either",
|
||||
"ena",
|
||||
"indexmap 2.5.0",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"la-arena",
|
||||
"nohash-hasher",
|
||||
"oorandom",
|
||||
@@ -1467,7 +1497,7 @@ dependencies = [
|
||||
"either",
|
||||
"fst",
|
||||
"indexmap 2.5.0",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"line-index",
|
||||
"memchr",
|
||||
"nohash-hasher",
|
||||
@@ -1513,7 +1543,7 @@ checksum = "82e6f24b61f1ef1f3a756493d1fb7e711b69b2e4d5f4746fcb959313dfd41471"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"crossbeam-channel",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"ra_ap_hir_expand",
|
||||
"ra_ap_ide_db",
|
||||
"ra_ap_intern",
|
||||
@@ -1608,7 +1638,7 @@ checksum = "db83d1844c74b22c110c4b8e8f2519be2b1723964008527281a11c3398749756"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo_metadata",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"la-arena",
|
||||
"ra_ap_base_db",
|
||||
"ra_ap_cfg",
|
||||
@@ -1632,7 +1662,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "370b302873eeafd07ccc6a714fc9395cae11e385955ccb78081093ee3b86f94e"
|
||||
dependencies = [
|
||||
"indexmap 2.5.0",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"lock_api",
|
||||
"oorandom",
|
||||
"parking_lot",
|
||||
@@ -1679,7 +1709,7 @@ checksum = "bb63ff9d6b11b4553fc0835f16705975258905e3b1230fcf1ddbf24c46aff69d"
|
||||
dependencies = [
|
||||
"always-assert",
|
||||
"crossbeam-channel",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"jod-thread",
|
||||
"libc",
|
||||
"miow",
|
||||
@@ -1695,7 +1725,7 @@ dependencies = [
|
||||
"cov-mark",
|
||||
"either",
|
||||
"indexmap 2.5.0",
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"ra-ap-rustc_lexer",
|
||||
"ra_ap_parser",
|
||||
"ra_ap_stdx",
|
||||
@@ -1729,7 +1759,7 @@ version = "0.0.232"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cb72ee1901baec556f4f2ef77e287d749ac0e973f063990672d6207b076aeac"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"text-size",
|
||||
]
|
||||
|
||||
@@ -2325,6 +2355,12 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ungrammar"
|
||||
version = "1.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e5df347f0bf3ec1d670aad6ca5c6a1859cd9ea61d2113125794654ccced68f"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.13"
|
||||
|
||||
@@ -7,6 +7,7 @@ members = [
|
||||
"ruby/extractor",
|
||||
"rust/extractor",
|
||||
"rust/extractor/macros",
|
||||
"rust/generate-schema",
|
||||
]
|
||||
|
||||
[patch.crates-io]
|
||||
|
||||
@@ -61,6 +61,7 @@ r.from_cargo(
|
||||
"//ruby/extractor:Cargo.toml",
|
||||
"//rust/extractor:Cargo.toml",
|
||||
"//rust/extractor/macros:Cargo.toml",
|
||||
"//rust/generate-schema:Cargo.toml",
|
||||
"//shared/tree-sitter-extractor:Cargo.toml",
|
||||
],
|
||||
)
|
||||
@@ -127,6 +128,7 @@ use_repo(
|
||||
"kotlin-compiler-1.9.20-Beta",
|
||||
"kotlin-compiler-2.0.0-RC1",
|
||||
"kotlin-compiler-2.0.20-Beta2",
|
||||
"kotlin-compiler-2.1.0-Beta1",
|
||||
"kotlin-compiler-embeddable-1.5.0",
|
||||
"kotlin-compiler-embeddable-1.5.10",
|
||||
"kotlin-compiler-embeddable-1.5.20",
|
||||
@@ -140,6 +142,7 @@ use_repo(
|
||||
"kotlin-compiler-embeddable-1.9.20-Beta",
|
||||
"kotlin-compiler-embeddable-2.0.0-RC1",
|
||||
"kotlin-compiler-embeddable-2.0.20-Beta2",
|
||||
"kotlin-compiler-embeddable-2.1.0-Beta1",
|
||||
"kotlin-stdlib-1.5.0",
|
||||
"kotlin-stdlib-1.5.10",
|
||||
"kotlin-stdlib-1.5.20",
|
||||
@@ -153,6 +156,7 @@ use_repo(
|
||||
"kotlin-stdlib-1.9.20-Beta",
|
||||
"kotlin-stdlib-2.0.0-RC1",
|
||||
"kotlin-stdlib-2.0.20-Beta2",
|
||||
"kotlin-stdlib-2.1.0-Beta1",
|
||||
)
|
||||
|
||||
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
|
||||
|
||||
@@ -57,10 +57,6 @@
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll"
|
||||
],
|
||||
"Model as Data Generation Java/C# - CaptureModels": [
|
||||
"java/ql/src/utils/modelgenerator/internal/CaptureModels.qll",
|
||||
"csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll"
|
||||
],
|
||||
"Sign Java/C#": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll"
|
||||
@@ -355,5 +351,9 @@
|
||||
"Python model summaries test extension": [
|
||||
"python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml",
|
||||
"python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml"
|
||||
],
|
||||
"Diagnostics.qll": [
|
||||
"ruby/ql/lib/codeql/ruby/Diagnostics.qll",
|
||||
"rust/ql/lib/codeql/rust/Diagnostics.qll"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 2.0.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 2.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
3
cpp/ql/lib/change-notes/released/2.0.1.md
Normal file
3
cpp/ql/lib/change-notes/released/2.0.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 2.0.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 2.0.0
|
||||
lastReleaseVersion: 2.0.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 2.0.1-dev
|
||||
version: 2.0.2-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -500,6 +500,17 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
* Gets the nearest enclosing AccessHolder.
|
||||
*/
|
||||
override AccessHolder getEnclosingAccessHolder() { result = this.getDeclaringType() }
|
||||
|
||||
/**
|
||||
* Holds if this function has extraction errors that create an `ErrorExpr`.
|
||||
*/
|
||||
predicate hasErrors() {
|
||||
exists(ErrorExpr e |
|
||||
e.getEnclosingFunction() = this and
|
||||
// Exclude the first allocator call argument because it is always extracted as `ErrorExpr`.
|
||||
not exists(NewOrNewArrayExpr new | e = new.getAllocatorCall().getArgument(0))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
@@ -651,7 +662,8 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
|
||||
/**
|
||||
* Holds if this declaration is an implicit function declaration, that is,
|
||||
* where a function is used before it is declared (under older C standards).
|
||||
* where a function is used before it is declared (under older C standards,
|
||||
* or when there were parse errors).
|
||||
*/
|
||||
predicate isImplicit() { fun_implicit(underlyingElement(this)) }
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ class Type extends Locatable, @type {
|
||||
|
||||
/**
|
||||
* Gets a specifier of this type, recursively looking through `typedef` and
|
||||
* `decltype`. For example, in the context of `typedef const int *restrict
|
||||
* t`, the type `volatile t` has specifiers `volatile` and `restrict` but not
|
||||
* `decltype`. For example, in the context of `typedef const int *restrict t`,
|
||||
* the type `volatile t` has specifiers `volatile` and `restrict` but not
|
||||
* `const` since the `const` is attached to the type being pointed to rather
|
||||
* than the pointer itself.
|
||||
*/
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -546,7 +546,7 @@ module ProductFlow {
|
||||
Flow1::PathGraph::edges(pred1, succ1, _, _) and
|
||||
exists(ReturnKindExt returnKind |
|
||||
succ1.getNode() = returnKind.getAnOutNode(call) and
|
||||
paramReturnNode(_, pred1.asParameterReturnNode(), _, returnKind)
|
||||
returnKind = getParamReturnPosition(_, pred1.asParameterReturnNode()).getKind()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -574,7 +574,7 @@ module ProductFlow {
|
||||
Flow2::PathGraph::edges(pred2, succ2, _, _) and
|
||||
exists(ReturnKindExt returnKind |
|
||||
succ2.getNode() = returnKind.getAnOutNode(call) and
|
||||
paramReturnNode(_, pred2.asParameterReturnNode(), _, returnKind)
|
||||
returnKind = getParamReturnPosition(_, pred2.asParameterReturnNode()).getKind()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -118,19 +118,34 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||
|
||||
/**
|
||||
* Gets the position of the first format argument, corresponding with
|
||||
* the first format specifier in the format string.
|
||||
* the first format specifier in the format string. We ignore all
|
||||
* implicit function definitions.
|
||||
*/
|
||||
int getFirstFormatArgumentIndex() {
|
||||
result = this.getNumberOfParameters() and
|
||||
// the formatting function either has a definition in the snapshot, or all
|
||||
// The formatting function either has a definition in the snapshot, or all
|
||||
// `DeclarationEntry`s agree on the number of parameters (otherwise we don't
|
||||
// really know the correct number)
|
||||
(
|
||||
this.hasDefinition()
|
||||
or
|
||||
forall(FunctionDeclarationEntry fde | fde = this.getADeclarationEntry() |
|
||||
result = fde.getNumberOfParameters()
|
||||
)
|
||||
if this.hasDefinition()
|
||||
then result = this.getDefinition().getNumberOfParameters()
|
||||
else result = this.getNumberOfExplicitParameters()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a non-implicit function declaration entry.
|
||||
*/
|
||||
private FunctionDeclarationEntry getAnExplicitDeclarationEntry() {
|
||||
result = this.getADeclarationEntry() and
|
||||
not result.isImplicit()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of parameters, excluding any parameters that have been defined
|
||||
* from implicit function declarations. If there is some inconsistency in the number
|
||||
* of parameters, then don't return anything.
|
||||
*/
|
||||
private int getNumberOfExplicitParameters() {
|
||||
forex(FunctionDeclarationEntry fde | fde = this.getAnExplicitDeclarationEntry() |
|
||||
result = fde.getNumberOfParameters()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -160,6 +160,26 @@ private module InvalidPointerToDerefBarrier {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* BEWARE: This configuration uses an unrestricted sink, so accessing its full
|
||||
* flow computation or any stages beyond the first 2 will likely diverge.
|
||||
* Stage 1 will still be fast and we use it to restrict the subsequent sink
|
||||
* computation.
|
||||
*/
|
||||
private module InvalidPointerReachesConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { invalidPointerToDerefSource(_, _, source) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { any() }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { InvalidPointerToDerefConfig::isBarrier(node) }
|
||||
|
||||
int fieldFlowBranchLimit() { result = invalidPointerToDereferenceFieldFlowBranchLimit() }
|
||||
}
|
||||
|
||||
private module InvalidPointerReachesFlow = DataFlow::Global<InvalidPointerReachesConfig>;
|
||||
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
|
||||
|
||||
/**
|
||||
* A configuration to track flow from a pointer-arithmetic operation found
|
||||
* by `AllocToInvalidPointerConfig` to a dereference of the pointer.
|
||||
@@ -173,8 +193,13 @@ private module InvalidPointerToDerefConfig implements DataFlow::StateConfigSig {
|
||||
invalidPointerToDerefSource(_, pai, source)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _, _, _) }
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DataFlowImplCommon::NodeEx n |
|
||||
InvalidPointerReachesFlow::Stages::Stage1::sinkNode(n, _) and
|
||||
n.asNode() = sink and
|
||||
isInvalidPointerDerefSink(sink, _, _, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink, FlowState pai) { none() }
|
||||
|
||||
|
||||
@@ -72,7 +72,6 @@ module FlowFromFree<FlowFromFreeParamSig P> {
|
||||
|
||||
predicate isSource(DataFlow::Node node, FlowState state) { isFree(node, _, state, _) }
|
||||
|
||||
pragma[inline]
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
exists(Expr e, DataFlow::Node source, DeallocationExpr dealloc |
|
||||
P::isSink(sink, e) and
|
||||
|
||||
@@ -57,5 +57,5 @@ where
|
||||
not declarationHasSideEffects(v) and
|
||||
not exists(AsmStmt s | f = s.getEnclosingFunction()) and
|
||||
not v.getAnAttribute().getName() = "unused" and
|
||||
not any(ErrorExpr e).getEnclosingFunction() = f // unextracted expr may use `v`
|
||||
not f.hasErrors() // Unextracted expressions may use `v`
|
||||
select v, "Variable " + v.getName() + " is not used."
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
## 1.2.4
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Fixed false positives in the `cpp/wrong-number-format-arguments` ("Too few arguments to formatting function") query when the formatting function has been declared implicitly.
|
||||
|
||||
## 1.2.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Removed false positives caused by buffer accesses in unreachable code.
|
||||
* Removed false positives caused by inconsistent type checking.
|
||||
* Removed false positives caused by buffer accesses in unreachable code
|
||||
* Removed false positives caused by inconsistent type checking
|
||||
* Add modeling of C functions that don't throw, thereby increasing the precision of the `cpp/incorrect-allocation-error-handling` ("Incorrect allocation-error handling") query. The query now produces additional true positives.
|
||||
|
||||
## 1.2.2
|
||||
|
||||
@@ -29,7 +29,7 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
|
||||
override predicate isSource(Instruction source) {
|
||||
exists(Function func |
|
||||
// Rule out FPs caused by extraction errors.
|
||||
not any(ErrorExpr e).getEnclosingFunction() = func and
|
||||
not func.hasErrors() and
|
||||
not intentionallyReturnsStackPointer(func) and
|
||||
func = source.getEnclosingFunction()
|
||||
|
|
||||
|
||||
@@ -65,6 +65,7 @@ predicate isSinkImpl(Instruction sink, VariableAccess va) {
|
||||
exists(LoadInstruction load |
|
||||
va = load.getUnconvertedResultExpression() and
|
||||
not va = commonException() and
|
||||
not va.getTarget().(LocalVariable).getFunction().hasErrors() and
|
||||
sink = load.getSourceValue()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ predicate instructionHasVariable(VariableAddressInstruction vai, StackVariable v
|
||||
// Pointer-to-member types aren't properly handled in the dbscheme.
|
||||
not vai.getResultType() instanceof PointerToMemberType and
|
||||
// Rule out FPs caused by extraction errors.
|
||||
not any(ErrorExpr e).getEnclosingFunction() = f
|
||||
not f.hasErrors()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,23 +13,85 @@
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
class WideCharPointerType extends PointerType {
|
||||
WideCharPointerType() { this.getBaseType() instanceof WideCharType }
|
||||
}
|
||||
|
||||
/**
|
||||
* Given type `t`, recurses through and returns all
|
||||
* intermediate base types, including `t`.
|
||||
*/
|
||||
Type getABaseType(Type t) {
|
||||
result = t
|
||||
or
|
||||
result = getABaseType(t.(DerivedType).getBaseType())
|
||||
or
|
||||
result = getABaseType(t.(TypedefType).getBaseType())
|
||||
}
|
||||
|
||||
/**
|
||||
* A type that may also be `CharPointerType`, but that are likely used as arbitrary buffers.
|
||||
*/
|
||||
class UnlikelyToBeAStringType extends Type {
|
||||
UnlikelyToBeAStringType() {
|
||||
this.(PointerType).getBaseType().(CharType).isUnsigned() or
|
||||
this.(PointerType).getBaseType().getName().toLowerCase().matches("%byte") or
|
||||
this.getName().toLowerCase().matches("%byte") or
|
||||
this.(PointerType).getBaseType().hasName("uint8_t")
|
||||
exists(Type targ | getABaseType(this) = targ |
|
||||
// NOTE: not using CharType isUnsigned, but rather look for any explicitly declared unsigned
|
||||
// char types. Assuming these are used for buffers, not strings.
|
||||
targ.(CharType).getName().toLowerCase().matches("unsigned%") or
|
||||
targ.getName().toLowerCase().matches(["uint8_t", "%byte%"])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Types that can be wide depending on the UNICODE macro
|
||||
// see https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types
|
||||
class UnicodeMacroDependentWidthType extends Type {
|
||||
UnicodeMacroDependentWidthType() {
|
||||
exists(Type targ | getABaseType(this) = targ |
|
||||
targ.getName() in [
|
||||
"LPCTSTR",
|
||||
"LPTSTR",
|
||||
"PCTSTR",
|
||||
"PTSTR",
|
||||
"TBYTE",
|
||||
"TCHAR"
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class UnicodeMacro extends Macro {
|
||||
UnicodeMacro() { this.getName().toLowerCase().matches("%unicode%") }
|
||||
}
|
||||
|
||||
class UnicodeMacroInvocation extends MacroInvocation {
|
||||
UnicodeMacroInvocation() { this.getMacro() instanceof UnicodeMacro }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds when a expression whose type is UnicodeMacroDependentWidthType and
|
||||
* is observed to be guarded by a check involving a bitwise-and operation
|
||||
* with a UnicodeMacroInvocation.
|
||||
* Such expressions are assumed to be checked dynamically, i.e.,
|
||||
* the flag would indicate if UNICODE typing is set correctly to allow
|
||||
* or disallow a widening cast.
|
||||
*/
|
||||
predicate isLikelyDynamicallyChecked(Expr e) {
|
||||
e.getType() instanceof UnicodeMacroDependentWidthType and
|
||||
exists(GuardCondition gc, BitwiseAndExpr bai, UnicodeMacroInvocation umi |
|
||||
bai.getAnOperand() = umi.getExpr()
|
||||
|
|
||||
// bai == 0 is false when reaching `e.getBasicBlock()`.
|
||||
// That is, bai != 0 when reaching `e.getBasicBlock()`.
|
||||
gc.ensuresEq(bai, 0, e.getBasicBlock(), false)
|
||||
or
|
||||
// bai == k and k != 0 is true when reaching `e.getBasicBlock()`.
|
||||
gc.ensuresEq(bai, any(int k | k != 0), e.getBasicBlock(), true)
|
||||
)
|
||||
}
|
||||
|
||||
from Expr e1, Cast e2
|
||||
where
|
||||
e2 = e1.getConversion() and
|
||||
@@ -42,7 +104,11 @@ where
|
||||
not e1.getType() instanceof UnlikelyToBeAStringType and
|
||||
// Avoid castings from 'new' expressions as typically these will be safe
|
||||
// Example: `__Type* ret = reinterpret_cast<__Type*>(New(m_pmo) char[num * sizeof(__Type)]);`
|
||||
not exists(NewOrNewArrayExpr newExpr | newExpr.getAChild*() = e1)
|
||||
not exists(NewOrNewArrayExpr newExpr | newExpr.getAChild*() = e1) and
|
||||
// Avoid cases where the cast is guarded by a check to determine if
|
||||
// unicode encoding is enabled in such a way to disallow the dangerous cast
|
||||
// at runtime.
|
||||
not isLikelyDynamicallyChecked(e1)
|
||||
select e1,
|
||||
"Conversion from " + e1.getType().toString() + " to " + e2.getType().toString() +
|
||||
". Use of invalid string can lead to undefined behavior."
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to detect byte arrays.
|
||||
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to recognize dynamic checks prior to possible dangerous widening.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Fixed false positives in the `cpp/uninitialized-local` ("Potentially uninitialized local variable") query if there are extraction errors in the function.
|
||||
5
cpp/ql/src/change-notes/released/1.2.4.md
Normal file
5
cpp/ql/src/change-notes/released/1.2.4.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 1.2.4
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Fixed false positives in the `cpp/wrong-number-format-arguments` ("Too few arguments to formatting function") query when the formatting function has been declared implicitly.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.2.3
|
||||
lastReleaseVersion: 1.2.4
|
||||
|
||||
34
cpp/ql/src/experimental/Security/CWE/CWE-295/CurlSSL.qhelp
Normal file
34
cpp/ql/src/experimental/Security/CWE/CWE-295/CurlSSL.qhelp
Normal file
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
Disabling verification of the SSL certificate allows man-in-the-middle attacks. A SSL
|
||||
connection is vulnerable to man-in-the-middle attacks if the certification is not checked
|
||||
properly. If the peer or the host's certificate verification is not verified, the underlying
|
||||
SSL communication is insecure.</p>
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>It is recommended that all communications be done post verification of the host as well as
|
||||
the
|
||||
peer.</p>
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>The following snippet disables certification verification by setting the value of <code>
|
||||
CURLOPT_SSL_VERIFYHOST</code> and <code>CURLOPT_SSL_VERIFYHOST</code> to <code>0</code>:</p>
|
||||
<sample src="CurlSSLBad.cpp" />
|
||||
<p>This is bad as the certificates are not verified any more. This can be easily fixed by
|
||||
setting the values of the options to <code>2</code>. </p>
|
||||
<sample src="CurlSSLGood.cpp" />
|
||||
</example>
|
||||
<references>
|
||||
<li> Curl Documentation:<a href="https://curl.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html">
|
||||
CURLOPT_SSL_VERIFYHOST</a></li>
|
||||
<li> Curl Documentation:<a href="https://curl.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html">
|
||||
CURLOPT_SSL_VERIFYPEER</a></li>
|
||||
<li> Related CVE: <a href="https://github.com/advisories/GHSA-5r3h-c3r7-9w4h"> CVE-2022-33684</a></li>
|
||||
<li> Related security advisory: <a
|
||||
href="https://huntr.com/bounties/42325662-6329-4e04-875a-49e2f5d69f78">
|
||||
openframeworks/openframeworks
|
||||
</a></li>
|
||||
</references>
|
||||
</qhelp>
|
||||
39
cpp/ql/src/experimental/Security/CWE/CWE-295/CurlSSL.ql
Normal file
39
cpp/ql/src/experimental/Security/CWE/CWE-295/CurlSSL.ql
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @name Disabled certifcate verification
|
||||
* @description Disabling SSL certificate verification of host or peer could expose the communication to man-in-the-middle(MITM) attacks.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id cpp/curl-disabled-ssl
|
||||
* @tags security
|
||||
* external/cwe/cwe-295
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.TaintTracking
|
||||
|
||||
/** Models the `curl_easy_setopt` function call */
|
||||
private class CurlSetOptCall extends FunctionCall {
|
||||
CurlSetOptCall() {
|
||||
exists(FunctionCall fc, Function f |
|
||||
f.hasGlobalOrStdName("curl_easy_setopt") and
|
||||
fc.getTarget() = f
|
||||
|
|
||||
this = fc
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Models an access to any enum constant which could affect SSL verification */
|
||||
private class CurlVerificationConstant extends EnumConstantAccess {
|
||||
CurlVerificationConstant() {
|
||||
exists(EnumConstant e | e.getName() = ["CURLOPT_SSL_VERIFYHOST", "CURLOPT_SSL_VERIFYPEER"] |
|
||||
e.getAnAccess() = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from CurlSetOptCall c
|
||||
where
|
||||
c.getArgument(1) = any(CurlVerificationConstant v) and
|
||||
c.getArgument(2).getValue() = "0"
|
||||
select c, "This call disables Secure Socket Layer and could potentially lead to MITM attacks"
|
||||
@@ -0,0 +1,9 @@
|
||||
string host = "codeql.com"
|
||||
void bad(void) {
|
||||
std::unique_ptr<CURL, void(*)(CURL*)> curl =
|
||||
std::unique_ptr<CURL, void(*)(CURL*)>(curl_easy_init(), curl_easy_cleanup);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_URL, host.c_str());
|
||||
curl_easy_perform(curl.get());
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
string host = "codeql.com"
|
||||
void good(void) {
|
||||
std::unique_ptr<CURL, void(*)(CURL*)> curl =
|
||||
std::unique_ptr<CURL, void(*)(CURL*)>(curl_easy_init(), curl_easy_cleanup);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, 2);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, 2);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_URL, host.c_str());
|
||||
curl_easy_perform(curl.get());
|
||||
}
|
||||
@@ -49,7 +49,7 @@ predicate functionsMissingReturnStmt(Function f, ControlFlowNode blame) {
|
||||
predicate functionImperfectlyExtracted(Function f) {
|
||||
exists(CompilerError e | f.getBlock().getLocation().subsumes(e.getLocation()))
|
||||
or
|
||||
exists(ErrorExpr ee | ee.getEnclosingFunction() = f)
|
||||
f.hasErrors()
|
||||
or
|
||||
count(f.getType()) > 1
|
||||
or
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 1.2.4-dev
|
||||
version: 1.2.5-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "../../../../../library-tests/string_concat/stl.h"
|
||||
|
||||
namespace std{
|
||||
struct CURL {};
|
||||
typedef CURL curl;
|
||||
enum curl_constant{
|
||||
CURLOPT_URL,
|
||||
CURLOPT_SSL_VERIFYHOST,
|
||||
CURLOPT_SSL_VERIFYPEER
|
||||
};
|
||||
|
||||
CURL *curl_easy_init();
|
||||
void curl_easy_cleanup(CURL *handle);
|
||||
void curl_easy_perform(CURL *handle);
|
||||
void curl_easy_setopt(CURL *handle, curl_constant param, int p);
|
||||
void curl_easy_setopt(CURL *handle, curl_constant param, char* p);
|
||||
}
|
||||
|
||||
|
||||
using namespace std;
|
||||
char host[] = "codeql.com";
|
||||
|
||||
void bad(void) {
|
||||
std::unique_ptr<CURL> curl = std::unique_ptr<CURL>(curl_easy_init());
|
||||
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_URL, host);
|
||||
curl_easy_perform(curl.get());
|
||||
}
|
||||
|
||||
void good(void) {
|
||||
std::unique_ptr<CURL> curl = std::unique_ptr<CURL>(curl_easy_init());
|
||||
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, 2);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, 2);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_URL, host);
|
||||
curl_easy_perform(curl.get());
|
||||
}
|
||||
|
||||
int main(int c, char** argv){
|
||||
bad();
|
||||
good();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
| CurlSSL.cpp:25:2:25:17 | call to curl_easy_setopt | This call disables Secure Socket Layer and could potentially lead to MITM attacks |
|
||||
| CurlSSL.cpp:26:2:26:17 | call to curl_easy_setopt | This call disables Secure Socket Layer and could potentially lead to MITM attacks |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-295/CurlSSL.ql
|
||||
@@ -3,20 +3,20 @@ failures
|
||||
edges
|
||||
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:10 |
|
||||
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:2 |
|
||||
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:2 Sink:MaD:6 |
|
||||
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:2 Sink:MaD:6 |
|
||||
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction |
|
||||
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:100:64:100:71 | *send_str | provenance | TaintFunction |
|
||||
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | |
|
||||
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
|
||||
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:6 |
|
||||
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:6 |
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:10 |
|
||||
| test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | test.cpp:4:5:4:11 | [summary] to write: ReturnValue in ymlStep | provenance | MaD:644 |
|
||||
| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:7:10:7:18 | call to ymlSource | provenance | Src:MaD:642 |
|
||||
| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:11:10:11:10 | x | provenance | Sink:MaD:643 |
|
||||
| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:11:10:11:10 | x | provenance | Sink:MaD:643 |
|
||||
| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:13:18:13:18 | x | provenance | |
|
||||
| test.cpp:13:10:13:16 | call to ymlStep | test.cpp:13:10:13:16 | call to ymlStep | provenance | |
|
||||
| test.cpp:13:10:13:16 | call to ymlStep | test.cpp:15:10:15:10 | y | provenance | Sink:MaD:643 |
|
||||
| test.cpp:13:10:13:16 | call to ymlStep | test.cpp:15:10:15:10 | y | provenance | Sink:MaD:643 |
|
||||
| test.cpp:13:18:13:18 | x | test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | provenance | |
|
||||
| test.cpp:13:18:13:18 | x | test.cpp:13:10:13:16 | call to ymlStep | provenance | MaD:644 |
|
||||
nodes
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| c.c | library-tests/files/c.c | CFile, MetricFile | C | | |
|
||||
| files1.cpp | library-tests/files/files1.cpp | CppFile, MetricFile | C++ | swap | t |
|
||||
| files1.h | library-tests/files/files1.h | HeaderFile, MetricFile | | swap | |
|
||||
| files2.cpp | library-tests/files/files2.cpp | CppFile, MetricFile | C++ | g | x, y |
|
||||
| c.c | c.c | CFile, MetricFile | C | | |
|
||||
| files1.cpp | files1.cpp | CppFile, MetricFile | C++ | swap | t |
|
||||
| files1.h | files1.h | HeaderFile, MetricFile | | swap | |
|
||||
| files2.cpp | files2.cpp | CppFile, MetricFile | C++ | g | x, y |
|
||||
|
||||
@@ -2,25 +2,168 @@
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | false |
|
||||
| file://:0:0:0:0 | __super | false |
|
||||
| file://:0:0:0:0 | __va_list_tag | false |
|
||||
| file://:0:0:0:0 | decltype([...](...){...}) | false |
|
||||
| file://:0:0:0:0 | operator= | false |
|
||||
| file://:0:0:0:0 | operator= | false |
|
||||
| test.cpp:0:0:0:0 | test.cpp | false |
|
||||
| test.cpp:2:1:2:61 | #define FOO class S{int i; void f(void) { int j; return; } }; | false |
|
||||
| test.cpp:2:1:2:68 | #define CLASS_DECL class S{int i; void f(void) { int j; return; } }; | false |
|
||||
| test.cpp:4:1:4:1 | S | false |
|
||||
| test.cpp:4:1:4:1 | declaration of S | false |
|
||||
| test.cpp:4:1:4:1 | declaration of operator= | false |
|
||||
| test.cpp:4:1:4:1 | declaration of operator= | false |
|
||||
| test.cpp:4:1:4:1 | operator= | false |
|
||||
| test.cpp:4:1:4:1 | operator= | false |
|
||||
| test.cpp:4:1:4:3 | FOO | false |
|
||||
| test.cpp:4:1:4:3 | S | false |
|
||||
| test.cpp:4:1:4:3 | declaration | true |
|
||||
| test.cpp:4:1:4:3 | definition of S | true |
|
||||
| test.cpp:4:1:4:3 | definition of f | true |
|
||||
| test.cpp:4:1:4:3 | definition of i | true |
|
||||
| test.cpp:4:1:4:3 | definition of j | true |
|
||||
| test.cpp:4:1:4:3 | f | false |
|
||||
| test.cpp:4:1:4:3 | i | false |
|
||||
| test.cpp:4:1:4:3 | j | true |
|
||||
| test.cpp:4:1:4:3 | return ... | true |
|
||||
| test.cpp:4:1:4:3 | { ... } | true |
|
||||
| test.cpp:4:1:4:10 | CLASS_DECL | false |
|
||||
| test.cpp:4:1:4:10 | S | false |
|
||||
| test.cpp:4:1:4:10 | declaration | true |
|
||||
| test.cpp:4:1:4:10 | definition of S | true |
|
||||
| test.cpp:4:1:4:10 | definition of f | true |
|
||||
| test.cpp:4:1:4:10 | definition of i | true |
|
||||
| test.cpp:4:1:4:10 | definition of j | true |
|
||||
| test.cpp:4:1:4:10 | f | false |
|
||||
| test.cpp:4:1:4:10 | i | false |
|
||||
| test.cpp:4:1:4:10 | j | true |
|
||||
| test.cpp:4:1:4:10 | return ... | true |
|
||||
| test.cpp:4:1:4:10 | { ... } | true |
|
||||
| test.cpp:6:1:6:42 | #define FUNCTION_DECL void f1() { int k; } | false |
|
||||
| test.cpp:8:1:8:13 | FUNCTION_DECL | false |
|
||||
| test.cpp:8:1:8:13 | declaration | true |
|
||||
| test.cpp:8:1:8:13 | definition of f1 | true |
|
||||
| test.cpp:8:1:8:13 | definition of k | true |
|
||||
| test.cpp:8:1:8:13 | f1 | false |
|
||||
| test.cpp:8:1:8:13 | k | true |
|
||||
| test.cpp:8:1:8:13 | return ... | true |
|
||||
| test.cpp:8:1:8:13 | { ... } | true |
|
||||
| test.cpp:10:1:10:33 | #define VARIABLE_DECL int v1 = 1; | false |
|
||||
| test.cpp:12:1:12:13 | 1 | true |
|
||||
| test.cpp:12:1:12:13 | VARIABLE_DECL | false |
|
||||
| test.cpp:12:1:12:13 | definition of v1 | true |
|
||||
| test.cpp:12:1:12:13 | initializer for v1 | true |
|
||||
| test.cpp:12:1:12:13 | v1 | true |
|
||||
| test.cpp:14:1:14:35 | #define TYPE_DECL_1 typedef int t1; | false |
|
||||
| test.cpp:16:1:16:11 | TYPE_DECL_1 | false |
|
||||
| test.cpp:16:1:16:11 | declaration of t1 | true |
|
||||
| test.cpp:16:1:16:11 | t1 | false |
|
||||
| test.cpp:18:1:18:35 | #define TYPE_DECL_2 using t2 = int; | false |
|
||||
| test.cpp:20:1:20:11 | TYPE_DECL_2 | false |
|
||||
| test.cpp:20:1:20:11 | declaration of t2 | true |
|
||||
| test.cpp:20:1:20:11 | t2 | false |
|
||||
| test.cpp:22:1:22:47 | #define NAMESPACE_DECL namespace ns { int v2; } | false |
|
||||
| test.cpp:24:1:24:14 | NAMESPACE_DECL | false |
|
||||
| test.cpp:24:1:24:14 | definition of v2 | true |
|
||||
| test.cpp:24:1:24:14 | ns | false |
|
||||
| test.cpp:24:1:24:14 | ns | false |
|
||||
| test.cpp:24:1:24:14 | v2 | true |
|
||||
| test.cpp:26:1:26:43 | #define USING_NAMESPACE using namespace ns; | false |
|
||||
| test.cpp:28:1:28:34 | #define ENUM_CONSTANT enum_element | false |
|
||||
| test.cpp:30:12:30:21 | definition of enum_class | false |
|
||||
| test.cpp:30:12:30:21 | enum_class | false |
|
||||
| test.cpp:30:25:30:37 | ENUM_CONSTANT | false |
|
||||
| test.cpp:30:25:30:37 | enum_element | false |
|
||||
| test.cpp:32:1:32:41 | #define USING_ENUM using enum enum_class; | false |
|
||||
| test.cpp:34:1:34:10 | USING_ENUM | false |
|
||||
| test.cpp:34:1:34:10 | using enum enum_class | false |
|
||||
| test.cpp:36:1:36:48 | #define STATIC_ASSERT static_assert(1 == 1, ""); | false |
|
||||
| test.cpp:38:1:38:13 | 1 | true |
|
||||
| test.cpp:38:1:38:13 | 1 | true |
|
||||
| test.cpp:38:1:38:13 | ... == ... | true |
|
||||
| test.cpp:38:1:38:13 | STATIC_ASSERT | false |
|
||||
| test.cpp:38:1:38:13 | static_assert(..., "") | false |
|
||||
| test.cpp:40:1:40:42 | #define ATTRIBUTE [[nodiscard("reason1")]] | false |
|
||||
| test.cpp:42:1:42:9 | ATTRIBUTE | false |
|
||||
| test.cpp:42:1:42:9 | nodiscard | false |
|
||||
| test.cpp:42:1:42:9 | reason1 | false |
|
||||
| test.cpp:42:1:42:9 | reason1 | true |
|
||||
| test.cpp:43:5:43:6 | declaration of f2 | false |
|
||||
| test.cpp:43:5:43:6 | f2 | false |
|
||||
| test.cpp:45:1:45:31 | #define ATTRIBUTE_ARG "reason2" | false |
|
||||
| test.cpp:47:3:47:11 | nodiscard | false |
|
||||
| test.cpp:47:13:47:25 | ATTRIBUTE_ARG | false |
|
||||
| test.cpp:47:13:47:25 | reason2 | false |
|
||||
| test.cpp:47:13:47:25 | reason2 | true |
|
||||
| test.cpp:48:5:48:6 | declaration of f3 | false |
|
||||
| test.cpp:48:5:48:6 | f3 | false |
|
||||
| test.cpp:50:1:50:16 | #define TYPE int | false |
|
||||
| test.cpp:52:1:52:4 | TYPE | false |
|
||||
| test.cpp:52:6:52:7 | definition of v3 | true |
|
||||
| test.cpp:52:6:52:7 | v3 | true |
|
||||
| test.cpp:52:11:52:11 | 1 | false |
|
||||
| test.cpp:52:11:52:11 | initializer for v3 | false |
|
||||
| test.cpp:54:1:54:29 | #define DERIVATION : public S | false |
|
||||
| test.cpp:56:7:56:7 | T | false |
|
||||
| test.cpp:56:7:56:7 | T | false |
|
||||
| test.cpp:56:7:56:7 | declaration of T | false |
|
||||
| test.cpp:56:7:56:7 | declaration of operator= | false |
|
||||
| test.cpp:56:7:56:7 | declaration of operator= | false |
|
||||
| test.cpp:56:7:56:7 | definition of T | false |
|
||||
| test.cpp:56:7:56:7 | operator= | false |
|
||||
| test.cpp:56:7:56:7 | operator= | false |
|
||||
| test.cpp:56:9:56:18 | DERIVATION | false |
|
||||
| test.cpp:56:9:56:18 | derivation | false |
|
||||
| test.cpp:58:1:58:31 | #define FRIEND friend int f3(); | false |
|
||||
| test.cpp:60:7:60:7 | U | false |
|
||||
| test.cpp:60:7:60:7 | declaration of operator= | false |
|
||||
| test.cpp:60:7:60:7 | declaration of operator= | false |
|
||||
| test.cpp:60:7:60:7 | definition of U | false |
|
||||
| test.cpp:60:7:60:7 | operator= | false |
|
||||
| test.cpp:60:7:60:7 | operator= | false |
|
||||
| test.cpp:61:3:61:8 | FRIEND | false |
|
||||
| test.cpp:61:3:61:8 | U's friend | false |
|
||||
| test.cpp:64:1:64:24 | #define NAME_QUAL_1 ns:: | false |
|
||||
| test.cpp:66:1:66:22 | #define NAME_QUAL_2 ns | false |
|
||||
| test.cpp:68:1:68:19 | #define LOCAL_VAR m | false |
|
||||
| test.cpp:70:6:70:7 | definition of f4 | false |
|
||||
| test.cpp:70:6:70:7 | f4 | false |
|
||||
| test.cpp:70:11:76:1 | { ... } | false |
|
||||
| test.cpp:71:5:71:8 | ns:: | false |
|
||||
| test.cpp:71:5:71:15 | NAME_QUAL_1 | false |
|
||||
| test.cpp:71:5:71:18 | v2 | false |
|
||||
| test.cpp:71:5:71:19 | ExprStmt | false |
|
||||
| test.cpp:72:5:72:8 | ns:: | false |
|
||||
| test.cpp:72:5:72:15 | NAME_QUAL_2 | false |
|
||||
| test.cpp:72:5:72:21 | v2 | false |
|
||||
| test.cpp:72:5:72:22 | ExprStmt | false |
|
||||
| test.cpp:73:5:73:23 | declaration | false |
|
||||
| test.cpp:73:9:73:17 | LOCAL_VAR | false |
|
||||
| test.cpp:73:9:73:17 | definition of m | true |
|
||||
| test.cpp:73:9:73:17 | m | true |
|
||||
| test.cpp:73:20:73:22 | 42 | false |
|
||||
| test.cpp:73:20:73:22 | initializer for m | false |
|
||||
| test.cpp:74:5:74:41 | declaration | false |
|
||||
| test.cpp:74:10:74:10 | definition of l | false |
|
||||
| test.cpp:74:10:74:10 | l | false |
|
||||
| test.cpp:74:13:74:40 | [...](...){...} | false |
|
||||
| test.cpp:74:13:74:40 | initializer for l | false |
|
||||
| test.cpp:74:13:74:40 | {...} | false |
|
||||
| test.cpp:74:14:74:14 | (unnamed constructor) | false |
|
||||
| test.cpp:74:14:74:14 | (unnamed constructor) | false |
|
||||
| test.cpp:74:14:74:14 | (unnamed constructor) | false |
|
||||
| test.cpp:74:14:74:14 | declaration of (unnamed constructor) | false |
|
||||
| test.cpp:74:14:74:14 | declaration of (unnamed constructor) | false |
|
||||
| test.cpp:74:14:74:14 | definition of (unnamed constructor) | false |
|
||||
| test.cpp:74:14:74:14 | definition of operator= | false |
|
||||
| test.cpp:74:14:74:14 | operator= | false |
|
||||
| test.cpp:74:15:74:15 | definition of m | false |
|
||||
| test.cpp:74:15:74:15 | m | false |
|
||||
| test.cpp:74:15:74:15 | m | false |
|
||||
| test.cpp:74:15:74:23 | LOCAL_VAR | false |
|
||||
| test.cpp:74:15:74:23 | m | true |
|
||||
| test.cpp:74:25:74:25 | definition of operator() | false |
|
||||
| test.cpp:74:25:74:25 | operator() | false |
|
||||
| test.cpp:74:28:74:40 | { ... } | false |
|
||||
| test.cpp:74:30:74:38 | return ... | false |
|
||||
| test.cpp:74:37:74:37 | (int)... | false |
|
||||
| test.cpp:75:5:75:5 | (const lambda [] type at line 74, col. 14)... | false |
|
||||
| test.cpp:75:5:75:5 | l | false |
|
||||
| test.cpp:75:5:75:8 | ExprStmt | false |
|
||||
| test.cpp:75:6:75:6 | call to operator() | false |
|
||||
| test.cpp:76:1:76:1 | return ... | false |
|
||||
| test.cpp:78:1:78:15 | #define ID(x) x | false |
|
||||
| test.cpp:79:1:79:23 | #define NESTED(x) ID(x) | false |
|
||||
| test.cpp:80:5:80:6 | definition of v4 | false |
|
||||
| test.cpp:80:5:80:6 | v4 | false |
|
||||
| test.cpp:80:10:80:18 | ID(x) | false |
|
||||
| test.cpp:80:10:80:18 | NESTED(x) | false |
|
||||
| test.cpp:80:17:80:17 | 1 | true |
|
||||
| test.cpp:80:17:80:17 | initializer for v4 | true |
|
||||
| test.cpp:82:1:82:39 | // semmle-extractor-options: -std=c++20 | false |
|
||||
|
||||
@@ -1,5 +1,82 @@
|
||||
|
||||
#define FOO class S{int i; void f(void) { int j; return; } };
|
||||
#define CLASS_DECL class S{int i; void f(void) { int j; return; } };
|
||||
|
||||
FOO
|
||||
CLASS_DECL
|
||||
|
||||
#define FUNCTION_DECL void f1() { int k; }
|
||||
|
||||
FUNCTION_DECL
|
||||
|
||||
#define VARIABLE_DECL int v1 = 1;
|
||||
|
||||
VARIABLE_DECL
|
||||
|
||||
#define TYPE_DECL_1 typedef int t1;
|
||||
|
||||
TYPE_DECL_1
|
||||
|
||||
#define TYPE_DECL_2 using t2 = int;
|
||||
|
||||
TYPE_DECL_2
|
||||
|
||||
#define NAMESPACE_DECL namespace ns { int v2; }
|
||||
|
||||
NAMESPACE_DECL
|
||||
|
||||
#define USING_NAMESPACE using namespace ns;
|
||||
|
||||
#define ENUM_CONSTANT enum_element
|
||||
|
||||
enum class enum_class { ENUM_CONSTANT };
|
||||
|
||||
#define USING_ENUM using enum enum_class;
|
||||
|
||||
USING_ENUM
|
||||
|
||||
#define STATIC_ASSERT static_assert(1 == 1, "");
|
||||
|
||||
STATIC_ASSERT
|
||||
|
||||
#define ATTRIBUTE [[nodiscard("reason1")]]
|
||||
|
||||
ATTRIBUTE
|
||||
int f2();
|
||||
|
||||
#define ATTRIBUTE_ARG "reason2"
|
||||
|
||||
[[nodiscard(ATTRIBUTE_ARG)]]
|
||||
int f3();
|
||||
|
||||
#define TYPE int
|
||||
|
||||
TYPE v3 = 1;
|
||||
|
||||
#define DERIVATION : public S
|
||||
|
||||
class T DERIVATION {};
|
||||
|
||||
#define FRIEND friend int f3();
|
||||
|
||||
class U {
|
||||
FRIEND
|
||||
};
|
||||
|
||||
#define NAME_QUAL_1 ns::
|
||||
|
||||
#define NAME_QUAL_2 ns
|
||||
|
||||
#define LOCAL_VAR m
|
||||
|
||||
void f4() {
|
||||
NAME_QUAL_1 v2;
|
||||
NAME_QUAL_2 :: v2;
|
||||
int LOCAL_VAR = 42;
|
||||
auto l = [LOCAL_VAR]() { return m; };
|
||||
l();
|
||||
}
|
||||
|
||||
#define ID(x) x
|
||||
#define NESTED(x) ID(x)
|
||||
int v4 = NESTED(1);
|
||||
|
||||
// semmle-extractor-options: -std=c++20
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
| containserror.cpp:0:0:0:0 | containserror.cpp | query-tests/Diagnostics/containserror.cpp | fromSource, normalTermination |
|
||||
| containswarning.cpp:0:0:0:0 | containswarning.cpp | query-tests/Diagnostics/containswarning.cpp | fromSource, normalTermination |
|
||||
| doesnotcompile.cpp:0:0:0:0 | doesnotcompile.cpp | query-tests/Diagnostics/doesnotcompile.cpp | ExtractionProblem (severity 1), fromSource, normalTermination |
|
||||
| containserror.cpp:0:0:0:0 | containserror.cpp | containserror.cpp | fromSource, normalTermination |
|
||||
| containswarning.cpp:0:0:0:0 | containswarning.cpp | containswarning.cpp | fromSource, normalTermination |
|
||||
| doesnotcompile.cpp:0:0:0:0 | doesnotcompile.cpp | doesnotcompile.cpp | ExtractionProblem (severity 1), fromSource, normalTermination |
|
||||
| file://:0:0:0:0 | | | |
|
||||
| header.h:0:0:0:0 | header.h | query-tests/Diagnostics/header.h | fromSource |
|
||||
| successful.cpp:0:0:0:0 | successful.cpp | query-tests/Diagnostics/successful.cpp | fromSource, normalTermination |
|
||||
| header.h:0:0:0:0 | header.h | header.h | fromSource |
|
||||
| successful.cpp:0:0:0:0 | successful.cpp | successful.cpp | fromSource, normalTermination |
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
| comment_prototypes.c:29:6:29:11 | proto6 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:9:5:9:10 | call to proto6 | query-tests/Documentation/DocumentApi/comment_prototypes_caller1.c |
|
||||
| comment_prototypes.c:29:6:29:11 | proto6 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:9:5:9:10 | call to proto6 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.c |
|
||||
| comment_prototypes.c:34:6:34:11 | proto7 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:10:5:10:10 | call to proto7 | query-tests/Documentation/DocumentApi/comment_prototypes_caller1.c |
|
||||
| comment_prototypes.c:34:6:34:11 | proto7 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:10:5:10:10 | call to proto7 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.c |
|
||||
| comment_prototypes.c:45:6:45:11 | proto9 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:12:5:12:10 | call to proto9 | query-tests/Documentation/DocumentApi/comment_prototypes_caller1.c |
|
||||
| comment_prototypes.c:45:6:45:11 | proto9 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:12:5:12:10 | call to proto9 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.c |
|
||||
| comment_prototypes.c:50:6:50:12 | proto10 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:13:5:13:11 | call to proto10 | query-tests/Documentation/DocumentApi/comment_prototypes_caller1.c |
|
||||
| comment_prototypes.c:50:6:50:12 | proto10 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:13:5:13:11 | call to proto10 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.c |
|
||||
| comment_prototypes.c:55:6:55:12 | proto11 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:14:5:14:11 | call to proto11 | query-tests/Documentation/DocumentApi/comment_prototypes_caller1.c |
|
||||
| comment_prototypes.c:55:6:55:12 | proto11 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:14:5:14:11 | call to proto11 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.c |
|
||||
| comment_prototypes.c:66:6:66:12 | proto13 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:16:5:16:11 | call to proto13 | query-tests/Documentation/DocumentApi/comment_prototypes_caller1.c |
|
||||
| comment_prototypes.c:66:6:66:12 | proto13 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:16:5:16:11 | call to proto13 | query-tests/Documentation/DocumentApi/comment_prototypes_caller2.c |
|
||||
| definition.c:2:6:2:7 | f1 | Functions called from other files should be documented (called from $@). | user1.c:9:5:9:6 | call to f1 | query-tests/Documentation/DocumentApi/user1.c |
|
||||
| definition.c:2:6:2:7 | f1 | Functions called from other files should be documented (called from $@). | user2.c:7:5:7:6 | call to f1 | query-tests/Documentation/DocumentApi/user2.c |
|
||||
| definition.c:32:6:32:7 | f6 | Functions called from other files should be documented (called from $@). | user1.c:14:5:14:6 | call to f6 | query-tests/Documentation/DocumentApi/user1.c |
|
||||
| definition.c:32:6:32:7 | f6 | Functions called from other files should be documented (called from $@). | user2.c:10:5:10:6 | call to f6 | query-tests/Documentation/DocumentApi/user2.c |
|
||||
| comment_prototypes.c:29:6:29:11 | proto6 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:9:5:9:10 | call to proto6 | comment_prototypes_caller1.c |
|
||||
| comment_prototypes.c:29:6:29:11 | proto6 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:9:5:9:10 | call to proto6 | comment_prototypes_caller2.c |
|
||||
| comment_prototypes.c:34:6:34:11 | proto7 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:10:5:10:10 | call to proto7 | comment_prototypes_caller1.c |
|
||||
| comment_prototypes.c:34:6:34:11 | proto7 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:10:5:10:10 | call to proto7 | comment_prototypes_caller2.c |
|
||||
| comment_prototypes.c:45:6:45:11 | proto9 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:12:5:12:10 | call to proto9 | comment_prototypes_caller1.c |
|
||||
| comment_prototypes.c:45:6:45:11 | proto9 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:12:5:12:10 | call to proto9 | comment_prototypes_caller2.c |
|
||||
| comment_prototypes.c:50:6:50:12 | proto10 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:13:5:13:11 | call to proto10 | comment_prototypes_caller1.c |
|
||||
| comment_prototypes.c:50:6:50:12 | proto10 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:13:5:13:11 | call to proto10 | comment_prototypes_caller2.c |
|
||||
| comment_prototypes.c:55:6:55:12 | proto11 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:14:5:14:11 | call to proto11 | comment_prototypes_caller1.c |
|
||||
| comment_prototypes.c:55:6:55:12 | proto11 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:14:5:14:11 | call to proto11 | comment_prototypes_caller2.c |
|
||||
| comment_prototypes.c:66:6:66:12 | proto13 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller1.c:16:5:16:11 | call to proto13 | comment_prototypes_caller1.c |
|
||||
| comment_prototypes.c:66:6:66:12 | proto13 | Functions called from other files should be documented (called from $@). | comment_prototypes_caller2.c:16:5:16:11 | call to proto13 | comment_prototypes_caller2.c |
|
||||
| definition.c:2:6:2:7 | f1 | Functions called from other files should be documented (called from $@). | user1.c:9:5:9:6 | call to f1 | user1.c |
|
||||
| definition.c:2:6:2:7 | f1 | Functions called from other files should be documented (called from $@). | user2.c:7:5:7:6 | call to f1 | user2.c |
|
||||
| definition.c:32:6:32:7 | f6 | Functions called from other files should be documented (called from $@). | user1.c:14:5:14:6 | call to f6 | user1.c |
|
||||
| definition.c:32:6:32:7 | f6 | Functions called from other files should be documented (called from $@). | user2.c:10:5:10:6 | call to f6 | user2.c |
|
||||
|
||||
@@ -10,3 +10,4 @@
|
||||
| test.c:15:2:15:7 | call to printf | Format for printf expects 3 arguments but given 2 |
|
||||
| test.c:19:2:19:7 | call to printf | Format for printf expects 2 arguments but given 1 |
|
||||
| test.c:29:3:29:8 | call to printf | Format for printf expects 2 arguments but given 1 |
|
||||
| test.c:53:2:53:10 | call to my_logger | Format for my_logger expects 3 arguments but given 2 |
|
||||
|
||||
@@ -44,3 +44,6 @@ void test_custom_printf2()
|
||||
printf("", "%i %i", 100, 200); // GOOD
|
||||
printf("%i %i", "" ); // GOOD
|
||||
}
|
||||
|
||||
extern "C" void my_logger(int param, char *fmt, ...) __attribute__((format(printf, 2, 3))) {}
|
||||
|
||||
|
||||
@@ -46,4 +46,12 @@ void test(int i, const char *str)
|
||||
printf("%Y", 1, 2); // GOOD (unknown format character, this might be correct)
|
||||
printf("%1.1Y", 1, 2); // GOOD (unknown format character, this might be correct)
|
||||
printf("%*.*Y", 1, 2); // GOOD (unknown format character, this might be correct)
|
||||
|
||||
// Implicit logger function declaration
|
||||
my_logger(0, "%i %i %i %i %i %i\n", 1, 2, 3, 4, 5, 6); // GOOD
|
||||
my_logger(0, "%i %i %i\n", 1, 2, 3); // GOOD
|
||||
my_logger(0, "%i %i %i\n", 1, 2); // BAD (too few format arguments)
|
||||
}
|
||||
|
||||
// A spurious definition of my_logger
|
||||
extern void my_logger(int param, char *fmt, int, int, int, int, int);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibC<\|>unknown | 5 |
|
||||
| /query-tests/Metrics/Dependencies/include.h<\|>LibD<\|>unknown | 1 |
|
||||
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibA<\|>unknown | 1 |
|
||||
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibB<\|>unknown | 1 |
|
||||
| /main.cpp<\|>LibC<\|>unknown | 5 |
|
||||
| /include.h<\|>LibD<\|>unknown | 1 |
|
||||
| /main.cpp<\|>LibA<\|>unknown | 1 |
|
||||
| /main.cpp<\|>LibB<\|>unknown | 1 |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| /query-tests/Metrics/Dependencies/include.h<\|>LibD<\|>unknown | include.h:0:0:0:0 | include.h |
|
||||
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibA<\|>unknown | main.cpp:0:0:0:0 | main.cpp |
|
||||
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibB<\|>unknown | main.cpp:0:0:0:0 | main.cpp |
|
||||
| /query-tests/Metrics/Dependencies/main.cpp<\|>LibC<\|>unknown | main.cpp:0:0:0:0 | main.cpp |
|
||||
| /include.h<\|>LibD<\|>unknown | include.h:0:0:0:0 | include.h |
|
||||
| /main.cpp<\|>LibA<\|>unknown | main.cpp:0:0:0:0 | main.cpp |
|
||||
| /main.cpp<\|>LibB<\|>unknown | main.cpp:0:0:0:0 | main.cpp |
|
||||
| /main.cpp<\|>LibC<\|>unknown | main.cpp:0:0:0:0 | main.cpp |
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
edges
|
||||
nodes
|
||||
| errors.cpp:13:7:13:7 | definition of x | semmle.label | definition of x |
|
||||
| test.cpp:11:6:11:8 | definition of foo | semmle.label | definition of foo |
|
||||
| test.cpp:111:6:111:8 | definition of foo | semmle.label | definition of foo |
|
||||
| test.cpp:226:7:226:7 | definition of x | semmle.label | definition of x |
|
||||
@@ -14,6 +15,7 @@ nodes
|
||||
| test.cpp:472:6:472:6 | definition of x | semmle.label | definition of x |
|
||||
| test.cpp:479:6:479:6 | definition of x | semmle.label | definition of x |
|
||||
#select
|
||||
| errors.cpp:14:18:14:18 | x | errors.cpp:13:7:13:7 | definition of x | errors.cpp:13:7:13:7 | definition of x | The variable $@ may not be initialized at this access. | errors.cpp:13:7:13:7 | x | x |
|
||||
| test.cpp:12:6:12:8 | foo | test.cpp:11:6:11:8 | definition of foo | test.cpp:11:6:11:8 | definition of foo | The variable $@ may not be initialized at this access. | test.cpp:11:6:11:8 | foo | foo |
|
||||
| test.cpp:113:6:113:8 | foo | test.cpp:111:6:111:8 | definition of foo | test.cpp:111:6:111:8 | definition of foo | The variable $@ may not be initialized at this access. | test.cpp:111:6:111:8 | foo | foo |
|
||||
| test.cpp:227:3:227:3 | x | test.cpp:226:7:226:7 | definition of x | test.cpp:226:7:226:7 | definition of x | The variable $@ may not be initialized at this access. | test.cpp:226:7:226:7 | x | x |
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// semmle-extractor-options: --expect_errors
|
||||
|
||||
int f1() {
|
||||
int x;
|
||||
initialize(&x); // error expression - initialize() is not defined
|
||||
return x; // GOOD - assume x is initialized
|
||||
}
|
||||
|
||||
void * operator new(unsigned long, bool);
|
||||
void operator delete(void*, bool);
|
||||
|
||||
int f2() {
|
||||
int x;
|
||||
new(true) int (x); // BAD, ignore implicit error expression
|
||||
}
|
||||
@@ -53,4 +53,59 @@ void NonStringFalsePositiveTest2(unsigned char* buffer)
|
||||
{
|
||||
wchar_t *lpWchar = NULL;
|
||||
lpWchar = (LPWSTR)buffer; // Possible False Positive
|
||||
}
|
||||
}
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
using FOO = BYTE*;
|
||||
|
||||
void NonStringFalsePositiveTest3(FOO buffer)
|
||||
{
|
||||
wchar_t *lpWchar = NULL;
|
||||
lpWchar = (LPWSTR)buffer; // GOOD
|
||||
}
|
||||
|
||||
#define UNICODE 0x8
|
||||
|
||||
// assume EMPTY_MACRO is tied to if UNICODE is enabled
|
||||
#ifdef EMPTY_MACRO
|
||||
typedef WCHAR* LPTSTR;
|
||||
#else
|
||||
typedef char* LPTSTR;
|
||||
#endif
|
||||
|
||||
void CheckedConversionFalsePositiveTest3(unsigned short flags, LPTSTR buffer)
|
||||
{
|
||||
wchar_t *lpWchar = NULL;
|
||||
if(flags & UNICODE)
|
||||
lpWchar = (LPWSTR)buffer; // GOOD
|
||||
else
|
||||
lpWchar = (LPWSTR)buffer; // BUG
|
||||
|
||||
if((flags & UNICODE) == 0x8)
|
||||
lpWchar = (LPWSTR)buffer; // GOOD
|
||||
else
|
||||
lpWchar = (LPWSTR)buffer; // BUG
|
||||
|
||||
if((flags & UNICODE) != 0x8)
|
||||
lpWchar = (LPWSTR)buffer; // BUG
|
||||
else
|
||||
lpWchar = (LPWSTR)buffer; // GOOD
|
||||
|
||||
// Bad operator precedence
|
||||
if(flags & UNICODE == 0x8)
|
||||
lpWchar = (LPWSTR)buffer; // BUG
|
||||
else
|
||||
lpWchar = (LPWSTR)buffer; // BUG
|
||||
|
||||
if((flags & UNICODE) != 0)
|
||||
lpWchar = (LPWSTR)buffer; // GOOD
|
||||
else
|
||||
lpWchar = (LPWSTR)buffer; // BUG
|
||||
|
||||
if((flags & UNICODE) == 0)
|
||||
lpWchar = (LPWSTR)buffer; // BUG
|
||||
else
|
||||
lpWchar = (LPWSTR)buffer; // GOOD
|
||||
|
||||
lpWchar = (LPWSTR)buffer; // BUG
|
||||
}
|
||||
|
||||
@@ -3,3 +3,11 @@
|
||||
| WcharCharConversion.cpp:24:22:24:27 | lpChar | Conversion from char * to wchar_t *. Use of invalid string can lead to undefined behavior. |
|
||||
| WcharCharConversion.cpp:26:23:26:28 | lpChar | Conversion from char * to LPCWSTR. Use of invalid string can lead to undefined behavior. |
|
||||
| WcharCharConversion.cpp:27:17:27:22 | lpChar | Conversion from char * to LPWSTR. Use of invalid string can lead to undefined behavior. |
|
||||
| WcharCharConversion.cpp:82:21:82:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
|
||||
| WcharCharConversion.cpp:87:21:87:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
|
||||
| WcharCharConversion.cpp:90:21:90:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
|
||||
| WcharCharConversion.cpp:96:21:96:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
|
||||
| WcharCharConversion.cpp:98:21:98:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
|
||||
| WcharCharConversion.cpp:103:21:103:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
|
||||
| WcharCharConversion.cpp:106:21:106:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
|
||||
| WcharCharConversion.cpp:110:20:110:25 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Context.ExtractionError($"Couldn't read file: {originalPath}. {exc.Message}", null, null, exc.StackTrace);
|
||||
Context.ExtractionError($"Couldn't read file: {originalPath}. {exc.Message}", null, null, exc.StackTrace, Semmle.Util.Logging.Severity.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.7.26
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.25
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.7.26
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.7.25
|
||||
lastReleaseVersion: 1.7.26
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-all
|
||||
version: 1.7.26-dev
|
||||
version: 1.7.27-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.7.26
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.25
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.7.26
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.7.25
|
||||
lastReleaseVersion: 1.7.26
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-queries
|
||||
version: 1.7.26-dev
|
||||
version: 1.7.27-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
@@ -61,8 +61,3 @@ query predicate preBasicBlockConsistency(ControlFlowElement cfe1, ControlFlowEle
|
||||
bbIntraSuccInconsistency(cfe1, cfe2) and
|
||||
s = "intra succ inconsistency"
|
||||
}
|
||||
|
||||
query predicate multipleToString(Node n, string s) {
|
||||
s = strictconcat(n.toString(), ",") and
|
||||
strictcount(n.toString()) > 1
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
## 3.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* C#: Add support for MaD directly on properties and indexers using *attributes*. Using `Attribute.Getter` or `Attribute.Setter` in the model `ext` field applies the model to the getter or setter for properties and indexers. Prior to this change `Attribute` models unintentionally worked for property setters (if the property is decorated with the matching attribute). That is, a model that uses the `Attribute` feature directly on a property for a property setter needs to be changed to `Attribute.Setter`.
|
||||
* C#: Remove all CIL tables and related QL library functionality.
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The class `ThreatModelFlowSource` has been renamed to `ActiveThreatModelSource` to more clearly reflect it only contains the currently active threat model sources. `ThreatModelFlowSource` has been marked as deprecated.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* `DataFlow::Node` instances are no longer created for library methods and fields that are not callable (either statically or dynamically) or otherwise referred to from source code. This may affect third-party queries that use these nodes to identify library methods or fields that are present in DLL files where those methods or fields are unreferenced. If this presents a problem, consider using `Callable` and other non-dataflow classes to identify such library entities.
|
||||
* C#: Add extractor support for attributes on indexers.
|
||||
|
||||
## 2.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* C#: Add support for MaD directly on properties and indexers using *attributes*. Using `Attribute.Getter` or `Attribute.Setter` in the model `ext` field applies the model to the getter or setter for properties and indexers. Prior to this change `Attribute` models unintentionally worked for property setters (if the property is decorated with the matching attribute). That is, a model that uses the `Attribute` feature directly on a property for a property setter needs to be changed to `Attribute.Setter`.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* C#: Remove all CIL tables and related QL library functionality.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* C#: Add extractor support for attributes on indexers.
|
||||
15
csharp/ql/lib/change-notes/released/3.0.0.md
Normal file
15
csharp/ql/lib/change-notes/released/3.0.0.md
Normal file
@@ -0,0 +1,15 @@
|
||||
## 3.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* C#: Add support for MaD directly on properties and indexers using *attributes*. Using `Attribute.Getter` or `Attribute.Setter` in the model `ext` field applies the model to the getter or setter for properties and indexers. Prior to this change `Attribute` models unintentionally worked for property setters (if the property is decorated with the matching attribute). That is, a model that uses the `Attribute` feature directly on a property for a property setter needs to be changed to `Attribute.Setter`.
|
||||
* C#: Remove all CIL tables and related QL library functionality.
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The class `ThreatModelFlowSource` has been renamed to `ActiveThreatModelSource` to more clearly reflect it only contains the currently active threat model sources. `ThreatModelFlowSource` has been marked as deprecated.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* `DataFlow::Node` instances are no longer created for library methods and fields that are not callable (either statically or dynamically) or otherwise referred to from source code. This may affect third-party queries that use these nodes to identify library methods or fields that are present in DLL files where those methods or fields are unreferenced. If this presents a problem, consider using `Callable` and other non-dataflow classes to identify such library entities.
|
||||
* C#: Add extractor support for attributes on indexers.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 2.0.0
|
||||
lastReleaseVersion: 3.0.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-all
|
||||
version: 2.0.1-dev
|
||||
version: 3.0.1-dev
|
||||
groups: csharp
|
||||
dbscheme: semmlecode.csharp.dbscheme
|
||||
extractor: csharp
|
||||
|
||||
@@ -15,11 +15,19 @@ class CfgScope extends Element, @top_level_exprorstmt_parent {
|
||||
CfgScope() {
|
||||
this.getFile().fromSource() and
|
||||
(
|
||||
this instanceof Callable
|
||||
this =
|
||||
any(Callable c |
|
||||
c.(Constructor).hasInitializer()
|
||||
or
|
||||
InitializerSplitting::constructorInitializes(c, _)
|
||||
or
|
||||
c.hasBody()
|
||||
)
|
||||
or
|
||||
// For now, static initializer values have their own scope. Eventually, they
|
||||
// should be treated like instance initializers.
|
||||
this.(Assignable).(Modifiable).isStatic()
|
||||
this.(Assignable).(Modifiable).isStatic() and
|
||||
expr_parent_top_level_adjusted2(_, _, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -283,6 +283,8 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { none() }
|
||||
}
|
||||
|
||||
deprecated private import Impl<Config> as I
|
||||
|
||||
@@ -995,6 +995,52 @@ private class InstanceCallable extends Callable {
|
||||
Location getARelevantLocation() { result = l }
|
||||
}
|
||||
|
||||
/**
|
||||
* A callable which is either itself defined in source or which is the target
|
||||
* of some call in source, and therefore ought to have dataflow nodes created.
|
||||
*
|
||||
* Note that for library methods these are always unbound declarations, since
|
||||
* generic instantiations never have dataflow nodes constructed.
|
||||
*/
|
||||
private class CallableUsedInSource extends Callable {
|
||||
CallableUsedInSource() {
|
||||
// Should generate nodes even for abstract methods declared in source
|
||||
this.fromSource()
|
||||
or
|
||||
// Should generate nodes even for synthetic methods derived from source
|
||||
this.hasBody()
|
||||
or
|
||||
exists(Callable target |
|
||||
exists(Call c |
|
||||
// Note that getADynamicTarget does not always include getTarget.
|
||||
target = c.getTarget()
|
||||
or
|
||||
// Note that getARuntimeTarget cannot be used here, because the
|
||||
// DelegateLikeCall case depends on lambda-flow, which in turn
|
||||
// uses the dataflow library; hence this would introduce recursion
|
||||
// into the definition of data-flow nodes.
|
||||
exists(DispatchCall dc | c = dc.getCall() | target = dc.getADynamicTarget())
|
||||
)
|
||||
or
|
||||
target = any(CallableAccess ca).getTarget()
|
||||
|
|
||||
this = target.getUnboundDeclaration()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A field or property which is either itself defined in source or which is the target
|
||||
* of some access in source, and therefore ought to have dataflow nodes created.
|
||||
*/
|
||||
private class FieldOrPropertyUsedInSource extends FieldOrProperty {
|
||||
FieldOrPropertyUsedInSource() {
|
||||
this.fromSource()
|
||||
or
|
||||
this.getAnAccess().fromSource()
|
||||
}
|
||||
}
|
||||
|
||||
/** A collection of cached types and predicates to be evaluated in the same stage. */
|
||||
cached
|
||||
private module Cached {
|
||||
@@ -1018,8 +1064,13 @@ private module Cached {
|
||||
TAssignableDefinitionNode(AssignableDefinition def, ControlFlow::Node cfn) {
|
||||
cfn = def.getExpr().getAControlFlowNode()
|
||||
} or
|
||||
TExplicitParameterNode(Parameter p, DataFlowCallable c) { p = c.asCallable(_).getAParameter() } or
|
||||
TInstanceParameterNode(InstanceCallable c, Location l) { l = c.getARelevantLocation() } or
|
||||
TExplicitParameterNode(Parameter p, DataFlowCallable c) {
|
||||
p = c.asCallable(_).(CallableUsedInSource).getAParameter()
|
||||
} or
|
||||
TInstanceParameterNode(InstanceCallable c, Location l) {
|
||||
c instanceof CallableUsedInSource and
|
||||
l = c.getARelevantLocation()
|
||||
} or
|
||||
TDelegateSelfReferenceNode(Callable c) { lambdaCreationExpr(_, c) } or
|
||||
TLocalFunctionCreationNode(ControlFlow::Nodes::ElementNode cfn, Boolean isPostUpdate) {
|
||||
cfn.getAstNode() instanceof LocalFunctionStmt
|
||||
@@ -1055,11 +1106,13 @@ private module Cached {
|
||||
or
|
||||
lambdaCallExpr(_, cfn)
|
||||
} or
|
||||
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
|
||||
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) {
|
||||
sn.getSummarizedCallable() instanceof CallableUsedInSource
|
||||
} or
|
||||
TParamsArgumentNode(ControlFlow::Node callCfn) {
|
||||
callCfn = any(Call c | isParamsArg(c, _, _)).getAControlFlowNode()
|
||||
} or
|
||||
TFlowInsensitiveFieldNode(FieldOrProperty f) { f.isFieldLike() } or
|
||||
TFlowInsensitiveFieldNode(FieldOrPropertyUsedInSource f) { f.isFieldLike() } or
|
||||
TFlowInsensitiveCapturedVariableNode(LocalScopeVariable v) { v.isCaptured() } or
|
||||
TInstanceParameterAccessNode(ControlFlow::Node cfn, Boolean isPostUpdate) {
|
||||
cfn = getAPrimaryConstructorParameterCfn(_)
|
||||
|
||||
@@ -299,9 +299,12 @@ class ContentSet extends TContentSet {
|
||||
*/
|
||||
predicate isProperty(Property p) { this = TPropertyContentSet(p) }
|
||||
|
||||
/** Holds if this content set represent the field `f`. */
|
||||
/** Holds if this content set represents the field `f`. */
|
||||
predicate isField(Field f) { this.isSingleton(TFieldContent(f)) }
|
||||
|
||||
/** Holds if this content set represents the synthetic field `s`. */
|
||||
predicate isSyntheticField(string s) { this.isSingleton(TSyntheticFieldContent(s)) }
|
||||
|
||||
/** Holds if this content set represents an element in a collection. */
|
||||
predicate isElement() { this.isSingleton(TElementContent()) }
|
||||
|
||||
|
||||
@@ -318,7 +318,7 @@ private predicate elementSpec(
|
||||
or
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _)
|
||||
or
|
||||
neutralModel(namespace, type, name, signature, _, _) and ext = "" and subtypes = false
|
||||
neutralModel(namespace, type, name, signature, _, _) and ext = "" and subtypes = true
|
||||
}
|
||||
|
||||
private predicate elementSpec(
|
||||
@@ -602,7 +602,7 @@ private predicate interpretSummary(
|
||||
predicate interpretNeutral(UnboundCallable c, string kind, string provenance) {
|
||||
exists(string namespace, string type, string name, string signature |
|
||||
neutralModel(namespace, type, name, signature, kind, provenance) and
|
||||
c = interpretElement(namespace, type, false, name, signature, "")
|
||||
c = interpretElement(namespace, type, true, name, signature, "")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ private predicate needsChecks(ActionMethod m) { m.isEdit() and not m.isAdmin() }
|
||||
* that may indicate that it's used as the ID for some resource
|
||||
*/
|
||||
private predicate hasIdParameter(ActionMethod m) {
|
||||
exists(ThreatModelFlowSource src | src.getEnclosingCallable() = m |
|
||||
exists(ActiveThreatModelSource src | src.getEnclosingCallable() = m |
|
||||
src.asParameter().getName().toLowerCase().matches(["%id", "%idx"])
|
||||
or
|
||||
// handle cases like `Request.QueryString["Id"]`
|
||||
|
||||
@@ -55,7 +55,7 @@ deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource
|
||||
deprecated class LocalSource extends DataFlow::Node instanceof LocalFlowSource { }
|
||||
|
||||
/** A source supported by the current threat model. */
|
||||
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
private class SimpleTypeSanitizer extends Sanitizer, SimpleTypeSanitizedExpr { }
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ module CommandInjection = TaintTracking::Global<CommandInjectionConfig>;
|
||||
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
|
||||
|
||||
/** A source supported by the current threat model. */
|
||||
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
/** Command Injection sinks defined through Models as Data. */
|
||||
private class ExternalCommandInjectionExprSink extends Sink {
|
||||
|
||||
@@ -54,7 +54,7 @@ module ConditionalBypass = TaintTracking::Global<ConditionalBypassConfig>;
|
||||
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
|
||||
|
||||
/** A source supported by the current threat model. */
|
||||
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
/** The result of a reverse dns may be user-controlled. */
|
||||
class ReverseDnsSource extends Source {
|
||||
|
||||
@@ -73,14 +73,14 @@ class ExternalApiDataNode extends DataFlow::Node {
|
||||
}
|
||||
}
|
||||
|
||||
/** A configuration for tracking flow from `ThreatModelFlowSource`s to `ExternalApiDataNode`s. */
|
||||
/** A configuration for tracking flow from `ActiveThreatModelSource`s to `ExternalApiDataNode`s. */
|
||||
private module RemoteSourceToExternalApiConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
|
||||
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
|
||||
}
|
||||
|
||||
/** A module for tracking flow from `ThreatModelFlowSource`s to `ExternalApiDataNode`s. */
|
||||
/** A module for tracking flow from `ActiveThreatModelSource`s to `ExternalApiDataNode`s. */
|
||||
module RemoteSourceToExternalApi = TaintTracking::Global<RemoteSourceToExternalApiConfig>;
|
||||
|
||||
/** A node representing untrusted data being passed to an external API. */
|
||||
|
||||
@@ -60,7 +60,7 @@ module LdapInjection = TaintTracking::Global<LdapInjectionConfig>;
|
||||
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
|
||||
|
||||
/** A source supported by the current threat model. */
|
||||
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
/** LDAP sinks defined through Models as Data. */
|
||||
private class ExternalLdapExprSink extends Sink {
|
||||
|
||||
@@ -42,8 +42,8 @@ private module LogForgingConfig implements DataFlow::ConfigSig {
|
||||
*/
|
||||
module LogForging = TaintTracking::Global<LogForgingConfig>;
|
||||
|
||||
/** A source of remote user input. */
|
||||
private class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
/** A source supported by the current threat model. */
|
||||
private class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
private class HtmlSanitizer extends Sanitizer {
|
||||
HtmlSanitizer() { this.asExpr() instanceof HtmlSanitizedExpr }
|
||||
|
||||
@@ -48,7 +48,7 @@ private module MissingXmlValidationConfig implements DataFlow::ConfigSig {
|
||||
module MissingXmlValidation = TaintTracking::Global<MissingXmlValidationConfig>;
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `ThreatModelFlowSource` instead.
|
||||
* DEPRECATED: Use `ActiveThreatModelSource` instead.
|
||||
*
|
||||
* A source of remote user input.
|
||||
*/
|
||||
@@ -57,7 +57,7 @@ deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource
|
||||
/**
|
||||
* A source supported by the current threat model.
|
||||
*/
|
||||
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
/**
|
||||
* The input argument to a call to `XmlReader.Create` where the input will not be validated against
|
||||
|
||||
@@ -49,7 +49,7 @@ module ReDoS = TaintTracking::Global<ReDoSConfig>;
|
||||
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
|
||||
|
||||
/** A source supported by the current threat model. */
|
||||
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
/**
|
||||
* An expression that represents a regular expression with potential exponential behavior.
|
||||
|
||||
@@ -48,7 +48,7 @@ module RegexInjection = TaintTracking::Global<RegexInjectionConfig>;
|
||||
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
|
||||
|
||||
/** A source supported by the current threat model. */
|
||||
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
/**
|
||||
* A `pattern` argument to a construction of a `Regex`.
|
||||
|
||||
@@ -54,7 +54,7 @@ deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource
|
||||
deprecated class LocalSource extends DataFlow::Node instanceof LocalFlowSource { }
|
||||
|
||||
/** A source supported by the current threat model. */
|
||||
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
/** An argument to the `ConnectionString` property on a data connection class. */
|
||||
class SqlConnectionStringSink extends Sink {
|
||||
|
||||
@@ -65,7 +65,7 @@ deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource
|
||||
deprecated class LocalSource extends DataFlow::Node instanceof LocalFlowSource { }
|
||||
|
||||
/** A source supported by the current threat model. */
|
||||
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
/** An SQL expression passed to an API call that executes SQL. */
|
||||
class SqlInjectionExprSink extends Sink {
|
||||
|
||||
@@ -50,7 +50,7 @@ module TaintedPath = TaintTracking::Global<TaintedPathConfig>;
|
||||
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
|
||||
|
||||
/** A source supported by the current threat model. */
|
||||
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
/**
|
||||
* A path argument to a `File` method call.
|
||||
|
||||
@@ -49,7 +49,7 @@ abstract private class ConstructorOrStaticMethodSink extends Sink { }
|
||||
*/
|
||||
abstract class Sanitizer extends DataFlow::Node { }
|
||||
|
||||
private class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
private class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
/**
|
||||
* User input to object method call deserialization flow tracking configuration.
|
||||
|
||||
@@ -52,7 +52,7 @@ module UrlRedirect = TaintTracking::Global<UrlRedirectConfig>;
|
||||
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
|
||||
|
||||
/** A source supported by the current threat model. */
|
||||
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
/** URL Redirection sinks defined through Models as Data. */
|
||||
private class ExternalUrlRedirectExprSink extends Sink {
|
||||
|
||||
@@ -15,7 +15,7 @@ private import semmle.code.csharp.security.Sanitizers
|
||||
*/
|
||||
abstract class Source extends DataFlow::Node { }
|
||||
|
||||
private class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
|
||||
private class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
|
||||
|
||||
/**
|
||||
* A data flow sink for untrusted user input used in XML processing.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user