mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge branch 'main' into rust-experiment
Conflicts: shared/tree-sitter-extractor/src/trap.rs
This commit is contained in:
@@ -16,9 +16,9 @@ local_path_override(
|
||||
|
||||
bazel_dep(name = "platforms", version = "0.0.10")
|
||||
bazel_dep(name = "rules_go", version = "0.50.0")
|
||||
bazel_dep(name = "rules_pkg", version = "0.10.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.32.2")
|
||||
bazel_dep(name = "rules_python", version = "0.35.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.6.1")
|
||||
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
|
||||
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
|
||||
@@ -27,7 +27,7 @@ bazel_dep(name = "rules_kotlin", version = "1.9.4-codeql.1")
|
||||
bazel_dep(name = "gazelle", version = "0.38.0")
|
||||
bazel_dep(name = "rules_dotnet", version = "0.15.1")
|
||||
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
|
||||
bazel_dep(name = "rules_rust", version = "0.49.1")
|
||||
bazel_dep(name = "rules_rust", version = "0.49.3")
|
||||
|
||||
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
|
||||
|
||||
|
||||
26
cpp/ql/src/experimental/Security/CWE/CWE-409/Brotli.qll
Normal file
26
cpp/ql/src/experimental/Security/CWE/CWE-409/Brotli.qll
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* https://github.com/google/brotli
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import DecompressionBomb
|
||||
|
||||
/**
|
||||
* The `BrotliDecoderDecompress` function is used in flow sink.
|
||||
* See https://www.brotli.org/decode.html.
|
||||
*/
|
||||
class BrotliDecoderDecompressFunction extends DecompressionFunction {
|
||||
BrotliDecoderDecompressFunction() { this.hasGlobalName("BrotliDecoderDecompress") }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 1 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `BrotliDecoderDecompressStream` function is used in flow sink.
|
||||
* See https://www.brotli.org/decode.html.
|
||||
*/
|
||||
class BrotliDecoderDecompressStreamFunction extends DecompressionFunction {
|
||||
BrotliDecoderDecompressStreamFunction() { this.hasGlobalName("BrotliDecoderDecompressStream") }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 2 }
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import MiniZip
|
||||
import ZlibGzopen
|
||||
import ZlibInflator
|
||||
import ZlibUncompress
|
||||
import LibArchive
|
||||
import ZSTD
|
||||
import Brotli
|
||||
|
||||
/**
|
||||
* The Decompression Sink instances, extend this class to define new decompression sinks.
|
||||
*/
|
||||
abstract class DecompressionFunction extends Function {
|
||||
abstract int getArchiveParameterIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* The Decompression Flow Steps, extend this class to define new decompression sinks.
|
||||
*/
|
||||
abstract class DecompressionFlowStep extends string {
|
||||
bindingset[this]
|
||||
DecompressionFlowStep() { any() }
|
||||
|
||||
abstract predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Extracting Compressed files with any compression algorithm like gzip can cause denial of service attacks.</p>
|
||||
<p>Attackers can compress a huge file consisting of repeated similiar bytes into a small compressed file.</p>
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>When you want to decompress a user-provided compressed file you must be careful about the decompression ratio or read these files within a loop byte by byte to be able to manage the decompressed size in each cycle of the loop.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>
|
||||
Reading an uncompressed Gzip file within a loop and check for a threshold size in each cycle.
|
||||
</p>
|
||||
<sample src="example_good.cpp"/>
|
||||
|
||||
<p>
|
||||
The following example is unsafe, as we do not check the uncompressed size.
|
||||
</p>
|
||||
<sample src="example_bad.cpp" />
|
||||
|
||||
</example>
|
||||
|
||||
<references>
|
||||
|
||||
<li>
|
||||
<a href="https://zlib.net/manual.html">Zlib documentation</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="https://www.bamsoftware.com/hacks/zipbomb/">An explanation of the attack</a>
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @name User-controlled file decompression
|
||||
* @description User-controlled data that flows into decompression library APIs without checking the compression rate is dangerous
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision low
|
||||
* @id cpp/data-decompression-bomb
|
||||
* @tags security
|
||||
* experimental
|
||||
* external/cwe/cwe-409
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.security.FlowSources
|
||||
import DecompressionBomb
|
||||
|
||||
predicate isSink(FunctionCall fc, DataFlow::Node sink) {
|
||||
exists(DecompressionFunction f | fc.getTarget() = f |
|
||||
fc.getArgument(f.getArchiveParameterIndex()) = [sink.asExpr(), sink.asIndirectExpr()]
|
||||
)
|
||||
}
|
||||
|
||||
module DecompressionTaintConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSink(_, sink) }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
any(DecompressionFlowStep s).isAdditionalFlowStep(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
module DecompressionTaint = TaintTracking::Global<DecompressionTaintConfig>;
|
||||
|
||||
import DecompressionTaint::PathGraph
|
||||
|
||||
from DecompressionTaint::PathNode source, DecompressionTaint::PathNode sink, FunctionCall fc
|
||||
where DecompressionTaint::flowPath(source, sink) and isSink(fc, sink.getNode())
|
||||
select sink.getNode(), source, sink, "The decompression output of $@ is not limited", fc,
|
||||
fc.getTarget().getName()
|
||||
32
cpp/ql/src/experimental/Security/CWE/CWE-409/LibArchive.qll
Normal file
32
cpp/ql/src/experimental/Security/CWE/CWE-409/LibArchive.qll
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* https://github.com/libarchive/libarchive/wiki
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import DecompressionBomb
|
||||
|
||||
/**
|
||||
* The `archive_read_data*` functions are used in flow sink.
|
||||
* See https://github.com/libarchive/libarchive/wiki/Examples.
|
||||
*/
|
||||
class Archive_read_data_block extends DecompressionFunction {
|
||||
Archive_read_data_block() {
|
||||
this.hasGlobalName(["archive_read_data_block", "archive_read_data", "archive_read_data_into_fd"])
|
||||
}
|
||||
|
||||
override int getArchiveParameterIndex() { result = 0 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `archive_read_open_filename` function as a flow step.
|
||||
*/
|
||||
class ReadOpenFunctionStep extends DecompressionFlowStep {
|
||||
ReadOpenFunctionStep() { this = "ReadOpenFunction" }
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(FunctionCall fc | fc.getTarget().hasGlobalName("archive_read_open_filename") |
|
||||
node1.asIndirectExpr() = fc.getArgument(1) and
|
||||
node2.asIndirectExpr() = fc.getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
56
cpp/ql/src/experimental/Security/CWE/CWE-409/MiniZip.qll
Normal file
56
cpp/ql/src/experimental/Security/CWE/CWE-409/MiniZip.qll
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* https://github.com/zlib-ng/minizip-ng
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import DecompressionBomb
|
||||
|
||||
/**
|
||||
* The `mz_zip_entry` function is used in flow sink.
|
||||
* See https://github.com/zlib-ng/minizip-ng/blob/master/doc/mz_zip.md.
|
||||
*/
|
||||
class Mz_zip_entry extends DecompressionFunction {
|
||||
Mz_zip_entry() { this.hasGlobalName("mz_zip_entry_read") }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 1 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `mz_zip_reader_entry_*` and `mz_zip_reader_save_all` functions are used in flow sink.
|
||||
* See https://github.com/zlib-ng/minizip-ng/blob/master/doc/mz_zip_rw.md.
|
||||
*/
|
||||
class Mz_zip_reader_entry extends DecompressionFunction {
|
||||
Mz_zip_reader_entry() {
|
||||
this.hasGlobalName([
|
||||
"mz_zip_reader_entry_save", "mz_zip_reader_entry_read", "mz_zip_reader_entry_save_process",
|
||||
"mz_zip_reader_entry_save_file", "mz_zip_reader_entry_save_buffer", "mz_zip_reader_save_all"
|
||||
])
|
||||
}
|
||||
|
||||
override int getArchiveParameterIndex() { result = 0 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `UnzOpen*` functions are used in flow sink.
|
||||
*/
|
||||
class UnzOpenFunction extends DecompressionFunction {
|
||||
UnzOpenFunction() { this.hasGlobalName(["UnzOpen", "unzOpen64", "unzOpen2", "unzOpen2_64"]) }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 0 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `mz_zip_reader_open_file` and `mz_zip_reader_open_file_in_memory` functions as a flow step.
|
||||
*/
|
||||
class ReaderOpenFunctionStep extends DecompressionFlowStep {
|
||||
ReaderOpenFunctionStep() { this = "ReaderOpenFunctionStep" }
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(FunctionCall fc |
|
||||
fc.getTarget().hasGlobalName(["mz_zip_reader_open_file_in_memory", "mz_zip_reader_open_file"])
|
||||
|
|
||||
node1.asIndirectExpr() = fc.getArgument(1) and
|
||||
node2.asIndirectExpr() = fc.getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
88
cpp/ql/src/experimental/Security/CWE/CWE-409/ZSTD.qll
Normal file
88
cpp/ql/src/experimental/Security/CWE/CWE-409/ZSTD.qll
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* https://github.com/facebook/zstd/blob/dev/examples/streaming_decompression.c
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import DecompressionBomb
|
||||
|
||||
/**
|
||||
* The `ZSTD_decompress` function is used in flow sink.
|
||||
*/
|
||||
class ZstdDecompressFunction extends DecompressionFunction {
|
||||
ZstdDecompressFunction() { this.hasGlobalName("ZSTD_decompress") }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 2 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `ZSTD_decompressDCtx` function is used in flow sink.
|
||||
*/
|
||||
class ZstdDecompressDctxFunction extends DecompressionFunction {
|
||||
ZstdDecompressDctxFunction() { this.hasGlobalName("ZSTD_decompressDCtx") }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 3 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `ZSTD_decompressStream` function is used in flow sink.
|
||||
*/
|
||||
class ZstdDecompressStreamFunction extends DecompressionFunction {
|
||||
ZstdDecompressStreamFunction() { this.hasGlobalName("ZSTD_decompressStream") }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 2 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `ZSTD_decompress_usingDDict` function is used in flow sink.
|
||||
*/
|
||||
class ZstdDecompressUsingDdictFunction extends DecompressionFunction {
|
||||
ZstdDecompressUsingDdictFunction() { this.hasGlobalName("ZSTD_decompress_usingDDict") }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 3 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `fopen_orDie` function as a flow step.
|
||||
*/
|
||||
class FopenOrDieFunctionStep extends DecompressionFlowStep {
|
||||
FopenOrDieFunctionStep() { this = "FopenOrDieFunctionStep" }
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(FunctionCall fc | fc.getTarget().hasGlobalName("fopen_orDie") |
|
||||
node1.asIndirectExpr() = fc.getArgument(0) and
|
||||
node2.asExpr() = fc
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `fread_orDie` function as a flow step.
|
||||
*/
|
||||
class FreadOrDieFunctionStep extends DecompressionFlowStep {
|
||||
FreadOrDieFunctionStep() { this = "FreadOrDieFunctionStep" }
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(FunctionCall fc | fc.getTarget().hasGlobalName("fread_orDie") |
|
||||
node1.asExpr() = fc.getArgument(2) and
|
||||
node2.asIndirectExpr() = fc.getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `src` member of a `ZSTD_inBuffer` variable is used in a flow steps.
|
||||
*/
|
||||
class SrcMember extends DecompressionFlowStep {
|
||||
SrcMember() { this = "SrcMember" }
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(VariableAccess inBufferAccess, Field srcField, ClassAggregateLiteral c |
|
||||
inBufferAccess.getType().hasName("ZSTD_inBuffer") and
|
||||
srcField.hasName("src")
|
||||
|
|
||||
node2.asExpr() = inBufferAccess and
|
||||
inBufferAccess.getTarget().getInitializer().getExpr() = c and
|
||||
node1.asIndirectExpr() = c.getFieldExpr(srcField, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
71
cpp/ql/src/experimental/Security/CWE/CWE-409/ZlibGzopen.qll
Normal file
71
cpp/ql/src/experimental/Security/CWE/CWE-409/ZlibGzopen.qll
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* https://www.zlib.net/
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import DecompressionBomb
|
||||
|
||||
/**
|
||||
* The `gzfread` function is used in flow sink.
|
||||
*
|
||||
* `gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file)`
|
||||
*/
|
||||
class GzFreadFunction extends DecompressionFunction {
|
||||
GzFreadFunction() { this.hasGlobalName("gzfread") }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 3 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `gzgets` function is used in flow sink.
|
||||
*
|
||||
* `gzgets(gzFile file, char *buf, int len)`
|
||||
*/
|
||||
class GzGetsFunction extends DecompressionFunction {
|
||||
GzGetsFunction() { this.hasGlobalName("gzgets") }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 0 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `gzread` function is used in flow sink.
|
||||
*
|
||||
* `gzread(gzFile file, voidp buf, unsigned len)`
|
||||
*/
|
||||
class GzReadFunction extends DecompressionFunction {
|
||||
GzReadFunction() { this.hasGlobalName("gzread") }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 0 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `gzdopen` function is used in flow steps.
|
||||
*
|
||||
* `gzdopen(int fd, const char *mode)`
|
||||
*/
|
||||
class GzdopenFunctionStep extends DecompressionFlowStep {
|
||||
GzdopenFunctionStep() { this = "GzdopenFunctionStep" }
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(FunctionCall fc | fc.getTarget().hasGlobalName("gzdopen") |
|
||||
node1.asExpr() = fc.getArgument(0) and
|
||||
node2.asExpr() = fc
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `gzopen` function is used in flow steps.
|
||||
*
|
||||
* `gzopen(const char *path, const char *mode)`
|
||||
*/
|
||||
class GzopenFunctionStep extends DecompressionFlowStep {
|
||||
GzopenFunctionStep() { this = "GzopenFunctionStep" }
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(FunctionCall fc | fc.getTarget().hasGlobalName("gzopen") |
|
||||
node1.asIndirectExpr() = fc.getArgument(0) and
|
||||
node2.asExpr() = fc
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* https://www.zlib.net/
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import DecompressionBomb
|
||||
|
||||
/**
|
||||
* The `inflate` and `inflateSync` functions are used in flow sink.
|
||||
*
|
||||
* `inflate(z_stream strm, int flush)`
|
||||
*
|
||||
* `inflateSync(z_stream strm)`
|
||||
*/
|
||||
class InflateFunction extends DecompressionFunction {
|
||||
InflateFunction() { this.hasGlobalName(["inflate", "inflateSync"]) }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 0 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `next_in` member of a `z_stream` variable is used in a flow steps.
|
||||
*/
|
||||
class NextInMemberStep extends DecompressionFlowStep {
|
||||
NextInMemberStep() { this = "NextInMemberStep" }
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(Variable nextInVar |
|
||||
nextInVar.getDeclaringType().hasName("z_stream") and
|
||||
nextInVar.hasName("next_in")
|
||||
|
|
||||
node1.asIndirectExpr() = nextInVar.getAnAssignedValue() and
|
||||
node2.asExpr() =
|
||||
nextInVar.getAnAccess().getQualifier().(VariableAccess).getTarget().getAnAccess()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* https://www.zlib.net/
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import DecompressionBomb
|
||||
|
||||
/**
|
||||
* The `uncompress`/`uncompress2` function is used in flow sink.
|
||||
*/
|
||||
class UncompressFunction extends DecompressionFunction {
|
||||
UncompressFunction() { this.hasGlobalName(["uncompress", "uncompress2"]) }
|
||||
|
||||
override int getArchiveParameterIndex() { result = 2 }
|
||||
}
|
||||
15
cpp/ql/src/experimental/Security/CWE/CWE-409/example_bad.cpp
Normal file
15
cpp/ql/src/experimental/Security/CWE/CWE-409/example_bad.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "zlib.h"
|
||||
|
||||
void UnsafeGzread(gzFile inFileZ) {
|
||||
const int BUFFER_SIZE = 8192;
|
||||
unsigned char unzipBuffer[BUFFER_SIZE];
|
||||
unsigned int unzippedBytes;
|
||||
while (true) {
|
||||
unzippedBytes = gzread(inFileZ, unzipBuffer, BUFFER_SIZE);
|
||||
if (unzippedBytes <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// process buffer
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "zlib.h"
|
||||
|
||||
void SafeGzread(gzFile inFileZ) {
|
||||
const int MAX_READ = 1024 * 1024 * 4;
|
||||
const int BUFFER_SIZE = 8192;
|
||||
unsigned char unzipBuffer[BUFFER_SIZE];
|
||||
unsigned int unzippedBytes;
|
||||
unsigned int totalRead = 0;
|
||||
while (true) {
|
||||
unzippedBytes = gzread(inFileZ, unzipBuffer, BUFFER_SIZE);
|
||||
totalRead += unzippedBytes;
|
||||
if (unzippedBytes <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (totalRead > MAX_READ) {
|
||||
// Possible decompression bomb, stop processing.
|
||||
break;
|
||||
} else {
|
||||
// process buffer
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
edges
|
||||
| brotliTest.cpp:15:41:15:44 | **argv | brotliTest.cpp:15:41:15:44 | **argv | provenance | |
|
||||
| brotliTest.cpp:15:41:15:44 | **argv | brotliTest.cpp:18:35:18:53 | *access to array | provenance | |
|
||||
| brotliTest.cpp:15:41:15:44 | **argv | brotliTest.cpp:21:30:21:52 | *access to array | provenance | |
|
||||
| brotliTest.cpp:21:30:21:52 | *access to array | brotliTest.cpp:24:51:24:58 | **& ... | provenance | |
|
||||
| libarchiveTests.cpp:16:31:16:32 | *ar | libarchiveTests.cpp:16:31:16:32 | *ar | provenance | |
|
||||
| libarchiveTests.cpp:16:31:16:32 | *ar | libarchiveTests.cpp:22:41:22:42 | *ar | provenance | |
|
||||
| libarchiveTests.cpp:30:45:30:48 | **argv | libarchiveTests.cpp:30:45:30:48 | **argv | provenance | |
|
||||
| libarchiveTests.cpp:30:45:30:48 | **argv | libarchiveTests.cpp:34:35:34:41 | *access to array | provenance | |
|
||||
| libarchiveTests.cpp:34:32:34:32 | *a | libarchiveTests.cpp:38:27:38:27 | *a | provenance | |
|
||||
| libarchiveTests.cpp:34:35:34:41 | *access to array | libarchiveTests.cpp:34:32:34:32 | *a | provenance | Config |
|
||||
| libarchiveTests.cpp:38:27:38:27 | *a | libarchiveTests.cpp:16:31:16:32 | *ar | provenance | |
|
||||
| libarchiveTests.cpp:38:27:38:27 | *a | libarchiveTests.cpp:38:27:38:27 | read_data output argument | provenance | |
|
||||
| libarchiveTests.cpp:38:27:38:27 | read_data output argument | libarchiveTests.cpp:38:27:38:27 | *a | provenance | |
|
||||
| main.cpp:7:33:7:36 | **argv | main.cpp:8:23:8:26 | **argv | provenance | |
|
||||
| main.cpp:7:33:7:36 | **argv | main.cpp:9:27:9:30 | **argv | provenance | |
|
||||
| main.cpp:7:33:7:36 | **argv | main.cpp:10:24:10:27 | **argv | provenance | |
|
||||
| main.cpp:7:33:7:36 | **argv | main.cpp:11:21:11:24 | **argv | provenance | |
|
||||
| main.cpp:7:33:7:36 | **argv | main.cpp:12:21:12:24 | **argv | provenance | |
|
||||
| main.cpp:8:23:8:26 | **argv | brotliTest.cpp:15:41:15:44 | **argv | provenance | |
|
||||
| main.cpp:8:23:8:26 | **argv | main.cpp:8:23:8:26 | brotli_test output argument | provenance | |
|
||||
| main.cpp:8:23:8:26 | brotli_test output argument | main.cpp:9:27:9:30 | **argv | provenance | |
|
||||
| main.cpp:8:23:8:26 | brotli_test output argument | main.cpp:10:24:10:27 | **argv | provenance | |
|
||||
| main.cpp:8:23:8:26 | brotli_test output argument | main.cpp:11:21:11:24 | **argv | provenance | |
|
||||
| main.cpp:8:23:8:26 | brotli_test output argument | main.cpp:12:21:12:24 | **argv | provenance | |
|
||||
| main.cpp:9:27:9:30 | **argv | libarchiveTests.cpp:30:45:30:48 | **argv | provenance | |
|
||||
| main.cpp:9:27:9:30 | **argv | main.cpp:9:27:9:30 | libarchive_test output argument | provenance | |
|
||||
| main.cpp:9:27:9:30 | libarchive_test output argument | main.cpp:10:24:10:27 | **argv | provenance | |
|
||||
| main.cpp:9:27:9:30 | libarchive_test output argument | main.cpp:11:21:11:24 | **argv | provenance | |
|
||||
| main.cpp:9:27:9:30 | libarchive_test output argument | main.cpp:12:21:12:24 | **argv | provenance | |
|
||||
| main.cpp:10:24:10:27 | **argv | main.cpp:10:24:10:27 | minizip_test output argument | provenance | |
|
||||
| main.cpp:10:24:10:27 | **argv | minizipTest.cpp:12:42:12:45 | **argv | provenance | |
|
||||
| main.cpp:10:24:10:27 | minizip_test output argument | main.cpp:11:21:11:24 | **argv | provenance | |
|
||||
| main.cpp:10:24:10:27 | minizip_test output argument | main.cpp:12:21:12:24 | **argv | provenance | |
|
||||
| main.cpp:11:21:11:24 | **argv | main.cpp:11:21:11:24 | zlib_test output argument | provenance | |
|
||||
| main.cpp:11:21:11:24 | **argv | main.cpp:11:21:11:24 | zlib_test output argument | provenance | |
|
||||
| main.cpp:11:21:11:24 | **argv | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
|
||||
| main.cpp:11:21:11:24 | zlib_test output argument | main.cpp:12:21:12:24 | **argv | provenance | |
|
||||
| main.cpp:11:21:11:24 | zlib_test output argument | main.cpp:12:21:12:24 | *argv | provenance | |
|
||||
| main.cpp:12:21:12:24 | **argv | zstdTest.cpp:26:39:26:42 | **argv | provenance | |
|
||||
| main.cpp:12:21:12:24 | *argv | zstdTest.cpp:26:39:26:42 | **argv | provenance | |
|
||||
| main.cpp:12:21:12:24 | *argv | zstdTest.cpp:26:39:26:42 | *argv | provenance | |
|
||||
| minizipTest.cpp:12:42:12:45 | **argv | minizipTest.cpp:12:42:12:45 | **argv | provenance | |
|
||||
| minizipTest.cpp:12:42:12:45 | **argv | minizipTest.cpp:17:52:17:67 | *access to array | provenance | |
|
||||
| minizipTest.cpp:12:42:12:45 | **argv | minizipTest.cpp:24:41:24:47 | *access to array | provenance | |
|
||||
| minizipTest.cpp:12:42:12:45 | **argv | minizipTest.cpp:28:13:28:19 | *access to array | provenance | |
|
||||
| minizipTest.cpp:24:29:24:38 | **zip_reader | minizipTest.cpp:26:30:26:39 | **zip_reader | provenance | |
|
||||
| minizipTest.cpp:24:29:24:38 | *zip_reader | minizipTest.cpp:26:30:26:39 | *zip_reader | provenance | |
|
||||
| minizipTest.cpp:24:41:24:47 | *access to array | minizipTest.cpp:24:29:24:38 | **zip_reader | provenance | Config |
|
||||
| minizipTest.cpp:24:41:24:47 | *access to array | minizipTest.cpp:24:29:24:38 | *zip_reader | provenance | Config |
|
||||
| zlibTest.cpp:16:26:16:30 | *input | zlibTest.cpp:20:25:20:39 | *input | provenance | |
|
||||
| zlibTest.cpp:20:25:20:39 | *input | zlibTest.cpp:16:26:16:30 | *input | provenance | |
|
||||
| zlibTest.cpp:20:25:20:39 | *input | zlibTest.cpp:24:17:24:26 | & ... | provenance | Config |
|
||||
| zlibTest.cpp:20:25:20:39 | *input | zlibTest.cpp:25:13:25:22 | & ... | provenance | Config |
|
||||
| zlibTest.cpp:24:17:24:26 | & ... | zlibTest.cpp:25:13:25:22 | & ... | provenance | |
|
||||
| zlibTest.cpp:37:25:37:32 | *fileName | zlibTest.cpp:38:29:38:36 | *fileName | provenance | |
|
||||
| zlibTest.cpp:38:22:38:27 | call to gzopen | zlibTest.cpp:38:22:38:27 | call to gzopen | provenance | |
|
||||
| zlibTest.cpp:38:22:38:27 | call to gzopen | zlibTest.cpp:41:20:41:26 | inFileZ | provenance | |
|
||||
| zlibTest.cpp:38:29:38:36 | *fileName | zlibTest.cpp:37:25:37:32 | *fileName | provenance | |
|
||||
| zlibTest.cpp:38:29:38:36 | *fileName | zlibTest.cpp:38:22:38:27 | call to gzopen | provenance | Config |
|
||||
| zlibTest.cpp:47:26:47:33 | *fileName | zlibTest.cpp:48:29:48:36 | *fileName | provenance | |
|
||||
| zlibTest.cpp:48:22:48:27 | call to gzopen | zlibTest.cpp:48:22:48:27 | call to gzopen | provenance | |
|
||||
| zlibTest.cpp:48:22:48:27 | call to gzopen | zlibTest.cpp:51:38:51:44 | inFileZ | provenance | |
|
||||
| zlibTest.cpp:48:29:48:36 | *fileName | zlibTest.cpp:47:26:47:33 | *fileName | provenance | |
|
||||
| zlibTest.cpp:48:29:48:36 | *fileName | zlibTest.cpp:48:22:48:27 | call to gzopen | provenance | Config |
|
||||
| zlibTest.cpp:57:25:57:32 | *fileName | zlibTest.cpp:58:29:58:36 | *fileName | provenance | |
|
||||
| zlibTest.cpp:58:22:58:27 | call to gzopen | zlibTest.cpp:58:22:58:27 | call to gzopen | provenance | |
|
||||
| zlibTest.cpp:58:22:58:27 | call to gzopen | zlibTest.cpp:62:25:62:31 | inFileZ | provenance | |
|
||||
| zlibTest.cpp:58:29:58:36 | *fileName | zlibTest.cpp:57:25:57:32 | *fileName | provenance | |
|
||||
| zlibTest.cpp:58:29:58:36 | *fileName | zlibTest.cpp:58:22:58:27 | call to gzopen | provenance | Config |
|
||||
| zlibTest.cpp:71:26:71:30 | *input | zlibTest.cpp:71:26:71:30 | *input | provenance | |
|
||||
| zlibTest.cpp:71:26:71:30 | *input | zlibTest.cpp:77:45:77:59 | *input | provenance | |
|
||||
| zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
|
||||
| zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:81:19:81:25 | *access to array | provenance | |
|
||||
| zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:82:18:82:24 | *access to array | provenance | |
|
||||
| zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:83:19:83:25 | *access to array | provenance | |
|
||||
| zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:84:18:84:24 | *access to array | provenance | |
|
||||
| zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:85:19:85:25 | *access to array | provenance | |
|
||||
| zlibTest.cpp:81:19:81:25 | *access to array | zlibTest.cpp:47:26:47:33 | *fileName | provenance | |
|
||||
| zlibTest.cpp:81:19:81:25 | *access to array | zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | provenance | |
|
||||
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
|
||||
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | zlibTest.cpp:80:33:80:36 | **argv [Return] | provenance | |
|
||||
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | zlibTest.cpp:82:18:82:24 | *access to array | provenance | |
|
||||
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | zlibTest.cpp:83:19:83:25 | *access to array | provenance | |
|
||||
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | zlibTest.cpp:84:18:84:24 | *access to array | provenance | |
|
||||
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | zlibTest.cpp:85:19:85:25 | *access to array | provenance | |
|
||||
| zlibTest.cpp:82:18:82:24 | *access to array | zlibTest.cpp:57:25:57:32 | *fileName | provenance | |
|
||||
| zlibTest.cpp:82:18:82:24 | *access to array | zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | provenance | |
|
||||
| zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
|
||||
| zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | zlibTest.cpp:80:33:80:36 | **argv [Return] | provenance | |
|
||||
| zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | zlibTest.cpp:83:19:83:25 | *access to array | provenance | |
|
||||
| zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | zlibTest.cpp:84:18:84:24 | *access to array | provenance | |
|
||||
| zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | zlibTest.cpp:85:19:85:25 | *access to array | provenance | |
|
||||
| zlibTest.cpp:83:19:83:25 | *access to array | zlibTest.cpp:16:26:16:30 | *input | provenance | |
|
||||
| zlibTest.cpp:83:19:83:25 | *access to array | zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument | provenance | |
|
||||
| zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
|
||||
| zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument | zlibTest.cpp:80:33:80:36 | **argv [Return] | provenance | |
|
||||
| zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument | zlibTest.cpp:84:18:84:24 | *access to array | provenance | |
|
||||
| zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument | zlibTest.cpp:85:19:85:25 | *access to array | provenance | |
|
||||
| zlibTest.cpp:84:18:84:24 | *access to array | zlibTest.cpp:37:25:37:32 | *fileName | provenance | |
|
||||
| zlibTest.cpp:84:18:84:24 | *access to array | zlibTest.cpp:84:18:84:24 | UnsafeGzread output argument | provenance | |
|
||||
| zlibTest.cpp:84:18:84:24 | UnsafeGzread output argument | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
|
||||
| zlibTest.cpp:84:18:84:24 | UnsafeGzread output argument | zlibTest.cpp:80:33:80:36 | **argv [Return] | provenance | |
|
||||
| zlibTest.cpp:84:18:84:24 | UnsafeGzread output argument | zlibTest.cpp:85:19:85:25 | *access to array | provenance | |
|
||||
| zlibTest.cpp:85:19:85:25 | *access to array | zlibTest.cpp:71:26:71:30 | *input | provenance | |
|
||||
| zlibTest.cpp:85:19:85:25 | *access to array | zlibTest.cpp:85:19:85:25 | InflateString output argument | provenance | |
|
||||
| zlibTest.cpp:85:19:85:25 | InflateString output argument | zlibTest.cpp:80:33:80:36 | **argv | provenance | |
|
||||
| zlibTest.cpp:85:19:85:25 | InflateString output argument | zlibTest.cpp:80:33:80:36 | **argv [Return] | provenance | |
|
||||
| zstdTest.cpp:26:39:26:42 | **argv | zstdTest.cpp:27:35:27:41 | *access to array | provenance | |
|
||||
| zstdTest.cpp:26:39:26:42 | *argv | zstdTest.cpp:27:35:27:41 | *access to array | provenance | |
|
||||
| zstdTest.cpp:27:23:27:33 | call to fopen_orDie | zstdTest.cpp:27:23:27:33 | call to fopen_orDie | provenance | |
|
||||
| zstdTest.cpp:27:23:27:33 | call to fopen_orDie | zstdTest.cpp:35:52:35:54 | fin | provenance | |
|
||||
| zstdTest.cpp:27:35:27:41 | *access to array | zstdTest.cpp:27:23:27:33 | call to fopen_orDie | provenance | Config |
|
||||
| zstdTest.cpp:35:32:35:37 | **buffIn | zstdTest.cpp:36:32:36:37 | **buffIn | provenance | |
|
||||
| zstdTest.cpp:35:32:35:37 | *buffIn | zstdTest.cpp:36:32:36:37 | *buffIn | provenance | |
|
||||
| zstdTest.cpp:35:52:35:54 | fin | zstdTest.cpp:35:32:35:37 | **buffIn | provenance | Config |
|
||||
| zstdTest.cpp:35:52:35:54 | fin | zstdTest.cpp:35:32:35:37 | *buffIn | provenance | Config |
|
||||
| zstdTest.cpp:36:32:36:37 | **buffIn | zstdTest.cpp:35:32:35:37 | **buffIn | provenance | |
|
||||
| zstdTest.cpp:36:32:36:37 | **buffIn | zstdTest.cpp:39:69:39:74 | & ... | provenance | Config |
|
||||
| zstdTest.cpp:36:32:36:37 | **buffIn | zstdTest.cpp:39:69:39:74 | & ... | provenance | Config |
|
||||
| zstdTest.cpp:36:32:36:37 | *buffIn | zstdTest.cpp:35:32:35:37 | *buffIn | provenance | |
|
||||
| zstdTest.cpp:36:32:36:37 | *buffIn | zstdTest.cpp:39:69:39:74 | & ... | provenance | Config |
|
||||
| zstdTest.cpp:36:32:36:37 | *buffIn | zstdTest.cpp:39:69:39:74 | & ... | provenance | Config |
|
||||
| zstdTest.cpp:39:69:39:74 | & ... | zstdTest.cpp:39:69:39:74 | & ... | provenance | |
|
||||
| zstdTest.cpp:39:69:39:74 | & ... | zstdTest.cpp:39:69:39:74 | & ... | provenance | |
|
||||
nodes
|
||||
| brotliTest.cpp:15:41:15:44 | **argv | semmle.label | **argv |
|
||||
| brotliTest.cpp:15:41:15:44 | **argv | semmle.label | **argv |
|
||||
| brotliTest.cpp:18:35:18:53 | *access to array | semmle.label | *access to array |
|
||||
| brotliTest.cpp:21:30:21:52 | *access to array | semmle.label | *access to array |
|
||||
| brotliTest.cpp:24:51:24:58 | **& ... | semmle.label | **& ... |
|
||||
| libarchiveTests.cpp:16:31:16:32 | *ar | semmle.label | *ar |
|
||||
| libarchiveTests.cpp:16:31:16:32 | *ar | semmle.label | *ar |
|
||||
| libarchiveTests.cpp:22:41:22:42 | *ar | semmle.label | *ar |
|
||||
| libarchiveTests.cpp:30:45:30:48 | **argv | semmle.label | **argv |
|
||||
| libarchiveTests.cpp:30:45:30:48 | **argv | semmle.label | **argv |
|
||||
| libarchiveTests.cpp:34:32:34:32 | *a | semmle.label | *a |
|
||||
| libarchiveTests.cpp:34:35:34:41 | *access to array | semmle.label | *access to array |
|
||||
| libarchiveTests.cpp:38:27:38:27 | *a | semmle.label | *a |
|
||||
| libarchiveTests.cpp:38:27:38:27 | read_data output argument | semmle.label | read_data output argument |
|
||||
| main.cpp:7:33:7:36 | **argv | semmle.label | **argv |
|
||||
| main.cpp:8:23:8:26 | **argv | semmle.label | **argv |
|
||||
| main.cpp:8:23:8:26 | brotli_test output argument | semmle.label | brotli_test output argument |
|
||||
| main.cpp:9:27:9:30 | **argv | semmle.label | **argv |
|
||||
| main.cpp:9:27:9:30 | libarchive_test output argument | semmle.label | libarchive_test output argument |
|
||||
| main.cpp:10:24:10:27 | **argv | semmle.label | **argv |
|
||||
| main.cpp:10:24:10:27 | minizip_test output argument | semmle.label | minizip_test output argument |
|
||||
| main.cpp:11:21:11:24 | **argv | semmle.label | **argv |
|
||||
| main.cpp:11:21:11:24 | zlib_test output argument | semmle.label | zlib_test output argument |
|
||||
| main.cpp:11:21:11:24 | zlib_test output argument | semmle.label | zlib_test output argument |
|
||||
| main.cpp:12:21:12:24 | **argv | semmle.label | **argv |
|
||||
| main.cpp:12:21:12:24 | *argv | semmle.label | *argv |
|
||||
| minizipTest.cpp:12:42:12:45 | **argv | semmle.label | **argv |
|
||||
| minizipTest.cpp:12:42:12:45 | **argv | semmle.label | **argv |
|
||||
| minizipTest.cpp:17:52:17:67 | *access to array | semmle.label | *access to array |
|
||||
| minizipTest.cpp:24:29:24:38 | **zip_reader | semmle.label | **zip_reader |
|
||||
| minizipTest.cpp:24:29:24:38 | *zip_reader | semmle.label | *zip_reader |
|
||||
| minizipTest.cpp:24:41:24:47 | *access to array | semmle.label | *access to array |
|
||||
| minizipTest.cpp:26:30:26:39 | **zip_reader | semmle.label | **zip_reader |
|
||||
| minizipTest.cpp:26:30:26:39 | *zip_reader | semmle.label | *zip_reader |
|
||||
| minizipTest.cpp:28:13:28:19 | *access to array | semmle.label | *access to array |
|
||||
| zlibTest.cpp:16:26:16:30 | *input | semmle.label | *input |
|
||||
| zlibTest.cpp:16:26:16:30 | *input | semmle.label | *input |
|
||||
| zlibTest.cpp:20:25:20:39 | *input | semmle.label | *input |
|
||||
| zlibTest.cpp:24:17:24:26 | & ... | semmle.label | & ... |
|
||||
| zlibTest.cpp:25:13:25:22 | & ... | semmle.label | & ... |
|
||||
| zlibTest.cpp:37:25:37:32 | *fileName | semmle.label | *fileName |
|
||||
| zlibTest.cpp:37:25:37:32 | *fileName | semmle.label | *fileName |
|
||||
| zlibTest.cpp:38:22:38:27 | call to gzopen | semmle.label | call to gzopen |
|
||||
| zlibTest.cpp:38:22:38:27 | call to gzopen | semmle.label | call to gzopen |
|
||||
| zlibTest.cpp:38:29:38:36 | *fileName | semmle.label | *fileName |
|
||||
| zlibTest.cpp:41:20:41:26 | inFileZ | semmle.label | inFileZ |
|
||||
| zlibTest.cpp:47:26:47:33 | *fileName | semmle.label | *fileName |
|
||||
| zlibTest.cpp:47:26:47:33 | *fileName | semmle.label | *fileName |
|
||||
| zlibTest.cpp:48:22:48:27 | call to gzopen | semmle.label | call to gzopen |
|
||||
| zlibTest.cpp:48:22:48:27 | call to gzopen | semmle.label | call to gzopen |
|
||||
| zlibTest.cpp:48:29:48:36 | *fileName | semmle.label | *fileName |
|
||||
| zlibTest.cpp:51:38:51:44 | inFileZ | semmle.label | inFileZ |
|
||||
| zlibTest.cpp:57:25:57:32 | *fileName | semmle.label | *fileName |
|
||||
| zlibTest.cpp:57:25:57:32 | *fileName | semmle.label | *fileName |
|
||||
| zlibTest.cpp:58:22:58:27 | call to gzopen | semmle.label | call to gzopen |
|
||||
| zlibTest.cpp:58:22:58:27 | call to gzopen | semmle.label | call to gzopen |
|
||||
| zlibTest.cpp:58:29:58:36 | *fileName | semmle.label | *fileName |
|
||||
| zlibTest.cpp:62:25:62:31 | inFileZ | semmle.label | inFileZ |
|
||||
| zlibTest.cpp:71:26:71:30 | *input | semmle.label | *input |
|
||||
| zlibTest.cpp:71:26:71:30 | *input | semmle.label | *input |
|
||||
| zlibTest.cpp:77:45:77:59 | *input | semmle.label | *input |
|
||||
| zlibTest.cpp:80:33:80:36 | **argv | semmle.label | **argv |
|
||||
| zlibTest.cpp:80:33:80:36 | **argv | semmle.label | **argv |
|
||||
| zlibTest.cpp:80:33:80:36 | **argv [Return] | semmle.label | **argv [Return] |
|
||||
| zlibTest.cpp:81:19:81:25 | *access to array | semmle.label | *access to array |
|
||||
| zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument | semmle.label | UnsafeGzfread output argument |
|
||||
| zlibTest.cpp:82:18:82:24 | *access to array | semmle.label | *access to array |
|
||||
| zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument | semmle.label | UnsafeGzgets output argument |
|
||||
| zlibTest.cpp:83:19:83:25 | *access to array | semmle.label | *access to array |
|
||||
| zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument | semmle.label | UnsafeInflate output argument |
|
||||
| zlibTest.cpp:84:18:84:24 | *access to array | semmle.label | *access to array |
|
||||
| zlibTest.cpp:84:18:84:24 | UnsafeGzread output argument | semmle.label | UnsafeGzread output argument |
|
||||
| zlibTest.cpp:85:19:85:25 | *access to array | semmle.label | *access to array |
|
||||
| zlibTest.cpp:85:19:85:25 | InflateString output argument | semmle.label | InflateString output argument |
|
||||
| zstdTest.cpp:26:39:26:42 | **argv | semmle.label | **argv |
|
||||
| zstdTest.cpp:26:39:26:42 | *argv | semmle.label | *argv |
|
||||
| zstdTest.cpp:27:23:27:33 | call to fopen_orDie | semmle.label | call to fopen_orDie |
|
||||
| zstdTest.cpp:27:23:27:33 | call to fopen_orDie | semmle.label | call to fopen_orDie |
|
||||
| zstdTest.cpp:27:35:27:41 | *access to array | semmle.label | *access to array |
|
||||
| zstdTest.cpp:35:32:35:37 | **buffIn | semmle.label | **buffIn |
|
||||
| zstdTest.cpp:35:32:35:37 | *buffIn | semmle.label | *buffIn |
|
||||
| zstdTest.cpp:35:52:35:54 | fin | semmle.label | fin |
|
||||
| zstdTest.cpp:36:32:36:37 | **buffIn | semmle.label | **buffIn |
|
||||
| zstdTest.cpp:36:32:36:37 | *buffIn | semmle.label | *buffIn |
|
||||
| zstdTest.cpp:39:69:39:74 | & ... | semmle.label | & ... |
|
||||
| zstdTest.cpp:39:69:39:74 | & ... | semmle.label | & ... |
|
||||
subpaths
|
||||
| libarchiveTests.cpp:38:27:38:27 | *a | libarchiveTests.cpp:16:31:16:32 | *ar | libarchiveTests.cpp:16:31:16:32 | *ar | libarchiveTests.cpp:38:27:38:27 | read_data output argument |
|
||||
| main.cpp:8:23:8:26 | **argv | brotliTest.cpp:15:41:15:44 | **argv | brotliTest.cpp:15:41:15:44 | **argv | main.cpp:8:23:8:26 | brotli_test output argument |
|
||||
| main.cpp:9:27:9:30 | **argv | libarchiveTests.cpp:30:45:30:48 | **argv | libarchiveTests.cpp:30:45:30:48 | **argv | main.cpp:9:27:9:30 | libarchive_test output argument |
|
||||
| main.cpp:10:24:10:27 | **argv | minizipTest.cpp:12:42:12:45 | **argv | minizipTest.cpp:12:42:12:45 | **argv | main.cpp:10:24:10:27 | minizip_test output argument |
|
||||
| main.cpp:11:21:11:24 | **argv | zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:80:33:80:36 | **argv | main.cpp:11:21:11:24 | zlib_test output argument |
|
||||
| main.cpp:11:21:11:24 | **argv | zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:80:33:80:36 | **argv [Return] | main.cpp:11:21:11:24 | zlib_test output argument |
|
||||
| main.cpp:11:21:11:24 | **argv | zlibTest.cpp:80:33:80:36 | **argv | zlibTest.cpp:80:33:80:36 | **argv [Return] | main.cpp:11:21:11:24 | zlib_test output argument |
|
||||
| zlibTest.cpp:81:19:81:25 | *access to array | zlibTest.cpp:47:26:47:33 | *fileName | zlibTest.cpp:47:26:47:33 | *fileName | zlibTest.cpp:81:19:81:25 | UnsafeGzfread output argument |
|
||||
| zlibTest.cpp:82:18:82:24 | *access to array | zlibTest.cpp:57:25:57:32 | *fileName | zlibTest.cpp:57:25:57:32 | *fileName | zlibTest.cpp:82:18:82:24 | UnsafeGzgets output argument |
|
||||
| zlibTest.cpp:83:19:83:25 | *access to array | zlibTest.cpp:16:26:16:30 | *input | zlibTest.cpp:16:26:16:30 | *input | zlibTest.cpp:83:19:83:25 | UnsafeInflate output argument |
|
||||
| zlibTest.cpp:84:18:84:24 | *access to array | zlibTest.cpp:37:25:37:32 | *fileName | zlibTest.cpp:37:25:37:32 | *fileName | zlibTest.cpp:84:18:84:24 | UnsafeGzread output argument |
|
||||
| zlibTest.cpp:85:19:85:25 | *access to array | zlibTest.cpp:71:26:71:30 | *input | zlibTest.cpp:71:26:71:30 | *input | zlibTest.cpp:85:19:85:25 | InflateString output argument |
|
||||
#select
|
||||
| brotliTest.cpp:18:35:18:53 | *access to array | main.cpp:7:33:7:36 | **argv | brotliTest.cpp:18:35:18:53 | *access to array | The decompression output of $@ is not limited | brotliTest.cpp:18:5:18:27 | call to BrotliDecoderDecompress | BrotliDecoderDecompress |
|
||||
| brotliTest.cpp:24:51:24:58 | **& ... | main.cpp:7:33:7:36 | **argv | brotliTest.cpp:24:51:24:58 | **& ... | The decompression output of $@ is not limited | brotliTest.cpp:24:5:24:33 | call to BrotliDecoderDecompressStream | BrotliDecoderDecompressStream |
|
||||
| libarchiveTests.cpp:22:41:22:42 | *ar | main.cpp:7:33:7:36 | **argv | libarchiveTests.cpp:22:41:22:42 | *ar | The decompression output of $@ is not limited | libarchiveTests.cpp:22:17:22:39 | call to archive_read_data_block | archive_read_data_block |
|
||||
| minizipTest.cpp:17:52:17:67 | *access to array | main.cpp:7:33:7:36 | **argv | minizipTest.cpp:17:52:17:67 | *access to array | The decompression output of $@ is not limited | minizipTest.cpp:17:22:17:38 | call to mz_zip_entry_read | mz_zip_entry_read |
|
||||
| minizipTest.cpp:26:30:26:39 | **zip_reader | main.cpp:7:33:7:36 | **argv | minizipTest.cpp:26:30:26:39 | **zip_reader | The decompression output of $@ is not limited | minizipTest.cpp:26:5:26:28 | call to mz_zip_reader_entry_save | mz_zip_reader_entry_save |
|
||||
| minizipTest.cpp:26:30:26:39 | *zip_reader | main.cpp:7:33:7:36 | **argv | minizipTest.cpp:26:30:26:39 | *zip_reader | The decompression output of $@ is not limited | minizipTest.cpp:26:5:26:28 | call to mz_zip_reader_entry_save | mz_zip_reader_entry_save |
|
||||
| minizipTest.cpp:28:13:28:19 | *access to array | main.cpp:7:33:7:36 | **argv | minizipTest.cpp:28:13:28:19 | *access to array | The decompression output of $@ is not limited | minizipTest.cpp:28:5:28:11 | call to UnzOpen | UnzOpen |
|
||||
| zlibTest.cpp:25:13:25:22 | & ... | main.cpp:7:33:7:36 | **argv | zlibTest.cpp:25:13:25:22 | & ... | The decompression output of $@ is not limited | zlibTest.cpp:25:5:25:11 | call to inflate | inflate |
|
||||
| zlibTest.cpp:41:20:41:26 | inFileZ | main.cpp:7:33:7:36 | **argv | zlibTest.cpp:41:20:41:26 | inFileZ | The decompression output of $@ is not limited | zlibTest.cpp:41:13:41:18 | call to gzread | gzread |
|
||||
| zlibTest.cpp:51:38:51:44 | inFileZ | main.cpp:7:33:7:36 | **argv | zlibTest.cpp:51:38:51:44 | inFileZ | The decompression output of $@ is not limited | zlibTest.cpp:51:14:51:20 | call to gzfread | gzfread |
|
||||
| zlibTest.cpp:62:25:62:31 | inFileZ | main.cpp:7:33:7:36 | **argv | zlibTest.cpp:62:25:62:31 | inFileZ | The decompression output of $@ is not limited | zlibTest.cpp:62:18:62:23 | call to gzgets | gzgets |
|
||||
| zlibTest.cpp:77:45:77:59 | *input | main.cpp:7:33:7:36 | **argv | zlibTest.cpp:77:45:77:59 | *input | The decompression output of $@ is not limited | zlibTest.cpp:77:5:77:14 | call to uncompress | uncompress |
|
||||
| zstdTest.cpp:39:69:39:74 | & ... | main.cpp:7:33:7:36 | **argv | zstdTest.cpp:39:69:39:74 | & ... | The decompression output of $@ is not limited | zstdTest.cpp:39:32:39:52 | call to ZSTD_decompressStream | ZSTD_decompressStream |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-409/DecompressionBombs.ql
|
||||
@@ -0,0 +1,26 @@
|
||||
typedef long unsigned int size_t;
|
||||
typedef unsigned char uint8_t;
|
||||
|
||||
enum BrotliDecoderResult {};
|
||||
struct BrotliDecoderState;
|
||||
|
||||
BrotliDecoderResult BrotliDecoderDecompress(
|
||||
size_t encoded_size, const uint8_t encoded_buffer[],
|
||||
size_t *decoded_size, uint8_t decoded_buffer[]);
|
||||
|
||||
BrotliDecoderResult BrotliDecoderDecompressStream(
|
||||
BrotliDecoderState *state, size_t *available_in, const uint8_t **next_in,
|
||||
size_t *available_out, uint8_t **next_out, size_t *total_out);
|
||||
|
||||
void brotli_test(int argc, const char **argv) {
|
||||
uint8_t output[1024];
|
||||
size_t output_size = sizeof(output);
|
||||
BrotliDecoderDecompress(1024, (uint8_t *) argv[2], &output_size, output); // BAD
|
||||
|
||||
size_t input_size = 1024;
|
||||
const uint8_t *input_p = (const uint8_t*)argv[2];
|
||||
uint8_t *output_p = output;
|
||||
size_t out_size;
|
||||
BrotliDecoderDecompressStream(0, &input_size, &input_p, &output_size, // BAD
|
||||
&output_p, &out_size);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#define ARCHIVE_EOF 1
|
||||
#define ARCHIVE_OK 0
|
||||
#define ARCHIVE_WARN (-20)
|
||||
|
||||
struct archive;
|
||||
struct archive_entry;
|
||||
typedef int size_t;
|
||||
typedef int la_int64_t;
|
||||
|
||||
archive *archive_read_new();
|
||||
int archive_read_open_filename(archive *pArchive, const char *filename, int i);
|
||||
int archive_read_next_header(archive *a, archive_entry **entry);
|
||||
int archive_entry_size(archive_entry *pEntry);
|
||||
int archive_read_data_block(archive *pArchive, const void **pVoid, size_t *pInt, la_int64_t *pInt1);
|
||||
|
||||
static int read_data(archive *ar) {
|
||||
for (;;) {
|
||||
const void *buff;
|
||||
size_t size;
|
||||
la_int64_t offset;
|
||||
|
||||
int r = archive_read_data_block(ar, &buff, &size, &offset); // BAD
|
||||
if (r == ARCHIVE_EOF)
|
||||
return ARCHIVE_OK;
|
||||
if (r < ARCHIVE_OK)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
void libarchive_test(int argc, const char **argv) {
|
||||
archive *a = archive_read_new();
|
||||
archive_entry *entry;
|
||||
|
||||
archive_read_open_filename(a, argv[1], 10240);
|
||||
for (;;) {
|
||||
archive_read_next_header(a, &entry);
|
||||
if (archive_entry_size(entry) > 0) {
|
||||
if (read_data(a) < ARCHIVE_WARN)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
void brotli_test(int argc, const char **argv);
|
||||
void libarchive_test(int argc, const char **argv);
|
||||
void minizip_test(int argc, const char **argv);
|
||||
void zlib_test(int argc, const char **argv);
|
||||
void zstd_test(int argc, const char **argv);
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
brotli_test(argc, argv);
|
||||
libarchive_test(argc, argv);
|
||||
minizip_test(argc, argv);
|
||||
zlib_test(argc, argv);
|
||||
zstd_test(argc, argv);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
typedef signed int int32_t;
|
||||
|
||||
void *mz_zip_reader_create();
|
||||
int32_t mz_zip_reader_open_file(void *handle, const char *path);
|
||||
int32_t mz_zip_reader_goto_first_entry(void *pVoid);
|
||||
int32_t mz_zip_reader_entry_save(void *pVoid, int stream, int write);
|
||||
int32_t mz_zip_entry_read(void *pVoid, void *buf, int32_t i);
|
||||
void UnzOpen(const char *string);
|
||||
|
||||
void *mz_zip_create();
|
||||
|
||||
void minizip_test(int argc, const char **argv) {
|
||||
void *zip_handle = mz_zip_create();
|
||||
int32_t bytes_read;
|
||||
char buf[4096];
|
||||
while(true) {
|
||||
bytes_read = mz_zip_entry_read(zip_handle, (char *) argv[1], sizeof(buf)); // BAD
|
||||
if (bytes_read <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void *zip_reader = mz_zip_reader_create();
|
||||
mz_zip_reader_open_file(zip_reader, argv[1]);
|
||||
mz_zip_reader_goto_first_entry(zip_reader);
|
||||
mz_zip_reader_entry_save(zip_reader, 0, 0); // BAD
|
||||
|
||||
UnzOpen(argv[3]); // BAD
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
typedef unsigned char Bytef;
|
||||
typedef unsigned long uLong;
|
||||
typedef uLong uLongf;
|
||||
typedef unsigned int uInt;
|
||||
|
||||
struct z_stream {
|
||||
Bytef *next_in;
|
||||
Bytef *next_out;
|
||||
uInt avail_out;
|
||||
};
|
||||
|
||||
void inflateInit(z_stream *infstream);
|
||||
void inflate(z_stream *infstream, int i);
|
||||
void inflateEnd(z_stream *infstream);
|
||||
|
||||
void UnsafeInflate(char *input) {
|
||||
unsigned char output[1024];
|
||||
|
||||
z_stream infstream;
|
||||
infstream.next_in = (Bytef *) input; // input char array
|
||||
infstream.avail_out = sizeof(output); // size of output
|
||||
infstream.next_out = output; // output char array
|
||||
|
||||
inflateInit(&infstream);
|
||||
inflate(&infstream, 0); // BAD
|
||||
}
|
||||
|
||||
|
||||
struct gzFile {
|
||||
};
|
||||
|
||||
gzFile gzopen(char *str, const char *rb);
|
||||
unsigned int gzread(gzFile gz_file, unsigned char *str, int i);
|
||||
bool gzfread(char *str, int i, int i1, gzFile gz_file);
|
||||
char *gzgets(gzFile gz_file, char *buffer, int i);
|
||||
|
||||
void UnsafeGzread(char *fileName) {
|
||||
gzFile inFileZ = gzopen(fileName, "rb");
|
||||
unsigned char unzipBuffer[8192];
|
||||
while (true) {
|
||||
if (gzread(inFileZ, unzipBuffer, 8192) <= 0) { // BAD
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnsafeGzfread(char *fileName) {
|
||||
gzFile inFileZ = gzopen(fileName, "rb");
|
||||
while (true) {
|
||||
char buffer[1000];
|
||||
if (!gzfread(buffer, 999, 1, inFileZ)) { // BAD
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnsafeGzgets(char *fileName) {
|
||||
gzFile inFileZ = gzopen(fileName, "rb");
|
||||
char *buffer = new char[4000000000];
|
||||
char *result;
|
||||
while (true) {
|
||||
result = gzgets(inFileZ, buffer, 1000000000); // BAD
|
||||
if (result == nullptr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
|
||||
|
||||
void InflateString(char *input) {
|
||||
unsigned char output[1024];
|
||||
|
||||
uLong source_length = 500;
|
||||
uLong destination_length = sizeof(output);
|
||||
|
||||
uncompress(output, &destination_length, (Bytef *) input, source_length); // BAD
|
||||
}
|
||||
|
||||
void zlib_test(int argc, char **argv) {
|
||||
UnsafeGzfread(argv[2]);
|
||||
UnsafeGzgets(argv[2]);
|
||||
UnsafeInflate(argv[2]);
|
||||
UnsafeGzread(argv[2]);
|
||||
InflateString(argv[2]);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
typedef long unsigned int size_t;
|
||||
struct FILE;
|
||||
|
||||
FILE *fopen_orDie(const char *filename, const char *instruction);
|
||||
size_t fread_orDie(void *const pVoid, const size_t read, FILE *const pFile);
|
||||
void *const malloc_orDie(const size_t size);
|
||||
|
||||
struct ZSTD_DCtx;
|
||||
typedef struct ZSTD_inBuffer_s {
|
||||
const void *src;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} ZSTD_inBuffer;
|
||||
typedef struct ZSTD_outBuffer_s {
|
||||
void *dst;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} ZSTD_outBuffer;
|
||||
|
||||
const size_t ZSTD_DStreamInSize();
|
||||
const size_t ZSTD_DStreamOutSize();
|
||||
ZSTD_DCtx *const ZSTD_createDCtx();
|
||||
const size_t ZSTD_decompressStream(ZSTD_DCtx *const pCtx, ZSTD_outBuffer *pS, ZSTD_inBuffer *pS1);
|
||||
void CHECK_ZSTD(const size_t ret);
|
||||
|
||||
void zstd_test(int argc, const char **argv) {
|
||||
FILE *const fin = fopen_orDie(argv[1], "rb");
|
||||
size_t const buffInSize = ZSTD_DStreamInSize();
|
||||
void *const buffIn = malloc_orDie(buffInSize);
|
||||
size_t const buffOutSize = ZSTD_DStreamOutSize();
|
||||
void *const buffOut = malloc_orDie(buffOutSize);
|
||||
|
||||
ZSTD_DCtx *const dctx = ZSTD_createDCtx();
|
||||
size_t read;
|
||||
while ((read = fread_orDie(buffIn, buffInSize, fin))) {
|
||||
ZSTD_inBuffer input = {buffIn, read, 0};
|
||||
while (input.pos < input.size) {
|
||||
ZSTD_outBuffer output = {buffOut, buffOutSize, 0};
|
||||
size_t const ret = ZSTD_decompressStream(dctx, &output, &input); // BAD
|
||||
CHECK_ZSTD(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,5 @@
|
||||
| main1.cpp:7:1:7:26 | #include "defines_issue.h" | Include | defines_issue.h | 1 |
|
||||
| main2.cpp:3:1:3:19 | #include "common.h" | Include | common.h | 1 |
|
||||
| main2.cpp:7:1:7:26 | #include "defines_issue.h" | Include | defines_issue.h | 1 |
|
||||
| nameclash.h:3:1:3:27 | #include_next "nameclash.h" | IncludeNext | nameclash.h | 1 |
|
||||
| nameclash.h:3:1:3:27 | #include_next "nameclash.h" | IncludeNext | subdir1/nameclash.h | 1 |
|
||||
| nameclash.h:3:1:3:27 | #include_next "nameclash.h" | IncludeNext | subdir2/nameclash.h | 1 |
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
| a/test.h:2:1:2:22 | #include_next <test.h> | a/test.h:0:0:0:0 | a/test.h |
|
||||
| a/test.h:2:1:2:22 | #include_next <test.h> | b/test.h:0:0:0:0 | b/test.h |
|
||||
| b/loop.h:2:1:2:22 | #include_next <test.h> | a/test.h:0:0:0:0 | a/test.h |
|
||||
| b/test.h:4:1:4:17 | #include "loop.h" | b/loop.h:0:0:0:0 | b/loop.h |
|
||||
|
||||
@@ -4474,6 +4474,33 @@ ir.c:
|
||||
# 29| Type = [IntType] int
|
||||
# 29| Value = [Literal] 0
|
||||
# 29| ValueCategory = prvalue
|
||||
# 32| [TopLevelFunction] void unexplained_loop_regression()
|
||||
# 32| <params>:
|
||||
# 33| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 34| getStmt(0): [MicrosoftTryExceptStmt] __try { ... } __except( ... ) { ... }
|
||||
# 35| getStmt(): [BlockStmt] { ... }
|
||||
# 36| getStmt(0): [ExprStmt] ExprStmt
|
||||
# 36| getExpr(): [FunctionCall] call to ExRaiseAccessViolation
|
||||
# 36| Type = [VoidType] void
|
||||
# 36| ValueCategory = prvalue
|
||||
# 36| getArgument(0): [Literal] 0
|
||||
# 36| Type = [IntType] int
|
||||
# 36| Value = [Literal] 0
|
||||
# 36| ValueCategory = prvalue
|
||||
# 38| getCondition(): [Literal] 1
|
||||
# 38| Type = [IntType] int
|
||||
# 38| Value = [Literal] 1
|
||||
# 38| ValueCategory = prvalue
|
||||
# 39| getExcept(): [BlockStmt] { ... }
|
||||
# 40| getStmt(0): [ExprStmt] ExprStmt
|
||||
# 40| getExpr(): [FunctionCall] call to ExRaiseAccessViolation
|
||||
# 40| Type = [VoidType] void
|
||||
# 40| ValueCategory = prvalue
|
||||
# 40| getArgument(0): [Literal] 1
|
||||
# 40| Type = [IntType] int
|
||||
# 40| Value = [Literal] 1
|
||||
# 40| ValueCategory = prvalue
|
||||
# 42| getStmt(1): [ReturnStmt] return ...
|
||||
ir.cpp:
|
||||
# 1| [TopLevelFunction] void Constants()
|
||||
# 1| <params>:
|
||||
|
||||
@@ -3156,6 +3156,53 @@ ir.c:
|
||||
# 21| Block 5
|
||||
# 21| v21_11(void) = Unreached :
|
||||
|
||||
# 32| void unexplained_loop_regression()
|
||||
# 32| Block 0
|
||||
# 32| v32_1(void) = EnterFunction :
|
||||
# 32| m32_2(unknown) = AliasedDefinition :
|
||||
# 32| m32_3(unknown) = InitializeNonLocal :
|
||||
# 32| m32_4(unknown) = Chi : total:m32_2, partial:m32_3
|
||||
# 36| r36_1(glval<unknown>) = FunctionAddress[ExRaiseAccessViolation] :
|
||||
# 36| r36_2(int) = Constant[0] :
|
||||
# 36| v36_3(void) = Call[ExRaiseAccessViolation] : func:r36_1, 0:r36_2
|
||||
# 36| m36_4(unknown) = ^CallSideEffect : ~m32_4
|
||||
# 36| m36_5(unknown) = Chi : total:m32_4, partial:m36_4
|
||||
#-----| Exception -> Block 3
|
||||
|
||||
# 39| Block 1
|
||||
# 39| r39_1(int) = Constant[0] :
|
||||
# 39| r39_2(bool) = CompareEQ : r38_2, r39_1
|
||||
# 39| v39_3(void) = ConditionalBranch : r39_2
|
||||
#-----| False (back edge) -> Block 2
|
||||
#-----| True -> Block 5
|
||||
|
||||
# 39| Block 2
|
||||
# 39| r39_4(int) = Constant[1] :
|
||||
# 39| r39_5(bool) = CompareEQ : r38_2, r39_4
|
||||
# 39| v39_6(void) = ConditionalBranch : r39_5
|
||||
#-----| False -> Block 5
|
||||
#-----| True (back edge) -> Block 4
|
||||
|
||||
# 38| Block 3
|
||||
# 38| m38_1(unknown) = Phi : from 0:~m36_5, from 4:~m40_5
|
||||
# 38| r38_2(int) = Constant[1] :
|
||||
# 39| r39_7(int) = Constant[-1] :
|
||||
# 39| r39_8(bool) = CompareEQ : r38_2, r39_7
|
||||
# 39| v39_9(void) = ConditionalBranch : r39_8
|
||||
#-----| False (back edge) -> Block 1
|
||||
#-----| True -> Block 5
|
||||
|
||||
# 40| Block 4
|
||||
# 40| r40_1(glval<unknown>) = FunctionAddress[ExRaiseAccessViolation] :
|
||||
# 40| r40_2(int) = Constant[1] :
|
||||
# 40| v40_3(void) = Call[ExRaiseAccessViolation] : func:r40_1, 0:r40_2
|
||||
# 40| m40_4(unknown) = ^CallSideEffect : ~m38_1
|
||||
# 40| m40_5(unknown) = Chi : total:m38_1, partial:m40_4
|
||||
#-----| Exception (back edge) -> Block 3
|
||||
|
||||
# 32| Block 5
|
||||
# 32| v32_5(void) = Unreached :
|
||||
|
||||
ir.cpp:
|
||||
# 1| void Constants()
|
||||
# 1| Block 0
|
||||
|
||||
@@ -8,6 +8,22 @@ sideEffectWithoutPrimary
|
||||
instructionWithoutSuccessor
|
||||
ambiguousSuccessors
|
||||
unexplainedLoop
|
||||
| ir.c:38:13:38:37 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:38:13:38:37 | Phi: 1 | Instruction 'Phi: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | Call: call to ExRaiseAccessViolation | Instruction 'Call: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Instruction 'FunctionAddress: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:28:40:28 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
unnecessaryPhiInstruction
|
||||
memoryOperandDefinitionIsUnmodeled
|
||||
operandAcrossFunctions
|
||||
@@ -18,6 +34,9 @@ containsLoopOfForwardEdges
|
||||
missingIRType
|
||||
multipleIRTypes
|
||||
lostReachability
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Block 'FunctionAddress: call to ExRaiseAccessViolation' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
|
||||
@@ -8,6 +8,22 @@ sideEffectWithoutPrimary
|
||||
instructionWithoutSuccessor
|
||||
ambiguousSuccessors
|
||||
unexplainedLoop
|
||||
| ir.c:38:13:38:37 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:38:13:38:37 | Phi: 1 | Instruction 'Phi: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | Call: call to ExRaiseAccessViolation | Instruction 'Call: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Instruction 'FunctionAddress: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:28:40:28 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
unnecessaryPhiInstruction
|
||||
memoryOperandDefinitionIsUnmodeled
|
||||
operandAcrossFunctions
|
||||
@@ -18,6 +34,9 @@ containsLoopOfForwardEdges
|
||||
missingIRType
|
||||
multipleIRTypes
|
||||
lostReachability
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Block 'FunctionAddress: call to ExRaiseAccessViolation' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
|
||||
@@ -29,4 +29,16 @@ int TryExceptTest(int x) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void unexplained_loop_regression()
|
||||
{
|
||||
__try
|
||||
{
|
||||
ExRaiseAccessViolation(0);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
ExRaiseAccessViolation(1);
|
||||
}
|
||||
}
|
||||
|
||||
// semmle-extractor-options: --microsoft
|
||||
|
||||
@@ -8,6 +8,20 @@ sideEffectWithoutPrimary
|
||||
instructionWithoutSuccessor
|
||||
ambiguousSuccessors
|
||||
unexplainedLoop
|
||||
| ir.c:38:13:38:37 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | Call: call to ExRaiseAccessViolation | Instruction 'Call: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Instruction 'FunctionAddress: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:28:40:28 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
unnecessaryPhiInstruction
|
||||
memoryOperandDefinitionIsUnmodeled
|
||||
operandAcrossFunctions
|
||||
@@ -18,6 +32,10 @@ containsLoopOfForwardEdges
|
||||
missingIRType
|
||||
multipleIRTypes
|
||||
lostReachability
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Unwind: { ... } | Block 'Unwind: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Block 'FunctionAddress: call to ExRaiseAccessViolation' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
| ir.cpp:1535:8:1535:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1535:8:1535:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() |
|
||||
|
||||
@@ -2926,6 +2926,52 @@ ir.c:
|
||||
# 27| mu27_3(int) = Store[#return] : &:r27_1, r27_2
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 32| void unexplained_loop_regression()
|
||||
# 32| Block 0
|
||||
# 32| v32_1(void) = EnterFunction :
|
||||
# 32| mu32_2(unknown) = AliasedDefinition :
|
||||
# 32| mu32_3(unknown) = InitializeNonLocal :
|
||||
# 36| r36_1(glval<unknown>) = FunctionAddress[ExRaiseAccessViolation] :
|
||||
# 36| r36_2(int) = Constant[0] :
|
||||
# 36| v36_3(void) = Call[ExRaiseAccessViolation] : func:r36_1, 0:r36_2
|
||||
# 36| mu36_4(unknown) = ^CallSideEffect : ~m?
|
||||
#-----| Exception -> Block 4
|
||||
|
||||
# 39| Block 1
|
||||
# 39| r39_1(int) = Constant[0] :
|
||||
# 39| r39_2(bool) = CompareEQ : r38_1, r39_1
|
||||
# 39| v39_3(void) = ConditionalBranch : r39_2
|
||||
#-----| False (back edge) -> Block 2
|
||||
#-----| True (back edge) -> Block 3
|
||||
|
||||
# 39| Block 2
|
||||
# 39| r39_4(int) = Constant[1] :
|
||||
# 39| r39_5(bool) = CompareEQ : r38_1, r39_4
|
||||
# 39| v39_6(void) = ConditionalBranch : r39_5
|
||||
#-----| True (back edge) -> Block 5
|
||||
|
||||
# 39| Block 3
|
||||
# 39| v39_7(void) = Unwind :
|
||||
# 42| v42_1(void) = NoOp :
|
||||
# 32| v32_4(void) = ReturnVoid :
|
||||
# 32| v32_5(void) = AliasedUse : ~m?
|
||||
# 32| v32_6(void) = ExitFunction :
|
||||
|
||||
# 38| Block 4
|
||||
# 38| r38_1(int) = Constant[1] :
|
||||
# 39| r39_8(int) = Constant[-1] :
|
||||
# 39| r39_9(bool) = CompareEQ : r38_1, r39_8
|
||||
# 39| v39_10(void) = ConditionalBranch : r39_9
|
||||
#-----| False (back edge) -> Block 1
|
||||
#-----| True (back edge) -> Block 3
|
||||
|
||||
# 40| Block 5
|
||||
# 40| r40_1(glval<unknown>) = FunctionAddress[ExRaiseAccessViolation] :
|
||||
# 40| r40_2(int) = Constant[1] :
|
||||
# 40| v40_3(void) = Call[ExRaiseAccessViolation] : func:r40_1, 0:r40_2
|
||||
# 40| mu40_4(unknown) = ^CallSideEffect : ~m?
|
||||
#-----| Exception (back edge) -> Block 4
|
||||
|
||||
ir.cpp:
|
||||
# 1| void Constants()
|
||||
# 1| Block 0
|
||||
|
||||
@@ -8,6 +8,20 @@ sideEffectWithoutPrimary
|
||||
instructionWithoutSuccessor
|
||||
ambiguousSuccessors
|
||||
unexplainedLoop
|
||||
| ir.c:38:13:38:37 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | Call: call to ExRaiseAccessViolation | Instruction 'Call: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Instruction 'FunctionAddress: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:28:40:28 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
unnecessaryPhiInstruction
|
||||
memoryOperandDefinitionIsUnmodeled
|
||||
operandAcrossFunctions
|
||||
@@ -18,6 +32,9 @@ containsLoopOfForwardEdges
|
||||
missingIRType
|
||||
multipleIRTypes
|
||||
lostReachability
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Block 'FunctionAddress: call to ExRaiseAccessViolation' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
|
||||
@@ -8,6 +8,20 @@ sideEffectWithoutPrimary
|
||||
instructionWithoutSuccessor
|
||||
ambiguousSuccessors
|
||||
unexplainedLoop
|
||||
| ir.c:38:13:38:37 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | Call: call to ExRaiseAccessViolation | Instruction 'Call: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Instruction 'FunctionAddress: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:28:40:28 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
unnecessaryPhiInstruction
|
||||
memoryOperandDefinitionIsUnmodeled
|
||||
operandAcrossFunctions
|
||||
@@ -18,6 +32,9 @@ containsLoopOfForwardEdges
|
||||
missingIRType
|
||||
multipleIRTypes
|
||||
lostReachability
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Block 'FunctionAddress: call to ExRaiseAccessViolation' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
|
||||
@@ -18,17 +18,35 @@ private class ReturnNodeExt extends DataFlow::Node {
|
||||
kind = DataFlowImplCommon::getParamReturnPosition(this, _).getKind()
|
||||
}
|
||||
|
||||
string getOutput() {
|
||||
kind instanceof DataFlowImplCommon::ValueReturnKind and
|
||||
/**
|
||||
* Gets the kind of the return node.
|
||||
*/
|
||||
DataFlowImplCommon::ReturnKindExt getKind() { result = kind }
|
||||
}
|
||||
|
||||
bindingset[c]
|
||||
private signature string printCallableParamSig(Callable c, ParameterPosition p);
|
||||
|
||||
private module PrintReturnNodeExt<printCallableParamSig/2 printCallableParam> {
|
||||
string getOutput(ReturnNodeExt node) {
|
||||
node.getKind() instanceof DataFlowImplCommon::ValueReturnKind and
|
||||
result = "ReturnValue"
|
||||
or
|
||||
exists(ParameterPosition pos |
|
||||
pos = kind.(DataFlowImplCommon::ParamUpdateReturnKind).getPosition() and
|
||||
result = paramReturnNodeAsOutput(returnNodeEnclosingCallable(this), pos)
|
||||
pos = node.getKind().(DataFlowImplCommon::ParamUpdateReturnKind).getPosition() and
|
||||
result = printCallableParam(returnNodeEnclosingCallable(node), pos)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
string getOutput(ReturnNodeExt node) {
|
||||
result = PrintReturnNodeExt<paramReturnNodeAsOutput/2>::getOutput(node)
|
||||
}
|
||||
|
||||
string getContentOutput(ReturnNodeExt node) {
|
||||
result = PrintReturnNodeExt<paramReturnNodeAsContentOutput/2>::getOutput(node)
|
||||
}
|
||||
|
||||
class DataFlowSummaryTargetApi extends SummaryTargetApi {
|
||||
DataFlowSummaryTargetApi() { not isUninterestingForDataFlowModels(this) }
|
||||
}
|
||||
@@ -71,7 +89,8 @@ private predicate isRelevantTaintStep(DataFlow::Node node1, DataFlow::Node node2
|
||||
* Holds if content `c` is either a field, a synthetic field or language specific
|
||||
* content of a relevant type or a container like content.
|
||||
*/
|
||||
private predicate isRelevantContent(DataFlow::ContentSet c) {
|
||||
pragma[nomagic]
|
||||
private predicate isRelevantContent0(DataFlow::ContentSet c) {
|
||||
isRelevantTypeInContent(c) or
|
||||
containerContent(c)
|
||||
}
|
||||
@@ -85,6 +104,16 @@ string parameterNodeAsInput(DataFlow::ParameterNode p) {
|
||||
result = qualifierString() and p instanceof InstanceParameterNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the parameter `p`
|
||||
* when used in content flow.
|
||||
*/
|
||||
string parameterNodeAsContentInput(DataFlow::ParameterNode p) {
|
||||
result = parameterContentAccess(p.asParameter())
|
||||
or
|
||||
result = qualifierString() and p instanceof InstanceParameterNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD input string representation of `source`.
|
||||
*/
|
||||
@@ -170,7 +199,7 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
) {
|
||||
exists(DataFlow::ContentSet c |
|
||||
DataFlowImplCommon::store(node1, c.getAStoreContent(), node2, _, _) and
|
||||
isRelevantContent(c) and
|
||||
isRelevantContent0(c) and
|
||||
(
|
||||
state1 instanceof TaintRead and state2.(TaintStore).getStep() = 1
|
||||
or
|
||||
@@ -180,7 +209,7 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
or
|
||||
exists(DataFlow::ContentSet c |
|
||||
DataFlowPrivate::readStep(node1, c, node2) and
|
||||
isRelevantContent(c) and
|
||||
isRelevantContent0(c) and
|
||||
state1.(TaintRead).getStep() + 1 = state2.(TaintRead).getStep()
|
||||
)
|
||||
}
|
||||
@@ -196,6 +225,9 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
|
||||
module PropagateFlow = TaintTracking::GlobalWithState<PropagateFlowConfig>;
|
||||
|
||||
/**
|
||||
* Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
|
||||
*/
|
||||
string captureThroughFlow0(
|
||||
DataFlowSummaryTargetApi api, DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt
|
||||
) {
|
||||
@@ -203,7 +235,7 @@ string captureThroughFlow0(
|
||||
p.getEnclosingCallable() = api and
|
||||
returnNodeExt.(DataFlow::Node).getEnclosingCallable() = api and
|
||||
input = parameterNodeAsInput(p) and
|
||||
output = returnNodeExt.getOutput() and
|
||||
output = getOutput(returnNodeExt) and
|
||||
input != output and
|
||||
result = Printing::asTaintModel(api, input, output)
|
||||
)
|
||||
@@ -219,6 +251,69 @@ string captureThroughFlow(DataFlowSummaryTargetApi api) {
|
||||
)
|
||||
}
|
||||
|
||||
private module PropagateContentFlowConfig implements ContentDataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source instanceof DataFlow::ParameterNode and
|
||||
source.getEnclosingCallable() instanceof DataFlowSummaryTargetApi
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
sink instanceof ReturnNodeExt and
|
||||
sink.getEnclosingCallable() instanceof DataFlowSummaryTargetApi
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep = isAdditionalContentFlowStep/2;
|
||||
|
||||
predicate isBarrier(DataFlow::Node n) {
|
||||
exists(Type t | t = n.getType() and not isRelevantType(t))
|
||||
}
|
||||
|
||||
int accessPathLimit() { result = 2 }
|
||||
|
||||
predicate isRelevantContent(DataFlow::ContentSet s) { isRelevantContent0(s) }
|
||||
|
||||
DataFlow::FlowFeature getAFeature() {
|
||||
result instanceof DataFlow::FeatureEqualSourceSinkCallContext
|
||||
}
|
||||
}
|
||||
|
||||
private module PropagateContentFlow = ContentDataFlow::Global<PropagateContentFlowConfig>;
|
||||
|
||||
private string getContent(PropagateContentFlow::AccessPath ap, int i) {
|
||||
exists(ContentSet head, PropagateContentFlow::AccessPath tail |
|
||||
head = ap.getHead() and
|
||||
tail = ap.getTail()
|
||||
|
|
||||
i = 0 and
|
||||
result = "." + printContent(head)
|
||||
or
|
||||
i > 0 and result = getContent(tail, i - 1)
|
||||
)
|
||||
}
|
||||
|
||||
private string printStoreAccessPath(PropagateContentFlow::AccessPath ap) {
|
||||
result = concat(int i | | getContent(ap, i), "" order by i)
|
||||
}
|
||||
|
||||
private string printReadAccessPath(PropagateContentFlow::AccessPath ap) {
|
||||
result = concat(int i | | getContent(ap, i), "" order by i desc)
|
||||
}
|
||||
|
||||
string captureContentFlow(DataFlowSummaryTargetApi api) {
|
||||
exists(
|
||||
DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt, string input, string output,
|
||||
PropagateContentFlow::AccessPath reads, PropagateContentFlow::AccessPath stores,
|
||||
boolean preservesValue
|
||||
|
|
||||
PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and
|
||||
returnNodeExt.getEnclosingCallable() = api and
|
||||
input = parameterNodeAsContentInput(p) + printReadAccessPath(reads) and
|
||||
output = getContentOutput(returnNodeExt) + printStoreAccessPath(stores) and
|
||||
input != output and
|
||||
result = Printing::asModel(api, input, output, preservesValue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A dataflow configuration used for finding new sources.
|
||||
* The sources are the already known existing sources and the sinks are the API return nodes.
|
||||
@@ -261,7 +356,7 @@ string captureSource(DataFlowSourceTargetApi api) {
|
||||
ExternalFlow::sourceNode(source, kind) and
|
||||
api = sink.getEnclosingCallable() and
|
||||
not irrelevantSourceSinkApi(source.getEnclosingCallable(), api) and
|
||||
result = Printing::asSourceModel(api, sink.getOutput(), kind)
|
||||
result = Printing::asSourceModel(api, getOutput(sink), kind)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
private import csharp as CS
|
||||
private import semmle.code.csharp.commons.Util as Util
|
||||
private import semmle.code.csharp.commons.Collections as Collections
|
||||
private import semmle.code.csharp.commons.QualifiedName as QualifiedName
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
|
||||
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
private import semmle.code.csharp.frameworks.system.linq.Expressions
|
||||
private import semmle.code.csharp.frameworks.System
|
||||
private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate as TaintTrackingPrivate
|
||||
import semmle.code.csharp.dataflow.internal.ExternalFlow as ExternalFlow
|
||||
import semmle.code.csharp.dataflow.internal.ContentDataFlow as ContentDataFlow
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowPrivate as DataFlowPrivate
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowDispatch as DataFlowDispatch
|
||||
@@ -22,6 +25,8 @@ class Type = CS::Type;
|
||||
|
||||
class Callable = CS::Callable;
|
||||
|
||||
class ContentSet = DataFlow::ContentSet;
|
||||
|
||||
/**
|
||||
* Holds if any of the parameters of `api` are `System.Func<>`.
|
||||
*/
|
||||
@@ -241,20 +246,40 @@ string parameterAccess(CS::Parameter p) {
|
||||
else result = "Argument[" + p.getPosition() + "]"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the parameter `p`
|
||||
* when used in content flow.
|
||||
*/
|
||||
string parameterContentAccess(CS::Parameter p) { result = "Argument[" + p.getPosition() + "]" }
|
||||
|
||||
class InstanceParameterNode = DataFlowPrivate::InstanceParameterNode;
|
||||
|
||||
class ParameterPosition = DataFlowDispatch::ParameterPosition;
|
||||
|
||||
private signature string parameterAccessSig(Parameter p);
|
||||
|
||||
module ParamReturnNodeAsOutput<parameterAccessSig/1 getParamAccess> {
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsOutput(CS::Callable c, ParameterPosition pos) {
|
||||
result = getParamAccess(c.getParameter(pos.getPosition()))
|
||||
or
|
||||
pos.isThisParameter() and
|
||||
result = qualifierString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of return through parameter at position
|
||||
* `pos` of callable `c`.
|
||||
*/
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsOutput(CS::Callable c, ParameterPosition pos) {
|
||||
result = parameterAccess(c.getParameter(pos.getPosition()))
|
||||
or
|
||||
pos.isThisParameter() and
|
||||
result = qualifierString()
|
||||
result = ParamReturnNodeAsOutput<parameterAccess/1>::paramReturnNodeAsOutput(c, pos)
|
||||
}
|
||||
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsContentOutput(Callable c, ParameterPosition pos) {
|
||||
result = ParamReturnNodeAsOutput<parameterContentAccess/1>::paramReturnNodeAsOutput(c, pos)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -344,3 +369,44 @@ predicate isRelevantSourceKind(string kind) { any() }
|
||||
* Holds if the the content `c` is a container.
|
||||
*/
|
||||
predicate containerContent(DataFlow::ContentSet c) { c.isElement() }
|
||||
|
||||
/**
|
||||
* Holds if there is a taint step from `node1` to `node2` in content flow.
|
||||
*/
|
||||
predicate isAdditionalContentFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
TaintTrackingPrivate::defaultAdditionalTaintStep(nodeFrom, nodeTo, _) and
|
||||
not nodeTo.asExpr() instanceof CS::ElementAccess and
|
||||
not exists(DataFlow::ContentSet c |
|
||||
DataFlowPrivate::readStep(nodeFrom, c, nodeTo) and containerContent(c)
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[d]
|
||||
private string getFullyQualifiedName(Declaration d) {
|
||||
exists(string qualifier, string name |
|
||||
d.hasFullyQualifiedName(qualifier, name) and
|
||||
result = QualifiedName::getQualifiedName(qualifier, name)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the contentset `c`.
|
||||
*/
|
||||
string printContent(DataFlow::ContentSet c) {
|
||||
exists(CS::Field f, string name | name = getFullyQualifiedName(f) |
|
||||
c.isField(f) and
|
||||
if f.isEffectivelyPublic()
|
||||
then result = "Field[" + name + "]"
|
||||
else result = "SyntheticField[" + name + "]"
|
||||
)
|
||||
or
|
||||
exists(CS::Property p, string name | name = getFullyQualifiedName(p) |
|
||||
c.isProperty(p) and
|
||||
if p.isEffectivelyPublic()
|
||||
then result = "Property[" + name + "]"
|
||||
else result = "SyntheticField[" + name + "]"
|
||||
)
|
||||
or
|
||||
c.isElement() and
|
||||
result = "Element"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
unexpectedModel
|
||||
expectedModel
|
||||
@@ -0,0 +1,12 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/csharp-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- [ "Models", "ManuallyModelled", False, "HasSummary", "(System.Object)", "", "Argument[0]", "ReturnValue", "value", "manual"]
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/csharp-all
|
||||
extensible: neutralModel
|
||||
data:
|
||||
- [ "Models", "ManuallyModelled", "HasNeutralSummary", "(System.Object)", "summary", "manual"]
|
||||
@@ -0,0 +1,11 @@
|
||||
import csharp
|
||||
import utils.modelgenerator.internal.CaptureModels
|
||||
import TestUtilities.InlineMadTest
|
||||
|
||||
module InlineMadTestConfig implements InlineMadTestConfigSig {
|
||||
string getCapturedModel(Callable c) { result = captureContentFlow(c) }
|
||||
|
||||
string getKind() { result = "contentbased-summary" }
|
||||
}
|
||||
|
||||
import InlineMadTest<InlineMadTestConfig>
|
||||
@@ -13,18 +13,21 @@ public class BasicFlow
|
||||
private string tainted;
|
||||
|
||||
// summary=Models;BasicFlow;false;ReturnThis;(System.Object);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnThis;(System.Object);;Argument[this];ReturnValue;value;df-generated
|
||||
public BasicFlow ReturnThis(object input)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// summary=Models;BasicFlow;false;ReturnParam0;(System.String,System.Object);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnParam0;(System.String,System.Object);;Argument[0];ReturnValue;value;df-generated
|
||||
public string ReturnParam0(string input0, object input1)
|
||||
{
|
||||
return input0;
|
||||
}
|
||||
|
||||
// summary=Models;BasicFlow;false;ReturnParam1;(System.String,System.Object);;Argument[1];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnParam1;(System.String,System.Object);;Argument[1];ReturnValue;value;df-generated
|
||||
public object ReturnParam1(string input0, object input1)
|
||||
{
|
||||
return input1;
|
||||
@@ -32,24 +35,29 @@ public class BasicFlow
|
||||
|
||||
// summary=Models;BasicFlow;false;ReturnParamMultiple;(System.Object,System.Object);;Argument[0];ReturnValue;taint;df-generated
|
||||
// summary=Models;BasicFlow;false;ReturnParamMultiple;(System.Object,System.Object);;Argument[1];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnParamMultiple;(System.Object,System.Object);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnParamMultiple;(System.Object,System.Object);;Argument[1];ReturnValue;value;df-generated
|
||||
public object ReturnParamMultiple(object input0, object input1)
|
||||
{
|
||||
return (System.DateTime.Now.DayOfWeek == System.DayOfWeek.Monday) ? input0 : input1;
|
||||
}
|
||||
|
||||
// summary=Models;BasicFlow;false;ReturnSubstring;(System.String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnSubstring;(System.String);;Argument[0];ReturnValue;taint;df-generated
|
||||
public string ReturnSubstring(string s)
|
||||
{
|
||||
return s.Substring(0, 1);
|
||||
}
|
||||
|
||||
// summary=Models;BasicFlow;false;SetField;(System.String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;SetField;(System.String);;Argument[0];Argument[this].SyntheticField[Models.BasicFlow.tainted];value;df-generated
|
||||
public void SetField(string s)
|
||||
{
|
||||
tainted = s;
|
||||
}
|
||||
|
||||
// summary=Models;BasicFlow;false;ReturnField;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BasicFlow;false;ReturnField;();;Argument[this].SyntheticField[Models.BasicFlow.tainted];ReturnValue;value;df-generated
|
||||
public string ReturnField()
|
||||
{
|
||||
return tainted;
|
||||
@@ -61,72 +69,84 @@ public class CollectionFlow
|
||||
private string tainted;
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnArrayElement;(System.Object[]);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnArrayElement;(System.Object[]);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
public object ReturnArrayElement(object[] input)
|
||||
{
|
||||
return input[0];
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;AssignToArray;(System.Object,System.Object[]);;Argument[0];Argument[1].Element;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;AssignToArray;(System.Object,System.Object[]);;Argument[0];Argument[1].Element;value;df-generated
|
||||
public void AssignToArray(object data, object[] target)
|
||||
{
|
||||
target[0] = data;
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;AssignFieldToArray;(System.Object[]);;Argument[this];Argument[0].Element;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;AssignFieldToArray;(System.Object[]);;Argument[this].SyntheticField[Models.CollectionFlow.tainted];Argument[0].Element;value;df-generated
|
||||
public void AssignFieldToArray(object[] target)
|
||||
{
|
||||
target[0] = tainted;
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnListElement;(System.Collections.Generic.List<System.Object>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnListElement;(System.Collections.Generic.List<System.Object>);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
public object ReturnListElement(List<object> input)
|
||||
{
|
||||
return input[0];
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;AddToList;(System.Collections.Generic.List<System.Object>,System.Object);;Argument[1];Argument[0].Element;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;AddToList;(System.Collections.Generic.List<System.Object>,System.Object);;Argument[1];Argument[0].Element;value;df-generated
|
||||
public void AddToList(List<object> input, object data)
|
||||
{
|
||||
input.Add(data);
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;AddFieldToList;(System.Collections.Generic.List<System.String>);;Argument[this];Argument[0].Element;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;AddFieldToList;(System.Collections.Generic.List<System.String>);;Argument[this].SyntheticField[Models.CollectionFlow.tainted];Argument[0].Element;value;df-generated
|
||||
public void AddFieldToList(List<string> input)
|
||||
{
|
||||
input.Add(tainted);
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnFieldInAList;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnFieldInAList;();;Argument[this].SyntheticField[Models.CollectionFlow.tainted];ReturnValue.Element;value;df-generated
|
||||
public List<string> ReturnFieldInAList()
|
||||
{
|
||||
return new List<string> { tainted };
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnComplexTypeArray;(System.String[]);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// SPURIOUS-summary=Models;CollectionFlow;false;ReturnComplexTypeArray;(System.String[]);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnComplexTypeArray;(System.String[]);;Argument[0];ReturnValue;value;df-generated
|
||||
public string[] ReturnComplexTypeArray(string[] a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnBulkTypeList;(System.Collections.Generic.List<System.Byte>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// SPURIOUS-summary=Models;CollectionFlow;false;ReturnBulkTypeList;(System.Collections.Generic.List<System.Byte>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnBulkTypeList;(System.Collections.Generic.List<System.Byte>);;Argument[0];ReturnValue;value;df-generated
|
||||
public List<byte> ReturnBulkTypeList(List<byte> a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnComplexTypeDictionary;(System.Collections.Generic.Dictionary<System.Int32,System.String>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// SPURIOUS-summary=Models;CollectionFlow;false;ReturnComplexTypeDictionary;(System.Collections.Generic.Dictionary<System.Int32,System.String>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnComplexTypeDictionary;(System.Collections.Generic.Dictionary<System.Int32,System.String>);;Argument[0];ReturnValue;value;df-generated
|
||||
public Dictionary<int, string> ReturnComplexTypeDictionary(Dictionary<int, string> a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnUntypedArray;(System.Array);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// SPURIOUS-summary=Models;CollectionFlow;false;ReturnUntypedArray;(System.Array);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnUntypedArray;(System.Array);;Argument[0];ReturnValue;value;df-generated
|
||||
public Array ReturnUntypedArray(Array a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
// summary=Models;CollectionFlow;false;ReturnUntypedList;(System.Collections.IList);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// SPURIOUS-summary=Models;CollectionFlow;false;ReturnUntypedList;(System.Collections.IList);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;CollectionFlow;false;ReturnUntypedList;(System.Collections.IList);;Argument[0];ReturnValue;value;df-generated
|
||||
public IList ReturnUntypedList(IList a)
|
||||
{
|
||||
return a;
|
||||
@@ -159,19 +179,22 @@ public class IEnumerableFlow
|
||||
{
|
||||
private string tainted;
|
||||
|
||||
// summary=Models;IEnumerableFlow;false;ReturnIEnumerable;(System.Collections.Generic.IEnumerable<System.String>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// SPURIOUS-summary=Models;IEnumerableFlow;false;ReturnIEnumerable;(System.Collections.Generic.IEnumerable<System.String>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;IEnumerableFlow;false;ReturnIEnumerable;(System.Collections.Generic.IEnumerable<System.String>);;Argument[0];ReturnValue;value;df-generated
|
||||
public IEnumerable<string> ReturnIEnumerable(IEnumerable<string> input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
// summary=Models;IEnumerableFlow;false;ReturnIEnumerableElement;(System.Collections.Generic.IEnumerable<System.Object>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;IEnumerableFlow;false;ReturnIEnumerableElement;(System.Collections.Generic.IEnumerable<System.Object>);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
public object ReturnIEnumerableElement(IEnumerable<object> input)
|
||||
{
|
||||
return input.First();
|
||||
}
|
||||
|
||||
// summary=Models;IEnumerableFlow;false;ReturnFieldInIEnumerable;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;IEnumerableFlow;false;ReturnFieldInIEnumerable;();;Argument[this].SyntheticField[Models.IEnumerableFlow.tainted];ReturnValue.Element;value;df-generated
|
||||
public IEnumerable<string> ReturnFieldInIEnumerable()
|
||||
{
|
||||
return new List<string> { tainted };
|
||||
@@ -183,42 +206,49 @@ public class GenericFlow<T>
|
||||
private T tainted;
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;SetGenericField;(T);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;SetGenericField;(T);;Argument[0];Argument[this].SyntheticField[Models.GenericFlow`1.tainted];value;df-generated
|
||||
public void SetGenericField(T t)
|
||||
{
|
||||
tainted = t;
|
||||
}
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;ReturnGenericField;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;ReturnGenericField;();;Argument[this].SyntheticField[Models.GenericFlow`1.tainted];ReturnValue;value;df-generated
|
||||
public T ReturnGenericField()
|
||||
{
|
||||
return tainted;
|
||||
}
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;AddFieldToGenericList;(System.Collections.Generic.List<T>);;Argument[this];Argument[0].Element;taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;AddFieldToGenericList;(System.Collections.Generic.List<T>);;Argument[this].SyntheticField[Models.GenericFlow`1.tainted];Argument[0].Element;value;df-generated
|
||||
public void AddFieldToGenericList(List<T> input)
|
||||
{
|
||||
input.Add(tainted);
|
||||
}
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;ReturnFieldInGenericList;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;ReturnFieldInGenericList;();;Argument[this].SyntheticField[Models.GenericFlow`1.tainted];ReturnValue.Element;value;df-generated
|
||||
public List<T> ReturnFieldInGenericList()
|
||||
{
|
||||
return new List<T> { tainted };
|
||||
}
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;ReturnGenericParam<S>;(S);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;ReturnGenericParam<S>;(S);;Argument[0];ReturnValue;value;df-generated
|
||||
public S ReturnGenericParam<S>(S input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;ReturnGenericElement<S>;(System.Collections.Generic.List<S>);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;ReturnGenericElement<S>;(System.Collections.Generic.List<S>);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
public S ReturnGenericElement<S>(List<S> input)
|
||||
{
|
||||
return input[0];
|
||||
}
|
||||
|
||||
// summary=Models;GenericFlow<T>;false;AddToGenericList<S>;(System.Collections.Generic.List<S>,S);;Argument[1];Argument[0].Element;taint;df-generated
|
||||
// contentbased-summary=Models;GenericFlow<T>;false;AddToGenericList<S>;(System.Collections.Generic.List<S>,S);;Argument[1];Argument[0].Element;value;df-generated
|
||||
public void AddToGenericList<S>(List<S> input, S data)
|
||||
{
|
||||
input.Add(data);
|
||||
@@ -228,6 +258,7 @@ public class GenericFlow<T>
|
||||
public abstract class BaseClassFlow
|
||||
{
|
||||
// summary=Models;BaseClassFlow;true;ReturnParam;(System.Object);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BaseClassFlow;true;ReturnParam;(System.Object);;Argument[0];ReturnValue;value;df-generated
|
||||
public virtual object ReturnParam(object input)
|
||||
{
|
||||
return input;
|
||||
@@ -237,6 +268,7 @@ public abstract class BaseClassFlow
|
||||
public class DerivedClass1Flow : BaseClassFlow
|
||||
{
|
||||
// summary=Models;DerivedClass1Flow;false;ReturnParam1;(System.String,System.String);;Argument[1];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;DerivedClass1Flow;false;ReturnParam1;(System.String,System.String);;Argument[1];ReturnValue;value;df-generated
|
||||
public string ReturnParam1(string input0, string input1)
|
||||
{
|
||||
return input1;
|
||||
@@ -246,12 +278,14 @@ public class DerivedClass1Flow : BaseClassFlow
|
||||
public class DerivedClass2Flow : BaseClassFlow
|
||||
{
|
||||
// summary=Models;BaseClassFlow;true;ReturnParam;(System.Object);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;BaseClassFlow;true;ReturnParam;(System.Object);;Argument[0];ReturnValue;value;df-generated
|
||||
public override object ReturnParam(object input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
// summary=Models;DerivedClass2Flow;false;ReturnParam0;(System.String,System.Int32);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;DerivedClass2Flow;false;ReturnParam0;(System.String,System.Int32);;Argument[0];ReturnValue;value;df-generated
|
||||
public string ReturnParam0(string input0, int input1)
|
||||
{
|
||||
return input0;
|
||||
@@ -263,6 +297,7 @@ public class OperatorFlow
|
||||
public readonly object Field;
|
||||
|
||||
// summary=Models;OperatorFlow;false;OperatorFlow;(System.Object);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=Models;OperatorFlow;false;OperatorFlow;(System.Object);;Argument[0];Argument[this].Field[Models.OperatorFlow.Field];value;df-generated
|
||||
public OperatorFlow(object o)
|
||||
{
|
||||
Field = o;
|
||||
@@ -270,6 +305,7 @@ public class OperatorFlow
|
||||
|
||||
// Flow Summary.
|
||||
// summary=Models;OperatorFlow;false;op_Addition;(Models.OperatorFlow,Models.OperatorFlow);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;OperatorFlow;false;op_Addition;(Models.OperatorFlow,Models.OperatorFlow);;Argument[0];ReturnValue;value;df-generated
|
||||
public static OperatorFlow operator +(OperatorFlow a, OperatorFlow b)
|
||||
{
|
||||
return a;
|
||||
@@ -310,6 +346,7 @@ public class EqualsGetHashCodeNoFlow
|
||||
}
|
||||
|
||||
// summary=Models;EqualsGetHashCodeNoFlow;false;Equals;(System.String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;EqualsGetHashCodeNoFlow;false;Equals;(System.String);;Argument[0];ReturnValue;value;df-generated
|
||||
public string Equals(string s)
|
||||
{
|
||||
return s;
|
||||
@@ -327,12 +364,14 @@ public class Properties
|
||||
private string tainted;
|
||||
|
||||
// summary=Models;Properties;false;get_Prop1;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;Properties;false;get_Prop1;();;Argument[this].SyntheticField[Models.Properties.tainted];ReturnValue;value;df-generated
|
||||
public string Prop1
|
||||
{
|
||||
get { return tainted; }
|
||||
}
|
||||
|
||||
// summary=Models;Properties;false;set_Prop2;(System.String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=Models;Properties;false;set_Prop2;(System.String);;Argument[0];Argument[this].SyntheticField[Models.Properties.tainted];value;df-generated
|
||||
public string Prop2
|
||||
{
|
||||
set { tainted = value; }
|
||||
@@ -513,6 +552,7 @@ public class Inheritance
|
||||
public class AImplBasePublic : BasePublic
|
||||
{
|
||||
// summary=Models;Inheritance+BasePublic;true;Id;(System.String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;Inheritance+BasePublic;true;Id;(System.String);;Argument[0];ReturnValue;value;df-generated
|
||||
public override string Id(string x)
|
||||
{
|
||||
return x;
|
||||
@@ -542,6 +582,7 @@ public class Inheritance
|
||||
public class BImpl : B
|
||||
{
|
||||
// summary=Models;Inheritance+IPublic1;true;Id;(System.String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;Inheritance+IPublic1;true;Id;(System.String);;Argument[0];ReturnValue;value;df-generated
|
||||
public override string Id(string x)
|
||||
{
|
||||
return x;
|
||||
@@ -551,6 +592,7 @@ public class Inheritance
|
||||
private class CImpl : C
|
||||
{
|
||||
// summary=Models;Inheritance+IPublic2;true;Id;(System.String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;Inheritance+IPublic2;true;Id;(System.String);;Argument[0];ReturnValue;value;df-generated
|
||||
public override string Id(string x)
|
||||
{
|
||||
return x;
|
||||
@@ -572,6 +614,7 @@ public class Inheritance
|
||||
private string tainted;
|
||||
|
||||
// summary=Models;Inheritance+IPublic3;true;get_Prop;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;Inheritance+IPublic3;true;get_Prop;();;Argument[this].SyntheticField[Models.Inheritance+DImpl.tainted];ReturnValue;value;df-generated
|
||||
public override string Prop { get { return tainted; } }
|
||||
}
|
||||
}
|
||||
@@ -586,14 +629,54 @@ public class MemberFlow
|
||||
}
|
||||
|
||||
// summary=Models;MemberFlow;false;M1;(Models.MemberFlow+C);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;MemberFlow;false;M1;(Models.MemberFlow+C);;Argument[0].Property[Models.MemberFlow+C.Prop];ReturnValue;value;df-generated
|
||||
public string M1(C c)
|
||||
{
|
||||
return c.Prop;
|
||||
}
|
||||
|
||||
// summary=Models;MemberFlow;false;M2;(Models.MemberFlow+C);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;MemberFlow;false;M2;(Models.MemberFlow+C);;Argument[0].Field[Models.MemberFlow+C.Field];ReturnValue;value;df-generated
|
||||
public string M2(C c)
|
||||
{
|
||||
return c.Field;
|
||||
}
|
||||
}
|
||||
|
||||
public class IDictionaryFlow
|
||||
{
|
||||
// summary=Models;IDictionaryFlow;false;ReturnIDictionaryValue;(System.Collections.Generic.IDictionary<System.Object,System.Object>,System.Object);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;IDictionaryFlow;false;ReturnIDictionaryValue;(System.Collections.Generic.IDictionary<System.Object,System.Object>,System.Object);;Argument[0].Element.Property[System.Collections.Generic.KeyValuePair`2.Value];ReturnValue;value;df-generated
|
||||
public object ReturnIDictionaryValue(IDictionary<object, object> input, object key)
|
||||
{
|
||||
return input[key];
|
||||
}
|
||||
}
|
||||
|
||||
public class NestedFieldFlow
|
||||
{
|
||||
public NestedFieldFlow FieldA;
|
||||
public NestedFieldFlow FieldB;
|
||||
|
||||
// summary=Models;NestedFieldFlow;false;Move;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;NestedFieldFlow;false;Move;();;Argument[this].Field[Models.NestedFieldFlow.FieldA];ReturnValue.Field[Models.NestedFieldFlow.FieldB];value;df-generated
|
||||
public NestedFieldFlow Move()
|
||||
{
|
||||
return new NestedFieldFlow() { FieldB = this.FieldA };
|
||||
}
|
||||
|
||||
// summary=Models;NestedFieldFlow;false;MoveNested;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;NestedFieldFlow;false;MoveNested;();;Argument[this].Field[Models.NestedFieldFlow.FieldB].Field[Models.NestedFieldFlow.FieldA];ReturnValue.Field[Models.NestedFieldFlow.FieldA].Field[Models.NestedFieldFlow.FieldB];value;df-generated
|
||||
public NestedFieldFlow MoveNested()
|
||||
{
|
||||
return new NestedFieldFlow() { FieldA = FieldB.Move() };
|
||||
}
|
||||
|
||||
// summary=Models;NestedFieldFlow;false;ReverseFields;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=Models;NestedFieldFlow;false;ReverseFields;();;Argument[this].Field[Models.NestedFieldFlow.FieldA].Field[Models.NestedFieldFlow.FieldB];ReturnValue.Field[Models.NestedFieldFlow.FieldA].Field[Models.NestedFieldFlow.FieldB];value;df-generated
|
||||
public NestedFieldFlow ReverseFields()
|
||||
{
|
||||
var x = new NestedFieldFlow() { FieldB = this.FieldA.FieldB };
|
||||
return new NestedFieldFlow() { FieldA = x };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ go 1.22.0
|
||||
// when adding or removing dependencies, run
|
||||
// bazel mod tidy
|
||||
require (
|
||||
golang.org/x/mod v0.20.0
|
||||
golang.org/x/mod v0.21.0
|
||||
golang.org/x/tools v0.24.0
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
|
||||
@@ -649,18 +649,28 @@ class ReceiverDecl extends FieldBase, Documentable, ExprParent {
|
||||
* Examples:
|
||||
*
|
||||
* ```go
|
||||
* int
|
||||
* string
|
||||
* error
|
||||
* r io.Reader
|
||||
* output string
|
||||
* err error
|
||||
* x, y int
|
||||
* ```
|
||||
*
|
||||
* as in the following code:
|
||||
*
|
||||
* ```go
|
||||
* func f(error) { return nil }
|
||||
* func g(r io.Reader) { return nil }
|
||||
* func h(x, y int) { return }
|
||||
* func f1() int { return 0 }
|
||||
* func f2(input string) (string, error) { return "", nil }
|
||||
* func f3(a int) (r io.Reader) { return nil }
|
||||
* func f4(input string) (output string, err error) { return}
|
||||
* func f5(e error) (x, y int) { return }
|
||||
* ```
|
||||
*
|
||||
* Note: `x, y int` is a single `ResultVariableDecl` even though it declares
|
||||
* two different result variables. Use the member predicate `getTypeExpr()` to
|
||||
* get `int`, `getNameExpr(0)` to get `x` and `getNameExpr(1)` to get `y`.
|
||||
*/
|
||||
class ResultVariableDecl extends ParameterOrResultDecl {
|
||||
ResultVariableDecl() { rawIndex < 0 }
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
private import java
|
||||
private import DataFlowImplSpecific
|
||||
private import codeql.dataflow.internal.ContentDataFlowImpl
|
||||
|
||||
module ContentDataFlow {
|
||||
import MakeImplContentDataFlow<Location, JavaDataFlow>
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @name Capture content based summary models.
|
||||
* @description Finds applicable content based summary models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id java/utils/modelgenerator/contentbased-summary-models
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
from DataFlowSummaryTargetApi api, string flow
|
||||
where flow = captureContentFlow(api)
|
||||
select flow order by flow
|
||||
@@ -18,17 +18,35 @@ private class ReturnNodeExt extends DataFlow::Node {
|
||||
kind = DataFlowImplCommon::getParamReturnPosition(this, _).getKind()
|
||||
}
|
||||
|
||||
string getOutput() {
|
||||
kind instanceof DataFlowImplCommon::ValueReturnKind and
|
||||
/**
|
||||
* Gets the kind of the return node.
|
||||
*/
|
||||
DataFlowImplCommon::ReturnKindExt getKind() { result = kind }
|
||||
}
|
||||
|
||||
bindingset[c]
|
||||
private signature string printCallableParamSig(Callable c, ParameterPosition p);
|
||||
|
||||
private module PrintReturnNodeExt<printCallableParamSig/2 printCallableParam> {
|
||||
string getOutput(ReturnNodeExt node) {
|
||||
node.getKind() instanceof DataFlowImplCommon::ValueReturnKind and
|
||||
result = "ReturnValue"
|
||||
or
|
||||
exists(ParameterPosition pos |
|
||||
pos = kind.(DataFlowImplCommon::ParamUpdateReturnKind).getPosition() and
|
||||
result = paramReturnNodeAsOutput(returnNodeEnclosingCallable(this), pos)
|
||||
pos = node.getKind().(DataFlowImplCommon::ParamUpdateReturnKind).getPosition() and
|
||||
result = printCallableParam(returnNodeEnclosingCallable(node), pos)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
string getOutput(ReturnNodeExt node) {
|
||||
result = PrintReturnNodeExt<paramReturnNodeAsOutput/2>::getOutput(node)
|
||||
}
|
||||
|
||||
string getContentOutput(ReturnNodeExt node) {
|
||||
result = PrintReturnNodeExt<paramReturnNodeAsContentOutput/2>::getOutput(node)
|
||||
}
|
||||
|
||||
class DataFlowSummaryTargetApi extends SummaryTargetApi {
|
||||
DataFlowSummaryTargetApi() { not isUninterestingForDataFlowModels(this) }
|
||||
}
|
||||
@@ -71,7 +89,8 @@ private predicate isRelevantTaintStep(DataFlow::Node node1, DataFlow::Node node2
|
||||
* Holds if content `c` is either a field, a synthetic field or language specific
|
||||
* content of a relevant type or a container like content.
|
||||
*/
|
||||
private predicate isRelevantContent(DataFlow::ContentSet c) {
|
||||
pragma[nomagic]
|
||||
private predicate isRelevantContent0(DataFlow::ContentSet c) {
|
||||
isRelevantTypeInContent(c) or
|
||||
containerContent(c)
|
||||
}
|
||||
@@ -85,6 +104,16 @@ string parameterNodeAsInput(DataFlow::ParameterNode p) {
|
||||
result = qualifierString() and p instanceof InstanceParameterNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the parameter `p`
|
||||
* when used in content flow.
|
||||
*/
|
||||
string parameterNodeAsContentInput(DataFlow::ParameterNode p) {
|
||||
result = parameterContentAccess(p.asParameter())
|
||||
or
|
||||
result = qualifierString() and p instanceof InstanceParameterNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD input string representation of `source`.
|
||||
*/
|
||||
@@ -170,7 +199,7 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
) {
|
||||
exists(DataFlow::ContentSet c |
|
||||
DataFlowImplCommon::store(node1, c.getAStoreContent(), node2, _, _) and
|
||||
isRelevantContent(c) and
|
||||
isRelevantContent0(c) and
|
||||
(
|
||||
state1 instanceof TaintRead and state2.(TaintStore).getStep() = 1
|
||||
or
|
||||
@@ -180,7 +209,7 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
or
|
||||
exists(DataFlow::ContentSet c |
|
||||
DataFlowPrivate::readStep(node1, c, node2) and
|
||||
isRelevantContent(c) and
|
||||
isRelevantContent0(c) and
|
||||
state1.(TaintRead).getStep() + 1 = state2.(TaintRead).getStep()
|
||||
)
|
||||
}
|
||||
@@ -196,6 +225,9 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
|
||||
module PropagateFlow = TaintTracking::GlobalWithState<PropagateFlowConfig>;
|
||||
|
||||
/**
|
||||
* Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
|
||||
*/
|
||||
string captureThroughFlow0(
|
||||
DataFlowSummaryTargetApi api, DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt
|
||||
) {
|
||||
@@ -203,7 +235,7 @@ string captureThroughFlow0(
|
||||
p.getEnclosingCallable() = api and
|
||||
returnNodeExt.(DataFlow::Node).getEnclosingCallable() = api and
|
||||
input = parameterNodeAsInput(p) and
|
||||
output = returnNodeExt.getOutput() and
|
||||
output = getOutput(returnNodeExt) and
|
||||
input != output and
|
||||
result = Printing::asTaintModel(api, input, output)
|
||||
)
|
||||
@@ -219,6 +251,69 @@ string captureThroughFlow(DataFlowSummaryTargetApi api) {
|
||||
)
|
||||
}
|
||||
|
||||
private module PropagateContentFlowConfig implements ContentDataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source instanceof DataFlow::ParameterNode and
|
||||
source.getEnclosingCallable() instanceof DataFlowSummaryTargetApi
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
sink instanceof ReturnNodeExt and
|
||||
sink.getEnclosingCallable() instanceof DataFlowSummaryTargetApi
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep = isAdditionalContentFlowStep/2;
|
||||
|
||||
predicate isBarrier(DataFlow::Node n) {
|
||||
exists(Type t | t = n.getType() and not isRelevantType(t))
|
||||
}
|
||||
|
||||
int accessPathLimit() { result = 2 }
|
||||
|
||||
predicate isRelevantContent(DataFlow::ContentSet s) { isRelevantContent0(s) }
|
||||
|
||||
DataFlow::FlowFeature getAFeature() {
|
||||
result instanceof DataFlow::FeatureEqualSourceSinkCallContext
|
||||
}
|
||||
}
|
||||
|
||||
private module PropagateContentFlow = ContentDataFlow::Global<PropagateContentFlowConfig>;
|
||||
|
||||
private string getContent(PropagateContentFlow::AccessPath ap, int i) {
|
||||
exists(ContentSet head, PropagateContentFlow::AccessPath tail |
|
||||
head = ap.getHead() and
|
||||
tail = ap.getTail()
|
||||
|
|
||||
i = 0 and
|
||||
result = "." + printContent(head)
|
||||
or
|
||||
i > 0 and result = getContent(tail, i - 1)
|
||||
)
|
||||
}
|
||||
|
||||
private string printStoreAccessPath(PropagateContentFlow::AccessPath ap) {
|
||||
result = concat(int i | | getContent(ap, i), "" order by i)
|
||||
}
|
||||
|
||||
private string printReadAccessPath(PropagateContentFlow::AccessPath ap) {
|
||||
result = concat(int i | | getContent(ap, i), "" order by i desc)
|
||||
}
|
||||
|
||||
string captureContentFlow(DataFlowSummaryTargetApi api) {
|
||||
exists(
|
||||
DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt, string input, string output,
|
||||
PropagateContentFlow::AccessPath reads, PropagateContentFlow::AccessPath stores,
|
||||
boolean preservesValue
|
||||
|
|
||||
PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and
|
||||
returnNodeExt.getEnclosingCallable() = api and
|
||||
input = parameterNodeAsContentInput(p) + printReadAccessPath(reads) and
|
||||
output = getContentOutput(returnNodeExt) + printStoreAccessPath(stores) and
|
||||
input != output and
|
||||
result = Printing::asModel(api, input, output, preservesValue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A dataflow configuration used for finding new sources.
|
||||
* The sources are the already known existing sources and the sinks are the API return nodes.
|
||||
@@ -261,7 +356,7 @@ string captureSource(DataFlowSourceTargetApi api) {
|
||||
ExternalFlow::sourceNode(source, kind) and
|
||||
api = sink.getEnclosingCallable() and
|
||||
not irrelevantSourceSinkApi(source.getEnclosingCallable(), api) and
|
||||
result = Printing::asSourceModel(api, sink.getOutput(), kind)
|
||||
result = Printing::asSourceModel(api, getOutput(sink), kind)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
|
||||
private import java as J
|
||||
private import semmle.code.java.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.java.dataflow.internal.DataFlowUtil as DataFlowUtil
|
||||
private import semmle.code.java.dataflow.internal.ContainerFlow as ContainerFlow
|
||||
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
private import semmle.code.java.dataflow.internal.ModelExclusions
|
||||
private import semmle.code.java.dataflow.DataFlow as Df
|
||||
private import semmle.code.java.dataflow.internal.ContentDataFlow as Cdf
|
||||
private import semmle.code.java.dataflow.SSA as Ssa
|
||||
private import semmle.code.java.dataflow.TaintTracking as Tt
|
||||
import semmle.code.java.dataflow.ExternalFlow as ExternalFlow
|
||||
@@ -17,6 +19,8 @@ import semmle.code.java.dataflow.internal.DataFlowDispatch as DataFlowDispatch
|
||||
|
||||
module DataFlow = Df::DataFlow;
|
||||
|
||||
module ContentDataFlow = Cdf::ContentDataFlow;
|
||||
|
||||
module TaintTracking = Tt::TaintTracking;
|
||||
|
||||
class Type = J::Type;
|
||||
@@ -25,6 +29,8 @@ class Unit = J::Unit;
|
||||
|
||||
class Callable = J::Callable;
|
||||
|
||||
class ContentSet = DataFlowUtil::ContentSet;
|
||||
|
||||
private predicate isInfrequentlyUsed(J::CompilationUnit cu) {
|
||||
cu.getPackage().getName().matches("javax.swing%") or
|
||||
cu.getPackage().getName().matches("java.awt%")
|
||||
@@ -217,6 +223,12 @@ string parameterAccess(J::Parameter p) {
|
||||
else result = "Argument[" + p.getPosition() + "]"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the parameter `p`
|
||||
* when used in content flow.
|
||||
*/
|
||||
string parameterContentAccess(J::Parameter p) { result = "Argument[" + p.getPosition() + "]" }
|
||||
|
||||
class InstanceParameterNode = DataFlow::InstanceParameterNode;
|
||||
|
||||
class ParameterPosition = DataFlowDispatch::ParameterPosition;
|
||||
@@ -232,6 +244,17 @@ string paramReturnNodeAsOutput(Callable c, ParameterPosition pos) {
|
||||
result = qualifierString() and pos = -1
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of return through parameter at position
|
||||
* `pos` of callable `c` for content flow.
|
||||
*/
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsContentOutput(Callable c, ParameterPosition pos) {
|
||||
result = parameterContentAccess(c.getParameter(pos))
|
||||
or
|
||||
result = qualifierString() and pos = -1
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enclosing callable of `ret`.
|
||||
*/
|
||||
@@ -305,3 +328,34 @@ bindingset[kind]
|
||||
predicate isRelevantSourceKind(string kind) { any() }
|
||||
|
||||
predicate containerContent = DataFlowPrivate::containerContent/1;
|
||||
|
||||
/**
|
||||
* Holds if there is a taint step from `node1` to `node2` in content flow.
|
||||
*/
|
||||
predicate isAdditionalContentFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
TaintTracking::defaultAdditionalTaintStep(node1, node2, _) and
|
||||
not exists(DataFlow::Content f |
|
||||
DataFlowPrivate::readStep(node1, f, node2) and containerContent(f)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the contentset `c`.
|
||||
*/
|
||||
string printContent(ContentSet c) {
|
||||
exists(Field f, string name |
|
||||
f = c.(DataFlowUtil::FieldContent).getField() and name = f.getQualifiedName()
|
||||
|
|
||||
if f.isPublic() then result = "Field[" + name + "]" else result = "SyntheticField[" + name + "]"
|
||||
)
|
||||
or
|
||||
result = "SyntheticField[" + c.(DataFlowUtil::SyntheticFieldContent).getField() + "]"
|
||||
or
|
||||
c instanceof DataFlowUtil::CollectionContent and result = "Element"
|
||||
or
|
||||
c instanceof DataFlowUtil::ArrayContent and result = "ArrayElement"
|
||||
or
|
||||
c instanceof DataFlowUtil::MapValueContent and result = "MapValue"
|
||||
or
|
||||
c instanceof DataFlowUtil::MapKeyContent and result = "MapKey"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
unexpectedModel
|
||||
expectedModel
|
||||
@@ -0,0 +1,11 @@
|
||||
import java
|
||||
import utils.modelgenerator.internal.CaptureModels
|
||||
import TestUtilities.InlineMadTest
|
||||
|
||||
module InlineMadTestConfig implements InlineMadTestConfigSig {
|
||||
string getCapturedModel(Callable c) { result = captureContentFlow(c) }
|
||||
|
||||
string getKind() { result = "contentbased-summary" }
|
||||
}
|
||||
|
||||
import InlineMadTest<InlineMadTestConfig>
|
||||
@@ -2,16 +2,18 @@ package p;
|
||||
|
||||
public final class Factory {
|
||||
|
||||
private String value;
|
||||
public String value;
|
||||
|
||||
private int intValue;
|
||||
|
||||
// summary=p;Factory;false;create;(String,int);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Factory;false;create;(String,int);;Argument[0];ReturnValue.Field[p.Factory.value];value;df-generated
|
||||
public static Factory create(String value, int foo) {
|
||||
return new Factory(value, foo);
|
||||
}
|
||||
|
||||
// summary=p;Factory;false;create;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Factory;false;create;(String);;Argument[0];ReturnValue.Field[p.Factory.value];value;df-generated
|
||||
public static Factory create(String value) {
|
||||
return new Factory(value, 0);
|
||||
}
|
||||
@@ -22,6 +24,7 @@ public final class Factory {
|
||||
}
|
||||
|
||||
// summary=p;Factory;false;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Factory;false;getValue;();;Argument[this].Field[p.Factory.value];ReturnValue;value;df-generated
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ public final class FinalClass {
|
||||
private static final String C = "constant";
|
||||
|
||||
// summary=p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
public String returnsInput(String input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package p;
|
||||
public final class FluentAPI {
|
||||
|
||||
// summary=p;FluentAPI;false;returnsThis;(String);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;FluentAPI;false;returnsThis;(String);;Argument[this];ReturnValue;value;df-generated
|
||||
public FluentAPI returnsThis(String input) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -7,12 +7,14 @@ public final class ImmutablePojo {
|
||||
private final long x;
|
||||
|
||||
// summary=p;ImmutablePojo;false;ImmutablePojo;(String,int);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;ImmutablePojo;(String,int);;Argument[0];Argument[this].SyntheticField[p.ImmutablePojo.value];value;df-generated
|
||||
public ImmutablePojo(String value, int x) {
|
||||
this.value = value;
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
// summary=p;ImmutablePojo;false;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;getValue;();;Argument[this].SyntheticField[p.ImmutablePojo.value];ReturnValue;value;df-generated
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
@@ -24,6 +26,8 @@ public final class ImmutablePojo {
|
||||
|
||||
// summary=p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// summary=p;ImmutablePojo;false;or;(String);;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;or;(String);;Argument[this].SyntheticField[p.ImmutablePojo.value];ReturnValue;value;df-generated
|
||||
public String or(String defaultValue) {
|
||||
return value != null ? value : defaultValue;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ public class Inheritance {
|
||||
|
||||
public class AImplBasePrivateImpl extends BasePrivate {
|
||||
// summary=p;Inheritance$AImplBasePrivateImpl;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Inheritance$AImplBasePrivateImpl;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -19,6 +20,7 @@ public class Inheritance {
|
||||
|
||||
public class AImplBasePublic extends BasePublic {
|
||||
// summary=p;Inheritance$BasePublic;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Inheritance$BasePublic;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -59,6 +61,7 @@ public class Inheritance {
|
||||
|
||||
public class BImpl extends B {
|
||||
// summary=p;Inheritance$IPublic1;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Inheritance$IPublic1;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -67,6 +70,7 @@ public class Inheritance {
|
||||
|
||||
public class CImpl extends C {
|
||||
// summary=p;Inheritance$C;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Inheritance$C;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -75,6 +79,7 @@ public class Inheritance {
|
||||
|
||||
public class DImpl extends D {
|
||||
// summary=p;Inheritance$IPublic2;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Inheritance$IPublic2;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
@@ -83,6 +88,7 @@ public class Inheritance {
|
||||
|
||||
public class EImpl extends E {
|
||||
// summary=p;Inheritance$EImpl;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Inheritance$EImpl;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
return s;
|
||||
|
||||
@@ -10,12 +10,14 @@ public class InnerClasses {
|
||||
|
||||
public class CaptureMe {
|
||||
// summary=p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
public String yesCm(String input) {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
// summary=p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
public String yes(String input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -19,21 +19,25 @@ public final class InnerHolder {
|
||||
private StringBuilder sb = new StringBuilder();
|
||||
|
||||
// summary=p;InnerHolder;false;setContext;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;setContext;(String);;Argument[0];Argument[this].SyntheticField[p.InnerHolder.context].SyntheticField[p.InnerHolder$Context.value];value;df-generated
|
||||
public void setContext(String value) {
|
||||
context = new Context(value);
|
||||
}
|
||||
|
||||
// summary=p;InnerHolder;false;explicitSetContext;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;explicitSetContext;(String);;Argument[0];Argument[this].SyntheticField[p.InnerHolder.context].SyntheticField[p.InnerHolder$Context.value];value;df-generated
|
||||
public void explicitSetContext(String value) {
|
||||
this.context = new Context(value);
|
||||
}
|
||||
|
||||
// summary=p;InnerHolder;false;append;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;append;(String);;Argument[0];Argument[this].SyntheticField[p.InnerHolder.sb];taint;df-generated
|
||||
public void append(String value) {
|
||||
sb.append(value);
|
||||
}
|
||||
|
||||
// summary=p;InnerHolder;false;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;InnerHolder;false;getValue;();;Argument[this].SyntheticField[p.InnerHolder.context].SyntheticField[p.InnerHolder$Context.value];ReturnValue;value;df-generated
|
||||
public String getValue() {
|
||||
return context.getValue();
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ public final class Joiner {
|
||||
private String emptyValue;
|
||||
|
||||
// summary=p;Joiner;false;Joiner;(CharSequence);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;Joiner;false;Joiner;(CharSequence);;Argument[0];Argument[this].SyntheticField[p.Joiner.delimiter];taint;df-generated
|
||||
public Joiner(CharSequence delimiter) {
|
||||
this(delimiter, "", "");
|
||||
}
|
||||
@@ -20,6 +21,9 @@ public final class Joiner {
|
||||
// summary=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[this];taint;df-generated
|
||||
// summary=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[1];Argument[this];taint;df-generated
|
||||
// summary=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[2];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[this].SyntheticField[p.Joiner.delimiter];taint;df-generated
|
||||
// contentbased-summary=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[1];Argument[this].SyntheticField[p.Joiner.prefix];taint;df-generated
|
||||
// contentbased-summary=p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[2];Argument[this].SyntheticField[p.Joiner.suffix];taint;df-generated
|
||||
public Joiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix) {
|
||||
Objects.requireNonNull(prefix, "The prefix must not be null");
|
||||
Objects.requireNonNull(delimiter, "The delimiter must not be null");
|
||||
@@ -32,6 +36,9 @@ public final class Joiner {
|
||||
|
||||
// summary=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[0];Argument[this];taint;df-generated
|
||||
// summary=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[0];Argument[this].SyntheticField[p.Joiner.emptyValue];taint;df-generated
|
||||
// contentbased-summary=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[0];ReturnValue.SyntheticField[p.Joiner.emptyValue];taint;df-generated
|
||||
// contentbased-summary=p;Joiner;false;setEmptyValue;(CharSequence);;Argument[this];ReturnValue;value;df-generated
|
||||
public Joiner setEmptyValue(CharSequence emptyValue) {
|
||||
this.emptyValue =
|
||||
Objects.requireNonNull(emptyValue, "The empty value must not be null").toString();
|
||||
@@ -71,6 +78,8 @@ public final class Joiner {
|
||||
}
|
||||
|
||||
// summary=p;Joiner;false;add;(CharSequence);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Joiner;false;add;(CharSequence);;Argument[this].SyntheticField[p.Joiner.elts].ArrayElement;ReturnValue.SyntheticField[p.Joiner.elts].ArrayElement;value;df-generated
|
||||
// contentbased-summary=p;Joiner;false;add;(CharSequence);;Argument[this];ReturnValue;value;df-generated
|
||||
public Joiner add(CharSequence newElement) {
|
||||
final String elt = String.valueOf(newElement);
|
||||
if (elts == null) {
|
||||
@@ -94,6 +103,8 @@ public final class Joiner {
|
||||
}
|
||||
|
||||
// summary=p;Joiner;false;merge;(Joiner);;Argument[this];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Joiner;false;merge;(Joiner);;Argument[this].SyntheticField[p.Joiner.elts].ArrayElement;ReturnValue.SyntheticField[p.Joiner.elts].ArrayElement;value;df-generated
|
||||
// contentbased-summary=p;Joiner;false;merge;(Joiner);;Argument[this];ReturnValue;value;df-generated
|
||||
public Joiner merge(Joiner other) {
|
||||
Objects.requireNonNull(other);
|
||||
if (other.elts == null) {
|
||||
|
||||
@@ -17,6 +17,7 @@ class MultipleImpl2 {
|
||||
|
||||
public class Impl2 implements IInterface {
|
||||
// summary=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;value;df-generated
|
||||
public Object m(Object value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ public class MultipleImpls {
|
||||
|
||||
public static class Strat1 implements Strategy {
|
||||
// summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
public String doSomething(String value) {
|
||||
return value;
|
||||
}
|
||||
@@ -29,12 +30,18 @@ public class MultipleImpls {
|
||||
private String foo;
|
||||
|
||||
// summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// A field based model should not be lifted if the field pertains to the concrete
|
||||
// implementation.
|
||||
// SPURIOUS-contentbased-summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[this].SyntheticField[p.MultipleImpls$Strat2.foo];value;df-generated
|
||||
public String doSomething(String value) {
|
||||
this.foo = value;
|
||||
return "none";
|
||||
}
|
||||
|
||||
// summary=p;MultipleImpls$Strat2;true;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// A field based model should not be lifted if the field pertains to the concrete
|
||||
// implementation.
|
||||
// SPURIOUS-contentbased-summary=p;MultipleImpls$Strat2;true;getValue;();;Argument[this].SyntheticField[p.MultipleImpls$Strat2.foo];ReturnValue;value;df-generated
|
||||
public String getValue() {
|
||||
return this.foo;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.util.List;
|
||||
public class ParamFlow {
|
||||
|
||||
// summary=p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
public String returnsInput(String input) {
|
||||
return input;
|
||||
}
|
||||
@@ -19,6 +20,8 @@ public class ParamFlow {
|
||||
|
||||
// summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;value;df-generated
|
||||
public String returnMultipleParameters(String one, String two) {
|
||||
if (System.currentTimeMillis() > 100) {
|
||||
return two;
|
||||
@@ -27,26 +30,31 @@ public class ParamFlow {
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;returnArrayElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnArrayElement;(String[]);;Argument[0].ArrayElement;ReturnValue;value;df-generated
|
||||
public String returnArrayElement(String[] input) {
|
||||
return input[0];
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;returnVarArgElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnVarArgElement;(String[]);;Argument[0].ArrayElement;ReturnValue;value;df-generated
|
||||
public String returnVarArgElement(String... input) {
|
||||
return input[0];
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;returnCollectionElement;(List);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnCollectionElement;(List);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
public String returnCollectionElement(List<String> input) {
|
||||
return input.get(0);
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;returnIteratorElement;(Iterator);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnIteratorElement;(Iterator);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
public String returnIteratorElement(Iterator<String> input) {
|
||||
return input.next();
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;returnIterableElement;(Iterable);;Argument[0].Element;ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnIterableElement;(Iterable);;Argument[0].Element;ReturnValue;value;df-generated
|
||||
public String returnIterableElement(Iterable<String> input) {
|
||||
return input.iterator().next();
|
||||
}
|
||||
@@ -57,16 +65,19 @@ public class ParamFlow {
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint;df-generated
|
||||
public void writeChunked(byte[] data, OutputStream output) throws IOException {
|
||||
output.write(data, 0, data.length);
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;writeChunked;(char[],OutputStream);;Argument[0];Argument[1];taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;writeChunked;(char[],OutputStream);;Argument[0];Argument[1];taint;df-generated
|
||||
public void writeChunked(char[] data, OutputStream output) throws IOException {
|
||||
output.write(String.valueOf(data).getBytes(), 0, data.length);
|
||||
}
|
||||
|
||||
// summary=p;ParamFlow;true;addTo;(String,List);;Argument[0];Argument[1].Element;taint;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;addTo;(String,List);;Argument[0];Argument[1].Element;value;df-generated
|
||||
public void addTo(String data, List<String> target) {
|
||||
target.add(data);
|
||||
}
|
||||
|
||||
@@ -24,18 +24,20 @@ public final class Pojo {
|
||||
|
||||
private int intValue = 2;
|
||||
|
||||
private byte[] byteArray = new byte[] {1, 2, 3};
|
||||
public byte[] byteArray = new byte[] {1, 2, 3};
|
||||
private float[] floatArray = new float[] {1, 2, 3};
|
||||
private char[] charArray = new char[] {'a', 'b', 'c'};
|
||||
private List<Character> charList = Arrays.asList('a', 'b', 'c');
|
||||
private Byte[] byteObjectArray = new Byte[] {1, 2, 3};
|
||||
|
||||
// summary=p;Pojo;false;getValue;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getValue;();;Argument[this].SyntheticField[p.Pojo.value];ReturnValue;value;df-generated
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;setValue;(String);;Argument[0];Argument[this];taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;setValue;(String);;Argument[0];Argument[this].SyntheticField[p.Pojo.value];value;df-generated
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
@@ -62,11 +64,13 @@ public final class Pojo {
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;getCharArray;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getCharArray;();;Argument[this].SyntheticField[p.Pojo.charArray];ReturnValue;value;df-generated
|
||||
public char[] getCharArray() {
|
||||
return charArray;
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;getByteArray;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getByteArray;();;Argument[this].Field[p.Pojo.byteArray];ReturnValue;value;df-generated
|
||||
public byte[] getByteArray() {
|
||||
return byteArray;
|
||||
}
|
||||
@@ -87,11 +91,13 @@ public final class Pojo {
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;getBoxedChars;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getBoxedChars;();;Argument[this].SyntheticField[p.Pojo.charList];ReturnValue;value;df-generated
|
||||
public List<Character> getBoxedChars() {
|
||||
return charList;
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;getBoxedBytes;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;getBoxedBytes;();;Argument[this].SyntheticField[p.Pojo.byteObjectArray];ReturnValue;value;df-generated
|
||||
public Byte[] getBoxedBytes() {
|
||||
return byteObjectArray;
|
||||
}
|
||||
@@ -107,6 +113,7 @@ public final class Pojo {
|
||||
}
|
||||
|
||||
// summary=p;Pojo;false;fillIn;(List);;Argument[this];Argument[0].Element;taint;df-generated
|
||||
// contentbased-summary=p;Pojo;false;fillIn;(List);;Argument[this].SyntheticField[p.Pojo.value];Argument[0].Element;value;df-generated
|
||||
public void fillIn(List<String> target) {
|
||||
target.add(value);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@ public class PrivateFlowViaPublicInterface {
|
||||
}
|
||||
|
||||
// summary=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this];ReturnValue;taint;df-generated
|
||||
// A field based model should not be lifted if the field pertains to the concrete
|
||||
// implementation.
|
||||
// SPURIOUS-contentbased-summary=p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[this].SyntheticField[p.PrivateFlowViaPublicInterface$PrivateImplWithSink.file];ReturnValue;taint;df-generated
|
||||
@Override
|
||||
public OutputStream openStream() throws IOException {
|
||||
return new FileOutputStream(file);
|
||||
@@ -51,6 +54,9 @@ public class PrivateFlowViaPublicInterface {
|
||||
}
|
||||
|
||||
// summary=p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue;taint;df-generated
|
||||
// A field based model should not be lifted if the field pertains to the concrete
|
||||
// implementation.
|
||||
// SPURIOUS-contentbased-summary=p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue.SyntheticField[p.PrivateFlowViaPublicInterface$PrivateImplWithSink.file];value;df-generated
|
||||
public static SPI createAnSPI(File file) {
|
||||
return new PrivateImplWithSink(file);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ class Generator:
|
||||
self.generateSources = False
|
||||
self.generateSummaries = False
|
||||
self.generateNeutrals = False
|
||||
self.generateContentSummaries = False
|
||||
self.generateTypeBasedSummaries = False
|
||||
self.dryRun = False
|
||||
self.dirname = "modelgenerator"
|
||||
@@ -50,6 +51,7 @@ Which models are generated is controlled by the flags:
|
||||
--with-sources
|
||||
--with-summaries
|
||||
--with-neutrals
|
||||
--with-content-summaries (Experimental). May not be used in conjunction with --with-summaries
|
||||
--with-typebased-summaries (Experimental)
|
||||
If none of these flags are specified, all models are generated except for the type based models.
|
||||
|
||||
@@ -81,6 +83,10 @@ Requirements: `codeql` should both appear on your path.
|
||||
generator.printHelp()
|
||||
sys.exit(0)
|
||||
|
||||
if "--with-summaries" in sys.argv and "--with-content-summaries" in sys.argv:
|
||||
generator.printHelp()
|
||||
sys.exit(0)
|
||||
|
||||
if "--with-sinks" in sys.argv:
|
||||
sys.argv.remove("--with-sinks")
|
||||
generator.generateSinks = True
|
||||
@@ -97,6 +103,10 @@ Requirements: `codeql` should both appear on your path.
|
||||
sys.argv.remove("--with-neutrals")
|
||||
generator.generateNeutrals = True
|
||||
|
||||
if "--with-content-summaries" in sys.argv:
|
||||
sys.argv.remove("--with-content-summaries")
|
||||
generator.generateContentSummaries = True
|
||||
|
||||
if "--with-typebased-summaries" in sys.argv:
|
||||
sys.argv.remove("--with-typebased-summaries")
|
||||
generator.generateTypeBasedSummaries = True
|
||||
@@ -105,7 +115,7 @@ Requirements: `codeql` should both appear on your path.
|
||||
sys.argv.remove("--dry-run")
|
||||
generator.dryRun = True
|
||||
|
||||
if not generator.generateSinks and not generator.generateSources and not generator.generateSummaries and not generator.generateNeutrals and not generator.generateTypeBasedSummaries:
|
||||
if not generator.generateSinks and not generator.generateSources and not generator.generateSummaries and not generator.generateNeutrals and not generator.generateTypeBasedSummaries and not generator.generateContentSummaries:
|
||||
generator.generateSinks = generator.generateSources = generator.generateSummaries = generator.generateNeutrals = True
|
||||
|
||||
n = len(sys.argv)
|
||||
@@ -162,8 +172,13 @@ Requirements: `codeql` should both appear on your path.
|
||||
neutralAddsTo = self.getAddsTo("CaptureNeutralModels.ql", helpers.neutralModelPredicate)
|
||||
else:
|
||||
neutralAddsTo = { }
|
||||
|
||||
return helpers.merge(summaryAddsTo, sinkAddsTo, sourceAddsTo, neutralAddsTo)
|
||||
|
||||
if self.generateContentSummaries:
|
||||
contentSummaryAddsTo = self.getAddsTo("CaptureContentSummaryModels.ql", helpers.summaryModelPredicate)
|
||||
else:
|
||||
contentSummaryAddsTo = { }
|
||||
|
||||
return helpers.merge(summaryAddsTo, contentSummaryAddsTo, sinkAddsTo, sourceAddsTo, neutralAddsTo)
|
||||
|
||||
def makeTypeBasedContent(self):
|
||||
if self.generateTypeBasedSummaries:
|
||||
|
||||
@@ -41,7 +41,9 @@ module CleartextLogging {
|
||||
*/
|
||||
class SensitiveDataSourceAsSource extends Source, SensitiveDataSource {
|
||||
SensitiveDataSourceAsSource() {
|
||||
not SensitiveDataSource.super.getClassification() = SensitiveDataClassification::id()
|
||||
not SensitiveDataSource.super.getClassification() in [
|
||||
SensitiveDataClassification::id(), SensitiveDataClassification::certificate()
|
||||
]
|
||||
}
|
||||
|
||||
override SensitiveDataClassification getClassification() {
|
||||
|
||||
@@ -40,7 +40,9 @@ module CleartextStorage {
|
||||
*/
|
||||
class SensitiveDataSourceAsSource extends Source, SensitiveDataSource {
|
||||
SensitiveDataSourceAsSource() {
|
||||
not SensitiveDataSource.super.getClassification() = SensitiveDataClassification::id()
|
||||
not SensitiveDataSource.super.getClassification() in [
|
||||
SensitiveDataClassification::id(), SensitiveDataClassification::certificate()
|
||||
]
|
||||
}
|
||||
|
||||
override SensitiveDataClassification getClassification() {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `py/clear-text-logging-sensitive-data` and `py/clear-text-storage-sensitive-data` queries have been updated to exclude the `certificate` classification of sensitive sources, which often do not contain sensitive data.
|
||||
@@ -30,7 +30,6 @@ nodes
|
||||
| test.py:23:58:23:65 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
|
||||
| test.py:27:40:27:47 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
|
||||
| test.py:30:58:30:65 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
|
||||
| test.py:34:30:34:39 | ControlFlowNode for get_cert() | semmle.label | ControlFlowNode for get_cert() |
|
||||
| test.py:37:11:37:24 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
|
||||
| test.py:39:22:39:35 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
|
||||
| test.py:40:22:40:35 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
|
||||
@@ -73,7 +72,6 @@ subpaths
|
||||
| test.py:23:58:23:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:23:58:23:65 | ControlFlowNode for password | This expression logs $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | sensitive data (password) |
|
||||
| test.py:27:40:27:47 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:27:40:27:47 | ControlFlowNode for password | This expression logs $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | sensitive data (password) |
|
||||
| test.py:30:58:30:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:30:58:30:65 | ControlFlowNode for password | This expression logs $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | sensitive data (password) |
|
||||
| test.py:34:30:34:39 | ControlFlowNode for get_cert() | test.py:34:30:34:39 | ControlFlowNode for get_cert() | test.py:34:30:34:39 | ControlFlowNode for get_cert() | This expression logs $@ as clear text. | test.py:34:30:34:39 | ControlFlowNode for get_cert() | sensitive data (certificate) |
|
||||
| test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | This expression logs $@ as clear text. | test.py:37:11:37:24 | ControlFlowNode for get_password() | sensitive data (password) |
|
||||
| test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | This expression logs $@ as clear text. | test.py:39:22:39:35 | ControlFlowNode for get_password() | sensitive data (password) |
|
||||
| test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | This expression logs $@ as clear text. | test.py:40:22:40:35 | ControlFlowNode for get_password() | sensitive data (password) |
|
||||
|
||||
@@ -31,7 +31,7 @@ def log_password():
|
||||
|
||||
|
||||
def log_cert():
|
||||
logging.debug("Cert=%s", get_cert()) # NOT OK
|
||||
logging.debug("Cert=%s", get_cert()) # OK
|
||||
|
||||
def print_password():
|
||||
print(get_password()) # NOT OK
|
||||
@@ -52,8 +52,8 @@ def log_private():
|
||||
print(passportNo) # NOT OK
|
||||
|
||||
def log2(post_code, zipCode, home_address):
|
||||
print(post_code) # NOT OK, but NOT FOUND - "code" is treated as enxrypted and thus not sensitive
|
||||
print(zipCode) # NOT OK, but NOT FOUND - "code" is treated as enxrypted and thus not sensitive
|
||||
print(post_code) # NOT OK, but NOT FOUND - "code" is treated as encrypted and thus not sensitive
|
||||
print(zipCode) # NOT OK, but NOT FOUND - "code" is treated as encrypted and thus not sensitive
|
||||
print(home_address) # NOT OK
|
||||
|
||||
def log3(user_latitude, user_longitude):
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
edges
|
||||
| test.py:9:5:9:8 | ControlFlowNode for cert | test.py:12:21:12:24 | ControlFlowNode for cert | provenance | |
|
||||
| test.py:9:5:9:8 | ControlFlowNode for cert | test.py:13:22:13:41 | ControlFlowNode for Attribute() | provenance | |
|
||||
| test.py:9:5:9:8 | ControlFlowNode for cert | test.py:15:26:15:29 | ControlFlowNode for cert | provenance | |
|
||||
| test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:9:5:9:8 | ControlFlowNode for cert | provenance | |
|
||||
| test.py:9:5:9:12 | ControlFlowNode for password | test.py:12:21:12:28 | ControlFlowNode for password | provenance | |
|
||||
| test.py:9:5:9:12 | ControlFlowNode for password | test.py:13:22:13:45 | ControlFlowNode for Attribute() | provenance | |
|
||||
| test.py:9:5:9:12 | ControlFlowNode for password | test.py:15:26:15:33 | ControlFlowNode for password | provenance | |
|
||||
| test.py:9:16:9:29 | ControlFlowNode for get_password() | test.py:9:5:9:12 | ControlFlowNode for password | provenance | |
|
||||
nodes
|
||||
| test.py:9:5:9:8 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert |
|
||||
| test.py:9:12:9:21 | ControlFlowNode for get_cert() | semmle.label | ControlFlowNode for get_cert() |
|
||||
| test.py:12:21:12:24 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert |
|
||||
| test.py:13:22:13:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| test.py:15:26:15:29 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert |
|
||||
| test.py:9:5:9:12 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
|
||||
| test.py:9:16:9:29 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
|
||||
| test.py:12:21:12:28 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
|
||||
| test.py:13:22:13:45 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| test.py:15:26:15:33 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
|
||||
subpaths
|
||||
#select
|
||||
| test.py:12:21:12:24 | ControlFlowNode for cert | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:12:21:12:24 | ControlFlowNode for cert | This expression stores $@ as clear text. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | sensitive data (certificate) |
|
||||
| test.py:13:22:13:41 | ControlFlowNode for Attribute() | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:13:22:13:41 | ControlFlowNode for Attribute() | This expression stores $@ as clear text. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | sensitive data (certificate) |
|
||||
| test.py:15:26:15:29 | ControlFlowNode for cert | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:15:26:15:29 | ControlFlowNode for cert | This expression stores $@ as clear text. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | sensitive data (certificate) |
|
||||
| test.py:12:21:12:28 | ControlFlowNode for password | test.py:9:16:9:29 | ControlFlowNode for get_password() | test.py:12:21:12:28 | ControlFlowNode for password | This expression stores $@ as clear text. | test.py:9:16:9:29 | ControlFlowNode for get_password() | sensitive data (password) |
|
||||
| test.py:13:22:13:45 | ControlFlowNode for Attribute() | test.py:9:16:9:29 | ControlFlowNode for get_password() | test.py:13:22:13:45 | ControlFlowNode for Attribute() | This expression stores $@ as clear text. | test.py:9:16:9:29 | ControlFlowNode for get_password() | sensitive data (password) |
|
||||
| test.py:15:26:15:33 | ControlFlowNode for password | test.py:9:16:9:29 | ControlFlowNode for get_password() | test.py:15:26:15:33 | ControlFlowNode for password | This expression stores $@ as clear text. | test.py:9:16:9:29 | ControlFlowNode for get_password() | sensitive data (password) |
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import pathlib
|
||||
|
||||
|
||||
def get_cert():
|
||||
return "<CERT>"
|
||||
def get_password():
|
||||
return "password"
|
||||
|
||||
|
||||
def write_password(filename):
|
||||
cert = get_cert()
|
||||
password = get_password()
|
||||
|
||||
path = pathlib.Path(filename)
|
||||
path.write_text(cert) # NOT OK
|
||||
path.write_bytes(cert.encode("utf-8")) # NOT OK
|
||||
path.write_text(password) # NOT OK
|
||||
path.write_bytes(password.encode("utf-8")) # NOT OK
|
||||
|
||||
path.open("w").write(cert) # NOT OK
|
||||
path.open("w").write(password) # NOT OK
|
||||
|
||||
@@ -3,10 +3,10 @@ edges
|
||||
| password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | password_in_cookie.py:7:5:7:12 | ControlFlowNode for password | provenance | |
|
||||
| password_in_cookie.py:14:5:14:12 | ControlFlowNode for password | password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | provenance | |
|
||||
| password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | password_in_cookie.py:14:5:14:12 | ControlFlowNode for password | provenance | |
|
||||
| test.py:6:5:6:8 | ControlFlowNode for cert | test.py:8:20:8:23 | ControlFlowNode for cert | provenance | |
|
||||
| test.py:6:5:6:8 | ControlFlowNode for cert | test.py:9:9:9:13 | ControlFlowNode for lines | provenance | |
|
||||
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:6:5:6:8 | ControlFlowNode for cert | provenance | |
|
||||
| test.py:9:9:9:13 | ControlFlowNode for lines | test.py:10:25:10:29 | ControlFlowNode for lines | provenance | |
|
||||
| test.py:15:5:15:12 | ControlFlowNode for password | test.py:17:20:17:27 | ControlFlowNode for password | provenance | |
|
||||
| test.py:15:5:15:12 | ControlFlowNode for password | test.py:18:9:18:13 | ControlFlowNode for lines | provenance | |
|
||||
| test.py:15:16:15:29 | ControlFlowNode for get_password() | test.py:15:5:15:12 | ControlFlowNode for password | provenance | |
|
||||
| test.py:18:9:18:13 | ControlFlowNode for lines | test.py:19:25:19:29 | ControlFlowNode for lines | provenance | |
|
||||
nodes
|
||||
| password_in_cookie.py:7:5:7:12 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
|
||||
| password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
@@ -14,14 +14,14 @@ nodes
|
||||
| password_in_cookie.py:14:5:14:12 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
|
||||
| password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
|
||||
| password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
|
||||
| test.py:6:5:6:8 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert |
|
||||
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | semmle.label | ControlFlowNode for get_cert() |
|
||||
| test.py:8:20:8:23 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert |
|
||||
| test.py:9:9:9:13 | ControlFlowNode for lines | semmle.label | ControlFlowNode for lines |
|
||||
| test.py:10:25:10:29 | ControlFlowNode for lines | semmle.label | ControlFlowNode for lines |
|
||||
| test.py:15:5:15:12 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
|
||||
| test.py:15:16:15:29 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
|
||||
| test.py:17:20:17:27 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
|
||||
| test.py:18:9:18:13 | ControlFlowNode for lines | semmle.label | ControlFlowNode for lines |
|
||||
| test.py:19:25:19:29 | ControlFlowNode for lines | semmle.label | ControlFlowNode for lines |
|
||||
subpaths
|
||||
#select
|
||||
| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | This expression stores $@ as clear text. | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | sensitive data (password) |
|
||||
| password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | This expression stores $@ as clear text. | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | sensitive data (password) |
|
||||
| test.py:8:20:8:23 | ControlFlowNode for cert | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert | This expression stores $@ as clear text. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | sensitive data (certificate) |
|
||||
| test.py:10:25:10:29 | ControlFlowNode for lines | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:10:25:10:29 | ControlFlowNode for lines | This expression stores $@ as clear text. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | sensitive data (certificate) |
|
||||
| test.py:17:20:17:27 | ControlFlowNode for password | test.py:15:16:15:29 | ControlFlowNode for get_password() | test.py:17:20:17:27 | ControlFlowNode for password | This expression stores $@ as clear text. | test.py:15:16:15:29 | ControlFlowNode for get_password() | sensitive data (password) |
|
||||
| test.py:19:25:19:29 | ControlFlowNode for lines | test.py:15:16:15:29 | ControlFlowNode for get_password() | test.py:19:25:19:29 | ControlFlowNode for lines | This expression stores $@ as clear text. | test.py:15:16:15:29 | ControlFlowNode for get_password() | sensitive data (password) |
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
def get_cert():
|
||||
return "<CERT>"
|
||||
|
||||
def get_password():
|
||||
return "password"
|
||||
|
||||
def write_cert(filename):
|
||||
cert = get_cert()
|
||||
with open(filename, "w") as file:
|
||||
file.write(cert) # NOT OK
|
||||
file.write(cert) # OK
|
||||
lines = [cert + "\n"]
|
||||
file.writelines(lines) # OK
|
||||
|
||||
def write_password(filename):
|
||||
password = get_password()
|
||||
with open(filename, "w") as file:
|
||||
file.write(password) # NOT OK
|
||||
lines = [password + "\n"]
|
||||
file.writelines(lines) # NOT OK
|
||||
|
||||
def FPs():
|
||||
|
||||
@@ -90,6 +90,7 @@ impl TrapFile {
|
||||
let end_line = end.line as usize;
|
||||
let end_column = end.col as usize;
|
||||
let (ret, _) = self.writer.location_label(trap::Location {
|
||||
file_label,
|
||||
start_line,
|
||||
start_column,
|
||||
end_line,
|
||||
|
||||
@@ -97,6 +97,18 @@ module ModelPrintingImpl<ModelPrintingLangSig Lang> {
|
||||
result = asSummaryModel(api, input, output, "taint")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the summary model for `api` with `input` and `output`.
|
||||
*/
|
||||
bindingset[input, output, preservesValue]
|
||||
string asModel(Printing::SummaryApi api, string input, string output, boolean preservesValue) {
|
||||
preservesValue = true and
|
||||
result = asValueModel(api, input, output)
|
||||
or
|
||||
preservesValue = false and
|
||||
result = asTaintModel(api, input, output)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sink model for `api` with `input` and `kind`.
|
||||
*/
|
||||
|
||||
@@ -76,8 +76,8 @@ pub fn populate_empty_location(writer: &mut trap::Writer) {
|
||||
let file_label = populate_empty_file(writer);
|
||||
let loc_label = global_location(
|
||||
writer,
|
||||
file_label,
|
||||
trap::Location {
|
||||
file_label,
|
||||
start_line: 0,
|
||||
start_column: 0,
|
||||
end_line: 0,
|
||||
@@ -127,14 +127,10 @@ pub fn populate_parent_folders(
|
||||
}
|
||||
|
||||
/** Get the label for the given location, defining it a global ID if it doesn't exist yet. */
|
||||
fn global_location(
|
||||
writer: &mut trap::Writer,
|
||||
file_label: trap::Label,
|
||||
location: trap::Location,
|
||||
) -> trap::Label {
|
||||
fn global_location(writer: &mut trap::Writer, location: trap::Location) -> trap::Label {
|
||||
let (loc_label, fresh) = writer.global_id(&format!(
|
||||
"loc,{{{}}},{},{},{},{}",
|
||||
file_label,
|
||||
location.file_label,
|
||||
location.start_line,
|
||||
location.start_column,
|
||||
location.end_line,
|
||||
@@ -145,7 +141,7 @@ fn global_location(
|
||||
"locations_default",
|
||||
vec![
|
||||
trap::Arg::Label(loc_label),
|
||||
trap::Arg::Label(file_label),
|
||||
trap::Arg::Label(location.file_label),
|
||||
trap::Arg::Int(location.start_line),
|
||||
trap::Arg::Int(location.start_column),
|
||||
trap::Arg::Int(location.end_line),
|
||||
@@ -158,18 +154,14 @@ fn global_location(
|
||||
|
||||
/** Get the label for the given location, creating it as a fresh ID if we haven't seen the location
|
||||
* yet for this file. */
|
||||
fn location_label(
|
||||
writer: &mut trap::Writer,
|
||||
file_label: trap::Label,
|
||||
location: trap::Location,
|
||||
) -> trap::Label {
|
||||
fn location_label(writer: &mut trap::Writer, location: trap::Location) -> trap::Label {
|
||||
let (loc_label, fresh) = writer.location_label(location);
|
||||
if fresh {
|
||||
writer.add_tuple(
|
||||
"locations_default",
|
||||
vec![
|
||||
trap::Arg::Label(loc_label),
|
||||
trap::Arg::Label(file_label),
|
||||
trap::Arg::Label(location.file_label),
|
||||
trap::Arg::Int(location.start_line),
|
||||
trap::Arg::Int(location.start_column),
|
||||
trap::Arg::Int(location.end_line),
|
||||
@@ -312,8 +304,8 @@ impl<'a> Visitor<'a> {
|
||||
node: Node,
|
||||
status_page: bool,
|
||||
) {
|
||||
let loc = location_for(self, node);
|
||||
let loc_label = location_label(self.trap_writer, self.file_label, loc);
|
||||
let loc = location_for(self, self.file_label, node);
|
||||
let loc_label = location_label(self.trap_writer, loc);
|
||||
let mut mesg = self.diagnostics_writer.new_entry(
|
||||
"parse-error",
|
||||
"Could not process some files due to syntax errors",
|
||||
@@ -364,8 +356,8 @@ impl<'a> Visitor<'a> {
|
||||
return;
|
||||
}
|
||||
let (id, _, child_nodes) = self.stack.pop().expect("Vistor: empty stack");
|
||||
let loc = location_for(self, node);
|
||||
let loc_label = location_label(self.trap_writer, self.file_label, loc);
|
||||
let loc = location_for(self, self.file_label, node);
|
||||
let loc_label = location_label(self.trap_writer, loc);
|
||||
let table = self
|
||||
.schema
|
||||
.get(&TypeName {
|
||||
@@ -627,7 +619,7 @@ fn sliced_source_arg(source: &[u8], n: Node) -> trap::Arg {
|
||||
// Emit a pair of `TrapEntry`s for the provided node, appropriately calibrated.
|
||||
// The first is the location and label definition, and the second is the
|
||||
// 'Located' entry.
|
||||
fn location_for(visitor: &mut Visitor, n: Node) -> trap::Location {
|
||||
fn location_for(visitor: &mut Visitor, file_label: trap::Label, n: Node) -> trap::Location {
|
||||
// Tree-sitter row, column values are 0-based while CodeQL starts
|
||||
// counting at 1. In addition Tree-sitter's row and column for the
|
||||
// end position are exclusive while CodeQL's end positions are inclusive.
|
||||
@@ -685,6 +677,7 @@ fn location_for(visitor: &mut Visitor, n: Node) -> trap::Location {
|
||||
}
|
||||
}
|
||||
trap::Location {
|
||||
file_label,
|
||||
start_line,
|
||||
start_column,
|
||||
end_line,
|
||||
|
||||
@@ -7,6 +7,7 @@ use flate2::write::GzEncoder;
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
pub struct Location {
|
||||
pub file_label: Label,
|
||||
pub start_line: usize,
|
||||
pub start_column: usize,
|
||||
pub end_line: usize,
|
||||
@@ -136,7 +137,7 @@ impl fmt::Display for Entry {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||
// Identifiers of the form #0, #1...
|
||||
pub struct Label(u32);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user