mirror of
https://github.com/github/codeql.git
synced 2026-05-27 09:31:30 +02:00
Compare commits
10 Commits
jhelie/dev
...
experiment
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e567d2944b | ||
|
|
d5c2499f4f | ||
|
|
63c0d0701f | ||
|
|
da88b22aac | ||
|
|
9fa893367e | ||
|
|
2e6cecd2d6 | ||
|
|
04de75bcd0 | ||
|
|
8094ee7699 | ||
|
|
18306b36d3 | ||
|
|
c6ab4ff237 |
16
.github/workflows/ql-for-ql-build.yml
vendored
16
.github/workflows/ql-for-ql-build.yml
vendored
@@ -16,10 +16,9 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||
uses: github/codeql-action/init@erik-krogh/ql
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
tools: latest
|
||||
- name: Get CodeQL version
|
||||
id: get-codeql-version
|
||||
run: |
|
||||
@@ -160,7 +159,7 @@ jobs:
|
||||
PACK: ${{ runner.temp }}/pack
|
||||
- name: Hack codeql-action options
|
||||
run: |
|
||||
JSON=$(jq -nc --arg pack "${PACK}" '.database."run-queries"=["--search-path", $pack] | .resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
|
||||
JSON=$(jq -nc --arg pack "${PACK}" '.resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
|
||||
echo "CODEQL_ACTION_EXTRA_OPTIONS=${JSON}" >> ${GITHUB_ENV}
|
||||
env:
|
||||
PACK: ${{ runner.temp }}/pack
|
||||
@@ -172,25 +171,22 @@ jobs:
|
||||
echo "paths:" > ${CONF}
|
||||
echo " - ${FOLDER}" >> ${CONF}
|
||||
echo "paths-ignore:" >> ${CONF}
|
||||
echo " - ql/ql/test" >> ${CONF}
|
||||
echo "disable-default-queries: true" >> ${CONF}
|
||||
echo "packs:" >> ${CONF}
|
||||
echo " - codeql/ql" >> ${CONF}
|
||||
echo " - ql/ql/test" >> ${CONF}
|
||||
echo "Config file: "
|
||||
cat ${CONF}
|
||||
env:
|
||||
CONF: ./ql-for-ql-config.yml
|
||||
FOLDER: ${{ matrix.folder }}
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||
uses: github/codeql-action/init@erik-krogh/ql
|
||||
with:
|
||||
languages: ql
|
||||
db-location: ${{ runner.temp }}/db
|
||||
config-file: ./ql-for-ql-config.yml
|
||||
tools: latest
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||
uses: github/codeql-action/analyze@erik-krogh/ql
|
||||
with:
|
||||
category: "ql-for-ql-${{ matrix.folder }}"
|
||||
- name: Copy sarif file to CWD
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||
uses: github/codeql-action/init@erik-krogh/ql
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: actions/cache@v2
|
||||
|
||||
2
.github/workflows/ql-for-ql-tests.yml
vendored
2
.github/workflows/ql-for-ql-tests.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@aa93aea877e5fb8841bcb1193f672abf6e9f2980
|
||||
uses: github/codeql-action/init@erik-krogh/ql
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: actions/cache@v2
|
||||
|
||||
51
benjamin-button.md
Normal file
51
benjamin-button.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# benjamin-buttons.md
|
||||
|
||||
This file describes the changes that have been applied to
|
||||
the library to make it behave as if it was younger.
|
||||
|
||||
## TaintedPath.ql
|
||||
|
||||
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
|
||||
|
||||
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
|
||||
|
||||
Sinks added between 2018-08-02 and 2020-01-01 have been removed. Found by looking at:
|
||||
|
||||
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+pathinjection
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+tainted-path
|
||||
|
||||
Sinks from the "graceful-fs" and "fs-extra" (added before the open-sourcing squash).
|
||||
|
||||
## Xss.ql
|
||||
|
||||
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
|
||||
|
||||
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
|
||||
|
||||
- recursive type tracking for `jQuery::dollar`, `DOM::domValueRef`.
|
||||
|
||||
## SqlInjection.ql
|
||||
|
||||
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
|
||||
|
||||
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-089
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
|
||||
|
||||
Sinks added between 2018-08-02 and 2020-01-01 have been removed. Found by looking at:
|
||||
|
||||
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-089
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sql
|
||||
|
||||
TypeTracking in SQL.qll (added before the open-sourcing squash)
|
||||
|
||||
The model of `mssql` and `sequelize` (added before the open-sourcing squash)
|
||||
|
||||
## PseudoProperties
|
||||
|
||||
Pseudo-properties (`$name$`) used in type-tracking and global dataflow configurations have been disabled.
|
||||
Found by searching for `"\$.*\$"`.
|
||||
@@ -519,11 +519,6 @@
|
||||
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll"
|
||||
],
|
||||
"Concepts Python/Ruby/JS": [
|
||||
"python/ql/lib/semmle/python/internal/ConceptsShared.qll",
|
||||
"ruby/ql/lib/codeql/ruby/internal/ConceptsShared.qll",
|
||||
"javascript/ql/lib/semmle/javascript/internal/ConceptsShared.qll"
|
||||
],
|
||||
"Hostname Regexp queries": [
|
||||
"javascript/ql/src/Security/CWE-020/HostnameRegexpShared.qll",
|
||||
"python/ql/src/Security/CWE-020/HostnameRegexpShared.qll",
|
||||
@@ -549,4 +544,4 @@
|
||||
"javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/HttpToFileAccessCustomizations.qll"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -73,24 +73,8 @@ class Location extends @location {
|
||||
|
||||
/** Holds if `this` comes on a line strictly before `l`. */
|
||||
pragma[inline]
|
||||
predicate isBefore(Location l) { this.isBefore(l, false) }
|
||||
|
||||
/**
|
||||
* Holds if `this` comes strictly before `l`. The boolean `sameLine` is
|
||||
* true if `l` is on the same line as `this`, but starts at a later column.
|
||||
* Otherwise, `sameLine` is false.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate isBefore(Location l, boolean sameLine) {
|
||||
this.getFile() = l.getFile() and
|
||||
(
|
||||
sameLine = false and
|
||||
this.getEndLine() < l.getStartLine()
|
||||
or
|
||||
sameLine = true and
|
||||
this.getEndLine() = l.getStartLine() and
|
||||
this.getEndColumn() < l.getStartColumn()
|
||||
)
|
||||
predicate isBefore(Location l) {
|
||||
this.getFile() = l.getFile() and this.getEndLine() < l.getStartLine()
|
||||
}
|
||||
|
||||
/** Holds if location `l` is completely contained within this one. */
|
||||
|
||||
@@ -161,13 +161,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
this.getASuccessor() = result and
|
||||
not this.immediatelyDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.dominanceFrontier() |
|
||||
this.immediatelyDominates(prev) and
|
||||
not this.immediatelyDominates(result)
|
||||
)
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,13 +201,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postDominanceFrontier() {
|
||||
this.getAPredecessor() = result and
|
||||
not this.immediatelyPostDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.postDominanceFrontier() |
|
||||
this.immediatelyPostDominates(prev) and
|
||||
not this.immediatelyPostDominates(result)
|
||||
)
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -161,13 +161,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
this.getASuccessor() = result and
|
||||
not this.immediatelyDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.dominanceFrontier() |
|
||||
this.immediatelyDominates(prev) and
|
||||
not this.immediatelyDominates(result)
|
||||
)
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,13 +201,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postDominanceFrontier() {
|
||||
this.getAPredecessor() = result and
|
||||
not this.immediatelyPostDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.postDominanceFrontier() |
|
||||
this.immediatelyPostDominates(prev) and
|
||||
not this.immediatelyPostDominates(result)
|
||||
)
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -349,7 +349,7 @@ Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind ki
|
||||
|
||||
/** Holds if `goto` jumps strictly forward in the program text. */
|
||||
private predicate isStrictlyForwardGoto(GotoStmt goto) {
|
||||
goto.getLocation().isBefore(goto.getTarget().getLocation(), _)
|
||||
goto.getLocation().isBefore(goto.getTarget().getLocation())
|
||||
}
|
||||
|
||||
Locatable getInstructionAst(TStageInstruction instr) {
|
||||
|
||||
@@ -154,6 +154,13 @@ private predicate ignoreSideEffects(Expr expr) {
|
||||
* around extractor bugs. Once the relevant extractor bugs are fixed, this predicate can be removed.
|
||||
*/
|
||||
private predicate isInvalidFunction(Function func) {
|
||||
exists(Literal literal |
|
||||
// Constructor field inits within a compiler-generated copy constructor have a source expression
|
||||
// that is a `Literal` with no value.
|
||||
literal = func.(Constructor).getAnInitializer().(ConstructorFieldInit).getExpr() and
|
||||
not exists(literal.getValue())
|
||||
)
|
||||
or
|
||||
exists(ThisExpr thisExpr |
|
||||
// An instantiation of a member function template is not treated as a `MemberFunction` if it has
|
||||
// only non-type template arguments.
|
||||
|
||||
@@ -161,13 +161,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
this.getASuccessor() = result and
|
||||
not this.immediatelyDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.dominanceFrontier() |
|
||||
this.immediatelyDominates(prev) and
|
||||
not this.immediatelyDominates(result)
|
||||
)
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,13 +201,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postDominanceFrontier() {
|
||||
this.getAPredecessor() = result and
|
||||
not this.immediatelyPostDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.postDominanceFrontier() |
|
||||
this.immediatelyPostDominates(prev) and
|
||||
not this.immediatelyPostDominates(result)
|
||||
)
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -92,7 +92,6 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||
* snapshots there may be multiple results where we can't tell which is correct for a
|
||||
* particular function.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
Type getWideCharType() {
|
||||
result = getFormatCharType() and
|
||||
result.getSize() > 1
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @name Extraction errors
|
||||
* @description List all extraction errors for files in the source code directory.
|
||||
* @kind diagnostic
|
||||
* @id cpp/diagnostics/extraction-errors
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import ExtractionErrors
|
||||
|
||||
// NOTE:
|
||||
// This file looks like the other `diagnostics/extraction-errors` queries in other CodeQL supported
|
||||
// languages. However, since this diagnostic query is located in the `Internal` subdirectory it will not
|
||||
// appear in the Code Scanning suite. The related query `cpp/diagnostics/extraction-warnings` is,
|
||||
// however, included as a public diagnostics query.
|
||||
from ExtractionError error
|
||||
where
|
||||
error instanceof ExtractionUnknownError or
|
||||
exists(error.getFile().getRelativePath())
|
||||
select error, "Extraction failed in " + error.getFile() + " with error " + error.getErrorMessage(),
|
||||
error.getSeverity()
|
||||
@@ -1,137 +0,0 @@
|
||||
/**
|
||||
* Provides a common hierarchy of all types of errors that can occur during extraction.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
* A note about how the C/C++ extractor emits diagnostics:
|
||||
* When the extractor frontend encounters an error, it emits a diagnostic message,
|
||||
* that includes a message, location and severity.
|
||||
* However, that process is best-effort and may fail (e.g. due to lack of memory).
|
||||
* Thus, if the extractor emitted at least one diagnostic of severity discretionary
|
||||
* error (or higher), it *also* emits a simple "There was an error during this compilation"
|
||||
* error diagnostic, without location information.
|
||||
* In the common case, this means that a compilation during which one or more errors happened also gets
|
||||
* the catch-all diagnostic.
|
||||
* This diagnostic has the empty string as file path.
|
||||
* We filter out these useless diagnostics if there is at least one error-level diagnostic
|
||||
* for the affected compilation in the database.
|
||||
* Otherwise, we show it to indicate that something went wrong and that we
|
||||
* don't know what exactly happened.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An error that, if present, leads to a file being marked as non-successfully extracted.
|
||||
*/
|
||||
class ReportableError extends Diagnostic {
|
||||
ReportableError() {
|
||||
(
|
||||
this instanceof CompilerDiscretionaryError or
|
||||
this instanceof CompilerError or
|
||||
this instanceof CompilerCatastrophe
|
||||
) and
|
||||
// Filter for the catch-all diagnostic, see note above.
|
||||
not this.getFile().getAbsolutePath() = ""
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TExtractionError =
|
||||
TReportableError(ReportableError err) or
|
||||
TCompilationFailed(Compilation c, File f) {
|
||||
f = c.getAFileCompiled() and not c.normalTermination()
|
||||
} or
|
||||
// Show the catch-all diagnostic (see note above) only if we haven't seen any other error-level diagnostic
|
||||
// for that compilation
|
||||
TUnknownError(CompilerError err) {
|
||||
not exists(ReportableError e | e.getCompilation() = err.getCompilation())
|
||||
}
|
||||
|
||||
/**
|
||||
* Superclass for the extraction error hierarchy.
|
||||
*/
|
||||
class ExtractionError extends TExtractionError {
|
||||
/** Gets the string representation of the error. */
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the error message for this error. */
|
||||
string getErrorMessage() { none() }
|
||||
|
||||
/** Gets the file this error occured in. */
|
||||
File getFile() { none() }
|
||||
|
||||
/** Gets the location this error occured in. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
/** Gets the SARIF severity of this error. */
|
||||
int getSeverity() {
|
||||
// Unfortunately, we can't distinguish between errors and fatal errors in SARIF,
|
||||
// so all errors have severity 2.
|
||||
result = 2
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An unrecoverable extraction error, where extraction was unable to finish.
|
||||
* This can be caused by a multitude of reasons, for example:
|
||||
* - hitting a frontend assertion
|
||||
* - crashing due to dereferencing an invalid pointer
|
||||
* - stack overflow
|
||||
* - out of memory
|
||||
*/
|
||||
class ExtractionUnrecoverableError extends ExtractionError, TCompilationFailed {
|
||||
Compilation c;
|
||||
File f;
|
||||
|
||||
ExtractionUnrecoverableError() { this = TCompilationFailed(c, f) }
|
||||
|
||||
override string toString() {
|
||||
result = "Unrecoverable extraction error while compiling " + f.toString()
|
||||
}
|
||||
|
||||
override string getErrorMessage() { result = "unrecoverable compilation failure." }
|
||||
|
||||
override File getFile() { result = f }
|
||||
|
||||
override Location getLocation() { result = f.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A recoverable extraction error.
|
||||
* These are compiler errors from the frontend.
|
||||
* Upon encountering one of these, we still continue extraction, but the
|
||||
* database will be incomplete for that file.
|
||||
*/
|
||||
class ExtractionRecoverableError extends ExtractionError, TReportableError {
|
||||
ReportableError err;
|
||||
|
||||
ExtractionRecoverableError() { this = TReportableError(err) }
|
||||
|
||||
override string toString() { result = "Recoverable extraction error: " + err }
|
||||
|
||||
override string getErrorMessage() { result = err.getFullMessage() }
|
||||
|
||||
override File getFile() { result = err.getFile() }
|
||||
|
||||
override Location getLocation() { result = err.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An unknown error happened during extraction.
|
||||
* These are only displayed if we know that we encountered an error during extraction,
|
||||
* but, for some reason, failed to emit a proper diagnostic with location information
|
||||
* and error message.
|
||||
*/
|
||||
class ExtractionUnknownError extends ExtractionError, TUnknownError {
|
||||
CompilerError err;
|
||||
|
||||
ExtractionUnknownError() { this = TUnknownError(err) }
|
||||
|
||||
override string toString() { result = "Unknown extraction error: " + err }
|
||||
|
||||
override string getErrorMessage() { result = err.getFullMessage() }
|
||||
|
||||
override File getFile() { result = err.getFile() }
|
||||
|
||||
override Location getLocation() { result = err.getLocation() }
|
||||
}
|
||||
@@ -19,9 +19,9 @@ import semmle.code.cpp.security.Security
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking2
|
||||
import semmle.code.cpp.security.FlowSources
|
||||
import semmle.code.cpp.models.implementations.Strcat
|
||||
import DataFlow::PathGraph
|
||||
|
||||
Expr sinkAsArgumentIndirection(DataFlow::Node sink) {
|
||||
result =
|
||||
@@ -66,70 +66,154 @@ predicate interestingConcatenation(DataFlow::Node fst, DataFlow::Node snd) {
|
||||
)
|
||||
}
|
||||
|
||||
class ConcatState extends DataFlow::FlowState {
|
||||
ConcatState() { this = "ConcatState" }
|
||||
}
|
||||
class TaintToConcatenationConfiguration extends TaintTracking::Configuration {
|
||||
TaintToConcatenationConfiguration() { this = "TaintToConcatenationConfiguration" }
|
||||
|
||||
class ExecState extends DataFlow::FlowState {
|
||||
DataFlow::Node fst;
|
||||
DataFlow::Node snd;
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||
|
||||
ExecState() {
|
||||
this =
|
||||
"ExecState (" + fst.getLocation() + " | " + fst + ", " + snd.getLocation() + " | " + snd + ")" and
|
||||
interestingConcatenation(fst, snd)
|
||||
override predicate isSink(DataFlow::Node sink) { interestingConcatenation(sink, _) }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
node.asInstruction().getResultType() instanceof IntegralType
|
||||
or
|
||||
node.asInstruction().getResultType() instanceof FloatingPointType
|
||||
}
|
||||
|
||||
DataFlow::Node getFstNode() { result = fst }
|
||||
|
||||
DataFlow::Node getSndNode() { result = snd }
|
||||
}
|
||||
|
||||
class ExecTaintConfiguration extends TaintTracking::Configuration {
|
||||
class ExecTaintConfiguration extends TaintTracking2::Configuration {
|
||||
ExecTaintConfiguration() { this = "ExecTaintConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
|
||||
source instanceof FlowSource and
|
||||
state instanceof ConcatState
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
exists(DataFlow::Node prevSink, TaintToConcatenationConfiguration conf |
|
||||
conf.hasFlow(_, prevSink) and
|
||||
interestingConcatenation(prevSink, source)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
|
||||
shellCommand(sinkAsArgumentIndirection(sink), _) and
|
||||
state instanceof ExecState
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
shellCommand(sinkAsArgumentIndirection(sink), _)
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
state1 instanceof ConcatState and
|
||||
state2.(ExecState).getFstNode() = node1 and
|
||||
state2.(ExecState).getSndNode() = node2
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
(
|
||||
node.asInstruction().getResultType() instanceof IntegralType
|
||||
or
|
||||
node.asInstruction().getResultType() instanceof FloatingPointType
|
||||
) and
|
||||
state instanceof ConcatState
|
||||
}
|
||||
|
||||
override predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
isSink(node, state) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
|
||||
override predicate isSanitizerOut(DataFlow::Node node) {
|
||||
isSink(node) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers
|
||||
}
|
||||
}
|
||||
|
||||
module StitchedPathGraph {
|
||||
// There's a different PathNode class for each DataFlowImplN.qll, so we can't simply combine the
|
||||
// PathGraph predicates directly. Instead, we use a newtype so there's a single type that
|
||||
// contains both sets of PathNodes.
|
||||
newtype TMergedPathNode =
|
||||
TPathNode1(DataFlow::PathNode node) or
|
||||
TPathNode2(DataFlow2::PathNode node)
|
||||
|
||||
// this wraps the toString and location predicates so we can use the merged node type in a
|
||||
// selection
|
||||
class MergedPathNode extends TMergedPathNode {
|
||||
string toString() {
|
||||
exists(DataFlow::PathNode n |
|
||||
this = TPathNode1(n) and
|
||||
result = n.toString()
|
||||
)
|
||||
or
|
||||
exists(DataFlow2::PathNode n |
|
||||
this = TPathNode2(n) and
|
||||
result = n.toString()
|
||||
)
|
||||
}
|
||||
|
||||
DataFlow::Node getNode() {
|
||||
exists(DataFlow::PathNode n |
|
||||
this = TPathNode1(n) and
|
||||
result = n.getNode()
|
||||
)
|
||||
or
|
||||
exists(DataFlow2::PathNode n |
|
||||
this = TPathNode2(n) and
|
||||
result = n.getNode()
|
||||
)
|
||||
}
|
||||
|
||||
DataFlow::PathNode getPathNode1() { this = TPathNode1(result) }
|
||||
|
||||
DataFlow2::PathNode getPathNode2() { this = TPathNode2(result) }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
exists(DataFlow::PathNode n |
|
||||
this = TPathNode1(n) and
|
||||
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
)
|
||||
or
|
||||
exists(DataFlow2::PathNode n |
|
||||
this = TPathNode2(n) and
|
||||
n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
query predicate edges(MergedPathNode a, MergedPathNode b) {
|
||||
exists(DataFlow::PathNode an, DataFlow::PathNode bn |
|
||||
a = TPathNode1(an) and
|
||||
b = TPathNode1(bn) and
|
||||
DataFlow::PathGraph::edges(an, bn)
|
||||
)
|
||||
or
|
||||
exists(DataFlow2::PathNode an, DataFlow2::PathNode bn |
|
||||
a = TPathNode2(an) and
|
||||
b = TPathNode2(bn) and
|
||||
DataFlow2::PathGraph::edges(an, bn)
|
||||
)
|
||||
or
|
||||
// This is where paths from the two configurations are connected. `interestingConcatenation`
|
||||
// is the only thing in this module that's actually specific to the query - everything else is
|
||||
// just using types and predicates from the DataFlow library.
|
||||
interestingConcatenation(a.getNode(), b.getNode()) and
|
||||
a instanceof TPathNode1 and
|
||||
b instanceof TPathNode2
|
||||
}
|
||||
|
||||
query predicate nodes(MergedPathNode mpn, string key, string val) {
|
||||
// here we just need the union of the underlying `nodes` predicates
|
||||
exists(DataFlow::PathNode n |
|
||||
mpn = TPathNode1(n) and
|
||||
DataFlow::PathGraph::nodes(n, key, val)
|
||||
)
|
||||
or
|
||||
exists(DataFlow2::PathNode n |
|
||||
mpn = TPathNode2(n) and
|
||||
DataFlow2::PathGraph::nodes(n, key, val)
|
||||
)
|
||||
}
|
||||
|
||||
query predicate subpaths(
|
||||
MergedPathNode arg, MergedPathNode par, MergedPathNode ret, MergedPathNode out
|
||||
) {
|
||||
// just forward subpaths from the underlying libraries. This might be slightly awkward when
|
||||
// the concatenation is deep in a call chain.
|
||||
DataFlow::PathGraph::subpaths(arg.getPathNode1(), par.getPathNode1(), ret.getPathNode1(),
|
||||
out.getPathNode1())
|
||||
or
|
||||
DataFlow2::PathGraph::subpaths(arg.getPathNode2(), par.getPathNode2(), ret.getPathNode2(),
|
||||
out.getPathNode2())
|
||||
}
|
||||
}
|
||||
|
||||
import StitchedPathGraph
|
||||
|
||||
from
|
||||
ExecTaintConfiguration conf, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode,
|
||||
string taintCause, string callChain, DataFlow::Node concatResult
|
||||
DataFlow::PathNode sourceNode, DataFlow::PathNode concatSink, DataFlow2::PathNode concatSource,
|
||||
DataFlow2::PathNode sinkNode, string taintCause, string callChain,
|
||||
TaintToConcatenationConfiguration conf1, ExecTaintConfiguration conf2
|
||||
where
|
||||
conf.hasFlowPath(sourceNode, sinkNode) and
|
||||
taintCause = sourceNode.getNode().(FlowSource).getSourceType() and
|
||||
shellCommand(sinkAsArgumentIndirection(sinkNode.getNode()), callChain) and
|
||||
concatResult = sinkNode.getState().(ExecState).getSndNode()
|
||||
select sinkAsArgumentIndirection(sinkNode.getNode()), sourceNode, sinkNode,
|
||||
conf1.hasFlowPath(sourceNode, concatSink) and
|
||||
interestingConcatenation(concatSink.getNode(), concatSource.getNode()) and // this loses call context
|
||||
conf2.hasFlowPath(concatSource, sinkNode) and
|
||||
shellCommand(sinkAsArgumentIndirection(sinkNode.getNode()), callChain)
|
||||
select sinkAsArgumentIndirection(sinkNode.getNode()), TPathNode1(sourceNode).(MergedPathNode),
|
||||
TPathNode2(sinkNode).(MergedPathNode),
|
||||
"This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to "
|
||||
+ callChain, sourceNode, "user input (" + taintCause + ")", concatResult,
|
||||
concatResult.toString()
|
||||
+ callChain, sourceNode, "user input (" + taintCause + ")", concatSource,
|
||||
concatSource.toString()
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Exposing system data or debugging information may help a malicious user learn about the system and form an attack plan. An attacker can use error messages that reveal technologies, operating systems, and product versions to tune their attack against known vulnerabilities in the software.</p>
|
||||
<p>Exposing system data or debugging information may help an adversary to learn about the system and form an attack plan. An attacker can use error messages that reveal technologies, operating systems, and product versions to tune their attack against known vulnerabilities in these technologies.</p>
|
||||
|
||||
<p>This query finds locations where system configuration information might be revealed to a remote user.</p>
|
||||
<p>This query finds locations where system configuration information might be revealed to a user.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>Do not expose system configuration information to remote users. Be wary of the difference between information that could be helpful to users, and unnecessary details that could be useful to a malicious user.</p>
|
||||
<p>Do not expose system configuration information to users. Be wary of the difference between information that could be helpful to users, and unnecessary details that could be useful to an adversary.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In this example the value of the <code>PATH</code> environment variable is revealed in full to the user when a particular error occurs. This might reveal information such as the software installed on your system to a malicious user who does not have legitimate access to that information.</p>
|
||||
<p>In this example the value of the <code>PATH</code> environment variable is revealed in full to the user when a particular error occurs. This might reveal information such as the software installed on your system to an adversary who does not have legitimate access to that information.</p>
|
||||
|
||||
<sample src="ExposedSystemDataIncorrect.cpp" />
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @name Exposure of system data to an unauthorized control sphere
|
||||
* @description Exposing system data or debugging information helps
|
||||
* a malicious user learn about the system and form an
|
||||
* an adversary learn about the system and form an
|
||||
* attack plan.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
@@ -13,15 +13,284 @@
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Environment
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import DataFlow::PathGraph
|
||||
import SystemData
|
||||
|
||||
/**
|
||||
* An element that should not be exposed to an adversary.
|
||||
*/
|
||||
abstract class SystemData extends Element {
|
||||
/**
|
||||
* Gets an expression that is part of this `SystemData`.
|
||||
*/
|
||||
abstract Expr getAnExpr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data originating from the environment.
|
||||
*/
|
||||
class EnvData extends SystemData {
|
||||
EnvData() {
|
||||
// identify risky looking environment variables only
|
||||
this.(EnvironmentRead)
|
||||
.getEnvironmentVariable()
|
||||
.toLowerCase()
|
||||
.regexpMatch(".*(user|host|admin|root|home|path|http|ssl|snmp|sock|port|proxy|pass|token|crypt|key).*")
|
||||
}
|
||||
|
||||
override Expr getAnExpr() { result = this }
|
||||
}
|
||||
|
||||
/**
|
||||
* Data originating from a call to `mysql_get_client_info()`.
|
||||
*/
|
||||
class SqlClientInfo extends SystemData {
|
||||
SqlClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") }
|
||||
|
||||
override Expr getAnExpr() { result = this }
|
||||
}
|
||||
|
||||
private predicate sqlConnectInfo(FunctionCall source, VariableAccess use) {
|
||||
(
|
||||
source.getTarget().hasName("mysql_connect") or
|
||||
source.getTarget().hasName("mysql_real_connect")
|
||||
) and
|
||||
use = source.getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed into an SQL connect function.
|
||||
*/
|
||||
class SqlConnectInfo extends SystemData {
|
||||
SqlConnectInfo() { sqlConnectInfo(this, _) }
|
||||
|
||||
override Expr getAnExpr() { sqlConnectInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate posixSystemInfo(FunctionCall source, Element use) {
|
||||
// size_t confstr(int name, char *buf, size_t len)
|
||||
// - various OS / system strings, such as the libc version
|
||||
// int statvfs(const char *__path, struct statvfs *__buf)
|
||||
// int fstatvfs(int __fd, struct statvfs *__buf)
|
||||
// - various filesystem parameters
|
||||
// int uname(struct utsname *buf)
|
||||
// - OS name and version
|
||||
source.getTarget().hasName(["confstr", "statvfs", "fstatvfs", "uname"]) and
|
||||
use = source.getArgument(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a POSIX system information call.
|
||||
*/
|
||||
class PosixSystemInfo extends SystemData {
|
||||
PosixSystemInfo() { posixSystemInfo(this, _) }
|
||||
|
||||
override Expr getAnExpr() { posixSystemInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate posixPWInfo(FunctionCall source, Element use) {
|
||||
// struct passwd *getpwnam(const char *name);
|
||||
// struct passwd *getpwuid(uid_t uid);
|
||||
// struct passwd *getpwent(void);
|
||||
// struct group *getgrnam(const char *name);
|
||||
// struct group *getgrgid(gid_t);
|
||||
// struct group *getgrent(void);
|
||||
source
|
||||
.getTarget()
|
||||
.hasName(["getpwnam", "getpwuid", "getpwent", "getgrnam", "getgrgid", "getgrent"]) and
|
||||
use = source
|
||||
or
|
||||
// int getpwnam_r(const char *name, struct passwd *pwd,
|
||||
// char *buf, size_t buflen, struct passwd **result);
|
||||
// int getpwuid_r(uid_t uid, struct passwd *pwd,
|
||||
// char *buf, size_t buflen, struct passwd **result);
|
||||
// int getgrgid_r(gid_t gid, struct group *grp,
|
||||
// char *buf, size_t buflen, struct group **result);
|
||||
// int getgrnam_r(const char *name, struct group *grp,
|
||||
// char *buf, size_t buflen, struct group **result);
|
||||
source.getTarget().hasName(["getpwnam_r", "getpwuid_r", "getgrgid_r", "getgrnam_r"]) and
|
||||
use = source.getArgument([1, 2, 4])
|
||||
or
|
||||
// int getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize,
|
||||
// struct passwd **result);
|
||||
// int getgrent_r(struct group *gbuf, char *buf,
|
||||
// size_t buflen, struct group **gbufp);
|
||||
source.getTarget().hasName(["getpwent_r", "getgrent_r"]) and
|
||||
use = source.getArgument([0, 1, 3])
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a POSIX user/password/group database information call.
|
||||
*/
|
||||
class PosixPWInfo extends SystemData {
|
||||
PosixPWInfo() { posixPWInfo(this, _) }
|
||||
|
||||
override Expr getAnExpr() { posixPWInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate windowsSystemInfo(FunctionCall source, Element use) {
|
||||
// DWORD WINAPI GetVersion(void);
|
||||
source.getTarget().hasGlobalName("GetVersion") and
|
||||
use = source
|
||||
or
|
||||
// BOOL WINAPI GetVersionEx(_Inout_ LPOSVERSIONINFO lpVersionInfo);
|
||||
// void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
|
||||
// void WINAPI GetNativeSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"GetVersionEx", "GetVersionExA", "GetVersionExW", "GetSystemInfo", "GetNativeSystemInfo"
|
||||
]) and
|
||||
use = source.getArgument(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a Windows system information call.
|
||||
*/
|
||||
class WindowsSystemInfo extends SystemData {
|
||||
WindowsSystemInfo() { windowsSystemInfo(this, _) }
|
||||
|
||||
override Expr getAnExpr() { windowsSystemInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate windowsFolderPath(FunctionCall source, Element use) {
|
||||
// BOOL SHGetSpecialFolderPath(
|
||||
// HWND hwndOwner,
|
||||
// _Out_ LPTSTR lpszPath,
|
||||
// _In_ int csidl,
|
||||
// _In_ BOOL fCreate
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"SHGetSpecialFolderPath", "SHGetSpecialFolderPathA", "SHGetSpecialFolderPathW"
|
||||
]) and
|
||||
use = source.getArgument(1)
|
||||
or
|
||||
// HRESULT SHGetKnownFolderPath(
|
||||
// _In_ REFKNOWNFOLDERID rfid,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _In_opt_ HANDLE hToken,
|
||||
// _Out_ PWSTR *ppszPath
|
||||
// );
|
||||
source.getTarget().hasGlobalName("SHGetKnownFolderPath") and
|
||||
use = source.getArgument(3)
|
||||
or
|
||||
// HRESULT SHGetFolderPath(
|
||||
// _In_ HWND hwndOwner,
|
||||
// _In_ int nFolder,
|
||||
// _In_ HANDLE hToken,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _Out_ LPTSTR pszPath
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["SHGetFolderPath", "SHGetFolderPathA", "SHGetFolderPathW"]) and
|
||||
use = source.getArgument(4)
|
||||
or
|
||||
// HRESULT SHGetFolderPathAndSubDir(
|
||||
// _In_ HWND hwnd,
|
||||
// _In_ int csidl,
|
||||
// _In_ HANDLE hToken,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _In_ LPCTSTR pszSubDir,
|
||||
// _Out_ LPTSTR pszPath
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"SHGetFolderPathAndSubDir", "SHGetFolderPathAndSubDirA", "SHGetFolderPathAndSubDirW"
|
||||
]) and
|
||||
use = source.getArgument(5)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained about Windows special paths (for example, the
|
||||
* location of `System32`).
|
||||
*/
|
||||
class WindowsFolderPath extends SystemData {
|
||||
WindowsFolderPath() { windowsFolderPath(this, _) }
|
||||
|
||||
override Expr getAnExpr() { windowsFolderPath(this, result) }
|
||||
}
|
||||
|
||||
private predicate logonUser(FunctionCall source, VariableAccess use) {
|
||||
source.getTarget().hasGlobalName(["LogonUser", "LogonUserW", "LogonUserA"]) and
|
||||
use = source.getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed into a `LogonUser` (Windows) function.
|
||||
*/
|
||||
class LogonUser extends SystemData {
|
||||
LogonUser() { logonUser(this, _) }
|
||||
|
||||
override Expr getAnExpr() { logonUser(this, result) }
|
||||
}
|
||||
|
||||
private predicate regQuery(FunctionCall source, VariableAccess use) {
|
||||
// LONG WINAPI RegQueryValue(
|
||||
// _In_ HKEY hKey,
|
||||
// _In_opt_ LPCTSTR lpSubKey,
|
||||
// _Out_opt_ LPTSTR lpValue,
|
||||
// _Inout_opt_ PLONG lpcbValue
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegQueryValue", "RegQueryValueA", "RegQueryValueW"]) and
|
||||
use = source.getArgument(2)
|
||||
or
|
||||
// LONG WINAPI RegQueryMultipleValues(
|
||||
// _In_ HKEY hKey,
|
||||
// _Out_ PVALENT val_list,
|
||||
// _In_ DWORD num_vals,
|
||||
// _Out_opt_ LPTSTR lpValueBuf,
|
||||
// _Inout_opt_ LPDWORD ldwTotsize
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"RegQueryMultipleValues", "RegQueryMultipleValuesA", "RegQueryMultipleValuesW"
|
||||
]) and
|
||||
use = source.getArgument(3)
|
||||
or
|
||||
// LONG WINAPI RegQueryValueEx(
|
||||
// _In_ HKEY hKey,
|
||||
// _In_opt_ LPCTSTR lpValueName,
|
||||
// _Reserved_ LPDWORD lpReserved,
|
||||
// _Out_opt_ LPDWORD lpType,
|
||||
// _Out_opt_ LPBYTE lpData,
|
||||
// _Inout_opt_ LPDWORD lpcbData
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegQueryValueEx", "RegQueryValueExA", "RegQueryValueExW"]) and
|
||||
use = source.getArgument(4)
|
||||
or
|
||||
// LONG WINAPI RegGetValue(
|
||||
// _In_ HKEY hkey,
|
||||
// _In_opt_ LPCTSTR lpSubKey,
|
||||
// _In_opt_ LPCTSTR lpValue,
|
||||
// _In_opt_ DWORD dwFlags,
|
||||
// _Out_opt_ LPDWORD pdwType,
|
||||
// _Out_opt_ PVOID pvData,
|
||||
// _Inout_opt_ LPDWORD pcbData
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegGetValue", "RegGetValueA", "RegGetValueW"]) and
|
||||
use = source.getArgument(5)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data read from the Windows registry.
|
||||
*/
|
||||
class RegQuery extends SystemData {
|
||||
RegQuery() { regQuery(this, _) }
|
||||
|
||||
override Expr getAnExpr() { regQuery(this, result) }
|
||||
}
|
||||
|
||||
class ExposedSystemDataConfiguration extends TaintTracking::Configuration {
|
||||
ExposedSystemDataConfiguration() { this = "ExposedSystemDataConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source = any(SystemData sd).getAnExpr() }
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asConvertedExpr() = any(SystemData sd).getAnExpr()
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall fc, FunctionInput input, int arg |
|
||||
|
||||
@@ -2,5 +2,6 @@ char* path = getenv("PATH");
|
||||
|
||||
//...
|
||||
|
||||
message = "An internal error has occurred. Please try again or contact a system administrator.\n";
|
||||
send(socket, message, strlen(message), 0);
|
||||
fprintf(stderr, "A required executable file could not be found. " \
|
||||
"Please ensure that the software has been installed " \
|
||||
"correctly or contact a system administrator.\n");
|
||||
@@ -2,5 +2,4 @@ char* path = getenv("PATH");
|
||||
|
||||
//...
|
||||
|
||||
sprintf(buffer, "Cannot find exe on path: %s", path);
|
||||
send(socket, buffer, strlen(buffer), 0);
|
||||
fprintf(stderr, "cannot find exe on path %s\n", path);
|
||||
@@ -1,28 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Exposing system data or debugging information may help a malicious user learn about the system and form an attack plan. An attacker can use error messages that reveal technologies, operating systems, and product versions to tune their attack against known vulnerabilities in the software.</p>
|
||||
|
||||
<p>This query finds locations where system configuration information that is particularly sensitive might be revealed to a user.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>Do not expose system configuration information to users. Be wary of the difference between information that could be helpful to users, and unnecessary details that could be useful to a malicious user.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In this example the value of the <code>PATH</code> environment variable is revealed in full to the user when a particular error occurs. This might reveal information such as the software installed on your system to a malicious user who does not have legitimate access to that information.</p>
|
||||
|
||||
<sample src="PotentiallyExposedSystemDataIncorrect.cpp" />
|
||||
|
||||
<p>The message should be rephrased without this information, for example:</p>
|
||||
|
||||
<sample src="PotentiallyExposedSystemDataCorrect.cpp" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
@@ -1,51 +0,0 @@
|
||||
/**
|
||||
* @name Potential exposure of sensitive system data to an unauthorized control sphere
|
||||
* @description Exposing sensitive system data helps
|
||||
* a malicious user learn about the system and form an
|
||||
* attack plan.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 6.5
|
||||
* @precision medium
|
||||
* @id cpp/potential-system-data-exposure
|
||||
* @tags security
|
||||
* external/cwe/cwe-497
|
||||
*/
|
||||
|
||||
/*
|
||||
* These queries are closely related:
|
||||
* - `cpp/system-data-exposure`, which flags exposure of system information
|
||||
* to a remote sink (i.e. focusses on quality of the sink).
|
||||
* - `cpp/potential-system-data-exposure`, which flags on exposure of the most
|
||||
* sensitive information to a local sink (i.e. focusses on quality of the
|
||||
* sensitive information).
|
||||
*
|
||||
* This used to be a single query with neither focus, which was too noisy and
|
||||
* gave the user less control.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import semmle.code.cpp.security.OutputWrite
|
||||
import DataFlow::PathGraph
|
||||
import SystemData
|
||||
|
||||
class PotentiallyExposedSystemDataConfiguration extends TaintTracking::Configuration {
|
||||
PotentiallyExposedSystemDataConfiguration() { this = "PotentiallyExposedSystemDataConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source = any(SystemData sd | sd.isSensitive()).getAnExpr()
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(OutputWrite ow | ow.getASource().getAChild*() = sink.asExpr())
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
PotentiallyExposedSystemDataConfiguration config, DataFlow::PathNode source,
|
||||
DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink, source, sink, "This operation potentially exposes sensitive system data from $@.",
|
||||
source, source.getNode().toString()
|
||||
@@ -1,5 +0,0 @@
|
||||
char* key = getenv("APP_KEY");
|
||||
|
||||
//...
|
||||
|
||||
fprintf(stderr, "Application key not recognized. Please ensure the key is correct or contact a system administrator.\n", key);
|
||||
@@ -1,5 +0,0 @@
|
||||
char* key = getenv("APP_KEY");
|
||||
|
||||
//...
|
||||
|
||||
fprintf(stderr, "Key not recognized: %s\n", key);
|
||||
@@ -1,342 +0,0 @@
|
||||
/**
|
||||
* Classes for recognizing system data, used by the exposed system data queries.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Environment
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
|
||||
/**
|
||||
* An element that should not be exposed to a malicious user.
|
||||
*/
|
||||
abstract class SystemData extends Element {
|
||||
/**
|
||||
* Gets an expression that is part of this `SystemData`.
|
||||
*/
|
||||
abstract DataFlow::Node getAnExpr();
|
||||
|
||||
/**
|
||||
* Holds if this system data is considered especially sensitive (for example
|
||||
* a password or token).
|
||||
*/
|
||||
predicate isSensitive() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Data originating from the environment.
|
||||
*/
|
||||
class EnvData extends SystemData {
|
||||
EnvData() {
|
||||
// identify risky looking environment variables only
|
||||
this.(EnvironmentRead)
|
||||
.getEnvironmentVariable()
|
||||
.toLowerCase()
|
||||
.regexpMatch(".*(user|host|admin|root|home|path|http|ssl|snmp|sock|port|proxy|pass|token|crypt|key).*")
|
||||
}
|
||||
|
||||
override DataFlow::Node getAnExpr() { result.asConvertedExpr() = this }
|
||||
|
||||
override predicate isSensitive() {
|
||||
this.(EnvironmentRead)
|
||||
.getEnvironmentVariable()
|
||||
.toLowerCase()
|
||||
.regexpMatch(".*(pass|token|key).*")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data originating from a call to `mysql_get_client_info()`.
|
||||
*/
|
||||
class SQLClientInfo extends SystemData {
|
||||
SQLClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") }
|
||||
|
||||
override DataFlow::Node getAnExpr() { result.asConvertedExpr() = this }
|
||||
|
||||
override predicate isSensitive() { any() }
|
||||
}
|
||||
|
||||
private predicate sqlConnectInfo(FunctionCall source, Expr use) {
|
||||
(
|
||||
source.getTarget().hasName("mysql_connect") or
|
||||
source.getTarget().hasName("mysql_real_connect")
|
||||
) and
|
||||
use = source.getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed into an SQL connect function.
|
||||
*/
|
||||
class SQLConnectInfo extends SystemData {
|
||||
SQLConnectInfo() { sqlConnectInfo(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { sqlConnectInfo(this, result.asConvertedExpr()) }
|
||||
|
||||
override predicate isSensitive() { any() }
|
||||
}
|
||||
|
||||
private predicate posixSystemInfo(FunctionCall source, DataFlow::Node use) {
|
||||
// size_t confstr(int name, char *buf, size_t len)
|
||||
// - various OS / system strings, such as the libc version
|
||||
// int statvfs(const char *__path, struct statvfs *__buf)
|
||||
// int fstatvfs(int __fd, struct statvfs *__buf)
|
||||
source.getTarget().hasName(["confstr", "statvfs", "fstatvfs"]) and
|
||||
use.asDefiningArgument() = source.getArgument(1)
|
||||
or
|
||||
// - various filesystem parameters
|
||||
// int uname(struct utsname *buf)
|
||||
// - OS name and version
|
||||
source.getTarget().hasName("uname") and
|
||||
use.asDefiningArgument() = source.getArgument(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a POSIX system information call.
|
||||
*/
|
||||
class PosixSystemInfo extends SystemData {
|
||||
PosixSystemInfo() { posixSystemInfo(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { posixSystemInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate posixPWInfo(FunctionCall source, DataFlow::Node use) {
|
||||
// struct passwd *getpwnam(const char *name);
|
||||
// struct passwd *getpwuid(uid_t uid);
|
||||
// struct passwd *getpwent(void);
|
||||
// struct group *getgrnam(const char *name);
|
||||
// struct group *getgrgid(gid_t);
|
||||
// struct group *getgrent(void);
|
||||
source
|
||||
.getTarget()
|
||||
.hasName(["getpwnam", "getpwuid", "getpwent", "getgrnam", "getgrgid", "getgrent"]) and
|
||||
use.asConvertedExpr() = source
|
||||
or
|
||||
// int getpwnam_r(const char *name, struct passwd *pwd,
|
||||
// char *buf, size_t buflen, struct passwd **result);
|
||||
// int getpwuid_r(uid_t uid, struct passwd *pwd,
|
||||
// char *buf, size_t buflen, struct passwd **result);
|
||||
// int getgrgid_r(gid_t gid, struct group *grp,
|
||||
// char *buf, size_t buflen, struct group **result);
|
||||
// int getgrnam_r(const char *name, struct group *grp,
|
||||
// char *buf, size_t buflen, struct group **result);
|
||||
source.getTarget().hasName(["getpwnam_r", "getpwuid_r", "getgrgid_r", "getgrnam_r"]) and
|
||||
(
|
||||
use.asConvertedExpr() = source.getArgument([1, 2]) or
|
||||
use.asDefiningArgument() = source.getArgument(4)
|
||||
)
|
||||
or
|
||||
// int getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize,
|
||||
// struct passwd **result);
|
||||
// int getgrent_r(struct group *gbuf, char *buf,
|
||||
// size_t buflen, struct group **gbufp);
|
||||
source.getTarget().hasName(["getpwent_r", "getgrent_r"]) and
|
||||
(
|
||||
use.asConvertedExpr() = source.getArgument([0, 1]) or
|
||||
use.asDefiningArgument() = source.getArgument(3)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a POSIX user/password/group database information call.
|
||||
*/
|
||||
class PosixPWInfo extends SystemData {
|
||||
PosixPWInfo() { posixPWInfo(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { posixPWInfo(this, result) }
|
||||
|
||||
override predicate isSensitive() { any() }
|
||||
}
|
||||
|
||||
private predicate windowsSystemInfo(FunctionCall source, DataFlow::Node use) {
|
||||
// DWORD WINAPI GetVersion(void);
|
||||
source.getTarget().hasGlobalName("GetVersion") and
|
||||
use.asConvertedExpr() = source
|
||||
or
|
||||
// BOOL WINAPI GetVersionEx(_Inout_ LPOSVERSIONINFO lpVersionInfo);
|
||||
// void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
|
||||
// void WINAPI GetNativeSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"GetVersionEx", "GetVersionExA", "GetVersionExW", "GetSystemInfo", "GetNativeSystemInfo"
|
||||
]) and
|
||||
use.asDefiningArgument() = source.getArgument(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained from a Windows system information call.
|
||||
*/
|
||||
class WindowsSystemInfo extends SystemData {
|
||||
WindowsSystemInfo() { windowsSystemInfo(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { windowsSystemInfo(this, result) }
|
||||
}
|
||||
|
||||
private predicate windowsFolderPath(FunctionCall source, Element use) {
|
||||
// BOOL SHGetSpecialFolderPath(
|
||||
// HWND hwndOwner,
|
||||
// _Out_ LPTSTR lpszPath,
|
||||
// _In_ int csidl,
|
||||
// _In_ BOOL fCreate
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"SHGetSpecialFolderPath", "SHGetSpecialFolderPathA", "SHGetSpecialFolderPathW"
|
||||
]) and
|
||||
use = source.getArgument(1)
|
||||
or
|
||||
// HRESULT SHGetKnownFolderPath(
|
||||
// _In_ REFKNOWNFOLDERID rfid,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _In_opt_ HANDLE hToken,
|
||||
// _Out_ PWSTR *ppszPath
|
||||
// );
|
||||
source.getTarget().hasGlobalName("SHGetKnownFolderPath") and
|
||||
use = source.getArgument(3)
|
||||
or
|
||||
// HRESULT SHGetFolderPath(
|
||||
// _In_ HWND hwndOwner,
|
||||
// _In_ int nFolder,
|
||||
// _In_ HANDLE hToken,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _Out_ LPTSTR pszPath
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["SHGetFolderPath", "SHGetFolderPathA", "SHGetFolderPathW"]) and
|
||||
use = source.getArgument(4)
|
||||
or
|
||||
// HRESULT SHGetFolderPathAndSubDir(
|
||||
// _In_ HWND hwnd,
|
||||
// _In_ int csidl,
|
||||
// _In_ HANDLE hToken,
|
||||
// _In_ DWORD dwFlags,
|
||||
// _In_ LPCTSTR pszSubDir,
|
||||
// _Out_ LPTSTR pszPath
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"SHGetFolderPathAndSubDir", "SHGetFolderPathAndSubDirA", "SHGetFolderPathAndSubDirW"
|
||||
]) and
|
||||
use = source.getArgument(5)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data obtained about Windows special paths (for example, the
|
||||
* location of `System32`).
|
||||
*/
|
||||
class WindowsFolderPath extends SystemData {
|
||||
WindowsFolderPath() { windowsFolderPath(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { windowsFolderPath(this, result.asDefiningArgument()) }
|
||||
}
|
||||
|
||||
private predicate logonUser(FunctionCall source, VariableAccess use) {
|
||||
source.getTarget().hasGlobalName(["LogonUser", "LogonUserW", "LogonUserA"]) and
|
||||
use = source.getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Data passed into a `LogonUser` (Windows) function.
|
||||
*/
|
||||
class LogonUser extends SystemData {
|
||||
LogonUser() { logonUser(this, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { logonUser(this, result.asConvertedExpr()) }
|
||||
|
||||
override predicate isSensitive() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of a registry query parameter, if it is of interest to us. This
|
||||
* is used to express information about registry query parameters in the
|
||||
* `regQuery` predicate concisely.
|
||||
*/
|
||||
private newtype TRegQueryParameter =
|
||||
TSubKeyName() or
|
||||
TValueName() or
|
||||
TReturnData()
|
||||
|
||||
/**
|
||||
* Registry query call (`source`) with information about parameters (`param`).
|
||||
*/
|
||||
private predicate regQuery(FunctionCall source, TRegQueryParameter paramType, Expr param) {
|
||||
// LONG WINAPI RegQueryValue(
|
||||
// _In_ HKEY hKey,
|
||||
// _In_opt_ LPCTSTR lpSubKey,
|
||||
// _Out_opt_ LPTSTR lpValue,
|
||||
// _Inout_opt_ PLONG lpcbValue
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegQueryValue", "RegQueryValueA", "RegQueryValueW"]) and
|
||||
(
|
||||
paramType = TSubKeyName() and param = source.getArgument(1)
|
||||
or
|
||||
paramType = TReturnData() and param = source.getArgument(2)
|
||||
)
|
||||
or
|
||||
// LONG WINAPI RegQueryMultipleValues(
|
||||
// _In_ HKEY hKey,
|
||||
// _Out_ PVALENT val_list,
|
||||
// _In_ DWORD num_vals,
|
||||
// _Out_opt_ LPTSTR lpValueBuf,
|
||||
// _Inout_opt_ LPDWORD ldwTotsize
|
||||
// );
|
||||
source
|
||||
.getTarget()
|
||||
.hasGlobalName([
|
||||
"RegQueryMultipleValues", "RegQueryMultipleValuesA", "RegQueryMultipleValuesW"
|
||||
]) and
|
||||
paramType = TReturnData() and
|
||||
param = source.getArgument(3)
|
||||
or
|
||||
// LONG WINAPI RegQueryValueEx(
|
||||
// _In_ HKEY hKey,
|
||||
// _In_opt_ LPCTSTR lpValueName,
|
||||
// _Reserved_ LPDWORD lpReserved,
|
||||
// _Out_opt_ LPDWORD lpType,
|
||||
// _Out_opt_ LPBYTE lpData,
|
||||
// _Inout_opt_ LPDWORD lpcbData
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegQueryValueEx", "RegQueryValueExA", "RegQueryValueExW"]) and
|
||||
(
|
||||
paramType = TValueName() and param = source.getArgument(1)
|
||||
or
|
||||
paramType = TReturnData() and param = source.getArgument(4)
|
||||
)
|
||||
or
|
||||
// LONG WINAPI RegGetValue(
|
||||
// _In_ HKEY hkey,
|
||||
// _In_opt_ LPCTSTR lpSubKey,
|
||||
// _In_opt_ LPCTSTR lpValue,
|
||||
// _In_opt_ DWORD dwFlags,
|
||||
// _Out_opt_ LPDWORD pdwType,
|
||||
// _Out_opt_ PVOID pvData,
|
||||
// _Inout_opt_ LPDWORD pcbData
|
||||
// );
|
||||
source.getTarget().hasGlobalName(["RegGetValue", "RegGetValueA", "RegGetValueW"]) and
|
||||
(
|
||||
paramType = TSubKeyName() and param = source.getArgument(1)
|
||||
or
|
||||
paramType = TValueName() and param = source.getArgument(2)
|
||||
or
|
||||
paramType = TReturnData() and param = source.getArgument(5)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Data read from the Windows registry.
|
||||
*/
|
||||
class RegQuery extends SystemData {
|
||||
RegQuery() { regQuery(this, _, _) }
|
||||
|
||||
override DataFlow::Node getAnExpr() { regQuery(this, TReturnData(), result.asDefiningArgument()) }
|
||||
|
||||
override predicate isSensitive() {
|
||||
exists(Expr e |
|
||||
(
|
||||
regQuery(this, TSubKeyName(), e) or
|
||||
regQuery(this, TValueName(), e)
|
||||
) and
|
||||
e.getValue().toLowerCase().regexpMatch(".*(pass|token|key).*")
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* A new query, "Potential exposure of sensitive system data to an unauthorized control sphere" (`cpp/potential-system-data-exposure`) has been added. This query is focused on exposure of information that is highly likely to be sensitive, whereas the similar query "Exposure of system data to an unauthorized control sphere" (`cpp/system-data-exposure`) is focused on exposure of information on a channel that is more likely to be intercepted by an attacker.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/command-line-injection` query now takes into account calling contexts across string concatenations. This removes false positives due to mismatched calling contexts before and after string concatenations.
|
||||
@@ -3,3 +3,4 @@
|
||||
- apply: code-scanning-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
- apply: codeql-suites/exclude-slow-queries.yml
|
||||
from: codeql/cpp-queries
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
- apply: lgtm-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
- apply: codeql-suites/exclude-slow-queries.yml
|
||||
from: codeql/cpp-queries
|
||||
# These are only for IDE use.
|
||||
- exclude:
|
||||
tags contain:
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
- apply: security-and-quality-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
- apply: codeql-suites/exclude-slow-queries.yml
|
||||
from: codeql/cpp-queries
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
- apply: security-extended-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
- apply: codeql-suites/exclude-slow-queries.yml
|
||||
from: codeql/cpp-queries
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* @name Linux kernel double-fetch vulnerability detection
|
||||
* @description Double-fetch is a very common vulnerability pattern
|
||||
* in linux kernel, attacker can exploit double-fetch
|
||||
* issues to obatain root privilege.
|
||||
* Double-fetch is caused by fetching data from user
|
||||
* mode by calling copy_from_user twice, CVE-2016-6480
|
||||
* is quite a good example for your information.
|
||||
* @kind problem
|
||||
* @id cpp/linux-kernel-double-fetch-vulnerability
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.5
|
||||
* @tags security
|
||||
* external/cwe/cwe-362
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
|
||||
class CopyFromUserFunctionCall extends FunctionCall {
|
||||
CopyFromUserFunctionCall() {
|
||||
this.getTarget().getName() = "copy_from_user" and
|
||||
not this.getArgument(1) instanceof AddressOfExpr
|
||||
}
|
||||
|
||||
//root cause of double-fetech issue is read from
|
||||
//the same user mode memory twice, so it makes
|
||||
//sense that only check user mode pointer
|
||||
predicate readFromSameUserModePointer(CopyFromUserFunctionCall another) {
|
||||
globalValueNumber(this.getArgument(1)) = globalValueNumber(another.getArgument(1))
|
||||
}
|
||||
}
|
||||
|
||||
from CopyFromUserFunctionCall p1, CopyFromUserFunctionCall p2
|
||||
where
|
||||
not p1 = p2 and
|
||||
p1.readFromSameUserModePointer(p2) and
|
||||
exists(IfStmt ifStmt |
|
||||
p1.getBasicBlock().getAFalseSuccessor*() = ifStmt.getBasicBlock() and
|
||||
ifStmt.getBasicBlock().getAFalseSuccessor*() = p2.getBasicBlock()
|
||||
) and
|
||||
not exists(AssignPointerAddExpr assignPtrAdd |
|
||||
globalValueNumber(p1.getArgument(1)) = globalValueNumber(assignPtrAdd.getLValue()) and
|
||||
p1.getBasicBlock().getAFalseSuccessor*() = assignPtrAdd.getBasicBlock()
|
||||
)
|
||||
select p2, "Double fetch vulnerability. First fetch was $@.", p1, p1.toString()
|
||||
@@ -208,16 +208,11 @@ postWithInFlow
|
||||
| lambdas.cpp:13:7:13:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:13:10:17:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:13:10:17:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:13:11:13:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:13:11:13:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:16:3:16:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:7:20:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:10:24:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:10:24:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:10:24:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:3 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -225,8 +220,6 @@ postWithInFlow
|
||||
| lambdas.cpp:28:7:28:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:11:28:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:11:28:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:34:7:34:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:34:13:34:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:40:7:40:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
|
||||
@@ -27,8 +27,7 @@
|
||||
| arrayassignment.cpp:29:8:29:13 | call to source | arrayassignment.cpp:29:2:29:15 | ... = ... | |
|
||||
| arrayassignment.cpp:29:8:29:13 | call to source | arrayassignment.cpp:33:7:33:9 | r_x | |
|
||||
| arrayassignment.cpp:32:8:32:10 | p_x | arrayassignment.cpp:32:7:32:10 | * ... | TAINT |
|
||||
| arrayassignment.cpp:37:7:37:7 | i | arrayassignment.cpp:37:7:37:7 | constructor init of field i | TAINT |
|
||||
| arrayassignment.cpp:37:7:37:7 | i | arrayassignment.cpp:37:7:37:7 | i | |
|
||||
| arrayassignment.cpp:37:7:37:7 | Unknown literal | arrayassignment.cpp:37:7:37:7 | constructor init of field i | TAINT |
|
||||
| arrayassignment.cpp:37:7:37:7 | this | arrayassignment.cpp:37:7:37:7 | constructor init of field i [pre-this] | |
|
||||
| arrayassignment.cpp:40:2:40:6 | this | arrayassignment.cpp:40:12:40:15 | constructor init of field i [pre-this] | |
|
||||
| arrayassignment.cpp:40:12:40:15 | 0 | arrayassignment.cpp:40:12:40:15 | constructor init of field i | TAINT |
|
||||
@@ -285,7 +284,6 @@
|
||||
| copyableclass_declonly.cpp:67:13:67:18 | call to source | copyableclass_declonly.cpp:67:13:67:20 | call to MyCopyableClassDeclOnly | TAINT |
|
||||
| copyableclass_declonly.cpp:67:13:67:20 | call to MyCopyableClassDeclOnly | copyableclass_declonly.cpp:67:8:67:9 | ref arg s3 | TAINT |
|
||||
| copyableclass_declonly.cpp:67:13:67:20 | call to MyCopyableClassDeclOnly | copyableclass_declonly.cpp:67:11:67:11 | call to operator= | TAINT |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | arrayassignment.cpp:37:7:37:7 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
|
||||
@@ -301,27 +299,6 @@
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:75:8:75:8 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:75:8:75:8 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | structlikeclass.cpp:5:7:5:7 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | structlikeclass.cpp:5:7:5:7 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:228:11:228:11 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:228:11:228:11 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:235:11:235:11 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:235:11:235:11 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:235:11:235:11 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:243:11:243:11 | (unnamed parameter 0) | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:243:11:243:11 | (unnamed parameter 0) | |
|
||||
| format.cpp:16:21:16:21 | s | format.cpp:16:21:16:21 | s | |
|
||||
| format.cpp:16:21:16:21 | s | format.cpp:22:22:22:22 | s | |
|
||||
| format.cpp:16:31:16:31 | n | format.cpp:22:25:22:25 | n | |
|
||||
@@ -3577,10 +3554,8 @@
|
||||
| standalone_iterators.cpp:120:2:120:3 | it | standalone_iterators.cpp:120:5:120:5 | call to operator+= | TAINT |
|
||||
| standalone_iterators.cpp:120:2:120:3 | ref arg it | standalone_iterators.cpp:121:7:121:8 | it | |
|
||||
| standalone_iterators.cpp:120:8:120:13 | call to source | standalone_iterators.cpp:120:2:120:3 | ref arg it | TAINT |
|
||||
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
||||
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
||||
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | container | |
|
||||
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | container | |
|
||||
| stl.h:75:8:75:8 | Unknown literal | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
||||
| stl.h:75:8:75:8 | Unknown literal | stl.h:75:8:75:8 | constructor init of field container | TAINT |
|
||||
| stl.h:75:8:75:8 | this | stl.h:75:8:75:8 | constructor init of field container [pre-this] | |
|
||||
| stl.h:75:8:75:8 | this | stl.h:75:8:75:8 | constructor init of field container [pre-this] | |
|
||||
| stl.h:95:69:95:69 | x | stl.h:95:69:95:69 | x | |
|
||||
@@ -3598,6 +3573,16 @@
|
||||
| stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT |
|
||||
| stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT |
|
||||
| stl.h:292:53:292:63 | 0 | stl.h:292:46:292:64 | (no string representation) | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | Unknown literal | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
|
||||
| stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
|
||||
| stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
|
||||
@@ -3608,26 +3593,6 @@
|
||||
| stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
|
||||
| stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
|
||||
| stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
|
||||
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
|
||||
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
|
||||
| stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
|
||||
| stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
|
||||
| stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
|
||||
@@ -5389,12 +5354,10 @@
|
||||
| stringstream.cpp:266:54:266:58 | ref arg call to flush | stringstream.cpp:266:35:266:39 | ref arg call to write | TAINT |
|
||||
| stringstream.cpp:266:68:266:72 | xyz | stringstream.cpp:266:54:266:58 | ref arg call to flush | TAINT |
|
||||
| stringstream.cpp:266:68:266:72 | xyz | stringstream.cpp:266:62:266:66 | call to write | TAINT |
|
||||
| structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT |
|
||||
| structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT |
|
||||
| structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | |
|
||||
| structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | |
|
||||
| structlikeclass.cpp:5:7:5:7 | v | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT |
|
||||
| structlikeclass.cpp:5:7:5:7 | v | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT |
|
||||
| structlikeclass.cpp:5:7:5:7 | v | structlikeclass.cpp:5:7:5:7 | v | |
|
||||
| structlikeclass.cpp:5:7:5:7 | v | structlikeclass.cpp:5:7:5:7 | v | |
|
||||
| structlikeclass.cpp:8:2:8:16 | this | structlikeclass.cpp:8:28:8:32 | constructor init of field v [pre-this] | |
|
||||
| structlikeclass.cpp:8:22:8:23 | _v | structlikeclass.cpp:8:30:8:31 | _v | |
|
||||
| structlikeclass.cpp:8:30:8:31 | _v | structlikeclass.cpp:8:28:8:32 | constructor init of field v | TAINT |
|
||||
@@ -6010,29 +5973,24 @@
|
||||
| taint.cpp:226:9:226:10 | 0 | taint.cpp:261:7:261:7 | w | |
|
||||
| taint.cpp:228:10:232:2 | [...](...){...} | taint.cpp:233:7:233:7 | a | |
|
||||
| taint.cpp:228:10:232:2 | {...} | taint.cpp:228:10:232:2 | [...](...){...} | |
|
||||
| taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:228:11:228:11 | constructor init of field t [post-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:228:11:228:11 | t | taint.cpp:228:11:228:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:228:11:228:11 | t | taint.cpp:228:11:228:11 | t | |
|
||||
| taint.cpp:228:11:228:11 | this | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | |
|
||||
| taint.cpp:228:11:228:11 | u | taint.cpp:228:11:228:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:228:11:228:11 | u | taint.cpp:228:11:228:11 | u | |
|
||||
| taint.cpp:228:17:228:17 | this | taint.cpp:229:3:229:6 | this | |
|
||||
| taint.cpp:229:3:229:6 | this | taint.cpp:230:3:230:6 | this | |
|
||||
| taint.cpp:230:3:230:6 | this | file://:0:0:0:0 | this | |
|
||||
| taint.cpp:235:10:239:2 | [...](...){...} | taint.cpp:240:2:240:2 | b | |
|
||||
| taint.cpp:235:10:239:2 | {...} | taint.cpp:235:10:239:2 | [...](...){...} | |
|
||||
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field v | TAINT |
|
||||
| taint.cpp:235:11:235:11 | constructor init of field t [post-this] | taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | constructor init of field u [post-this] | taint.cpp:235:11:235:11 | constructor init of field v [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | taint.cpp:235:11:235:11 | constructor init of field v [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | t | taint.cpp:235:11:235:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:235:11:235:11 | t | taint.cpp:235:11:235:11 | t | |
|
||||
| taint.cpp:235:11:235:11 | this | taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | u | taint.cpp:235:11:235:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:235:11:235:11 | u | taint.cpp:235:11:235:11 | u | |
|
||||
| taint.cpp:235:11:235:11 | v | taint.cpp:235:11:235:11 | constructor init of field v | TAINT |
|
||||
| taint.cpp:235:11:235:11 | v | taint.cpp:235:11:235:11 | v | |
|
||||
| taint.cpp:235:15:235:15 | this | taint.cpp:236:3:236:6 | this | |
|
||||
| taint.cpp:236:3:236:6 | this | taint.cpp:237:3:237:6 | this | |
|
||||
| taint.cpp:237:3:237:6 | this | taint.cpp:238:3:238:14 | this | |
|
||||
@@ -6040,13 +5998,11 @@
|
||||
| taint.cpp:238:7:238:12 | call to source | taint.cpp:238:3:238:14 | ... = ... | |
|
||||
| taint.cpp:243:10:246:2 | [...](...){...} | taint.cpp:247:2:247:2 | c | |
|
||||
| taint.cpp:243:10:246:2 | {...} | taint.cpp:243:10:246:2 | [...](...){...} | |
|
||||
| taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:243:11:243:11 | constructor init of field t [post-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:243:11:243:11 | t | taint.cpp:243:11:243:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:243:11:243:11 | t | taint.cpp:243:11:243:11 | t | |
|
||||
| taint.cpp:243:11:243:11 | this | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | |
|
||||
| taint.cpp:243:11:243:11 | u | taint.cpp:243:11:243:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:243:11:243:11 | u | taint.cpp:243:11:243:11 | u | |
|
||||
| taint.cpp:243:15:243:15 | this | taint.cpp:244:3:244:6 | this | |
|
||||
| taint.cpp:244:3:244:6 | this | taint.cpp:245:3:245:6 | this | |
|
||||
| taint.cpp:249:11:252:2 | [...](...){...} | taint.cpp:253:2:253:2 | d | |
|
||||
|
||||
@@ -12,12 +12,8 @@
|
||||
| addressOf.cpp:40:15:40:15 | i | non-const address |
|
||||
| addressOf.cpp:42:19:42:22 | iref | non-const address |
|
||||
| addressOf.cpp:47:12:47:31 | captured | non-const address |
|
||||
| addressOf.cpp:47:13:47:13 | (unnamed parameter 0) | |
|
||||
| addressOf.cpp:47:13:47:13 | captured | |
|
||||
| addressOf.cpp:47:19:47:28 | captured | |
|
||||
| addressOf.cpp:48:3:48:4 | f1 | const address |
|
||||
| addressOf.cpp:49:13:49:13 | (unnamed parameter 0) | |
|
||||
| addressOf.cpp:49:13:49:13 | captured | |
|
||||
| addressOf.cpp:49:15:49:22 | captured | non-const address |
|
||||
| addressOf.cpp:49:27:49:36 | captured | |
|
||||
| addressOf.cpp:50:3:50:4 | f2 | const address |
|
||||
@@ -249,10 +245,6 @@
|
||||
| test.cpp:173:19:173:19 | x | const address |
|
||||
| test.cpp:174:20:174:20 | x | const address |
|
||||
| test.cpp:175:7:175:7 | x | |
|
||||
| test.cpp:178:8:178:8 | (unnamed parameter 0) | |
|
||||
| test.cpp:178:8:178:8 | (unnamed parameter 0) | |
|
||||
| test.cpp:178:8:178:8 | nested | |
|
||||
| test.cpp:178:8:178:8 | x_ | |
|
||||
| test.cpp:183:38:183:41 | yptr | |
|
||||
| test.cpp:183:48:183:48 | z | |
|
||||
| test.cpp:184:28:184:35 | static_y | non-const address |
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
| addressOf.cpp:61:33:61:35 | ref | addressOf.cpp:63:24:63:26 | ref |
|
||||
| addressOf.cpp:70:29:70:31 | obj | addressOf.cpp:71:32:71:34 | obj |
|
||||
| addressOf.cpp:70:29:70:31 | obj | addressOf.cpp:71:32:71:34 | obj |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | addressOf.cpp:47:13:47:13 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | addressOf.cpp:49:13:49:13 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:178:8:178:8 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:178:8:178:8 | (unnamed parameter 0) |
|
||||
| indirect_use.cpp:19:31:19:32 | ip | indirect_use.cpp:20:14:20:15 | ip |
|
||||
| indirect_use.cpp:24:31:24:32 | ip | indirect_use.cpp:25:14:25:15 | ip |
|
||||
| indirect_use.cpp:30:28:30:30 | ppp | indirect_use.cpp:31:19:31:21 | ppp |
|
||||
|
||||
@@ -26,10 +26,6 @@
|
||||
| addressOf.cpp:70:29:70:31 | obj | addressOf.cpp:71:32:71:34 | obj |
|
||||
| addressOf.cpp:76:7:76:7 | x | addressOf.cpp:77:27:77:27 | x |
|
||||
| addressOf.cpp:76:7:76:7 | x | addressOf.cpp:77:48:77:48 | x |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | addressOf.cpp:47:13:47:13 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | addressOf.cpp:49:13:49:13 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:178:8:178:8 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:178:8:178:8 | (unnamed parameter 0) |
|
||||
| indirect_use.cpp:19:31:19:32 | ip | indirect_use.cpp:20:14:20:15 | ip |
|
||||
| indirect_use.cpp:20:10:20:10 | p | indirect_use.cpp:21:17:21:17 | p |
|
||||
| indirect_use.cpp:24:31:24:32 | ip | indirect_use.cpp:25:14:25:15 | ip |
|
||||
|
||||
@@ -12,10 +12,6 @@
|
||||
| addressOf.cpp:61:23:61:25 | ptr | addressOf.cpp:63:19:63:21 | ptr |
|
||||
| addressOf.cpp:70:29:70:31 | obj | addressOf.cpp:71:32:71:34 | obj |
|
||||
| addressOf.cpp:76:7:76:7 | x | addressOf.cpp:77:48:77:48 | x |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | addressOf.cpp:47:13:47:13 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | addressOf.cpp:49:13:49:13 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:178:8:178:8 | (unnamed parameter 0) |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | test.cpp:178:8:178:8 | (unnamed parameter 0) |
|
||||
| indirect_use.cpp:19:31:19:32 | ip | indirect_use.cpp:20:14:20:15 | ip |
|
||||
| indirect_use.cpp:20:10:20:10 | p | indirect_use.cpp:21:17:21:17 | p |
|
||||
| indirect_use.cpp:24:31:24:32 | ip | indirect_use.cpp:25:14:25:15 | ip |
|
||||
|
||||
@@ -155,21 +155,15 @@ bad_asts.cpp:
|
||||
# 19| getInitializer(0): [ConstructorFieldInit] constructor init of field x
|
||||
# 19| Type = [IntType] int
|
||||
# 19| ValueCategory = prvalue
|
||||
# 19| getExpr(): [FieldAccess] x
|
||||
# 19| getExpr(): [Literal] Unknown literal
|
||||
# 19| Type = [IntType] int
|
||||
# 19| ValueCategory = prvalue(load)
|
||||
# 19| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 19| Type = [LValueReferenceType] const Point &
|
||||
# 19| ValueCategory = prvalue(load)
|
||||
# 19| ValueCategory = prvalue
|
||||
# 19| getInitializer(1): [ConstructorFieldInit] constructor init of field y
|
||||
# 19| Type = [IntType] int
|
||||
# 19| ValueCategory = prvalue
|
||||
# 19| getExpr(): [FieldAccess] y
|
||||
# 19| getExpr(): [Literal] Unknown literal
|
||||
# 19| Type = [IntType] int
|
||||
# 19| ValueCategory = prvalue(load)
|
||||
# 19| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 19| Type = [LValueReferenceType] const Point &
|
||||
# 19| ValueCategory = prvalue(load)
|
||||
# 19| ValueCategory = prvalue
|
||||
# 19| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 19| getStmt(0): [ReturnStmt] return ...
|
||||
# 19| [MoveConstructor] void Bad::Point::Point(Bad::Point&&)
|
||||
@@ -11651,75 +11645,51 @@ ir.cpp:
|
||||
# 1486| getInitializer(0): [ConstructorFieldInit] constructor init of field i
|
||||
# 1486| Type = [IntType] int
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [FieldAccess] i
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| Type = [IntType] int
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getInitializer(1): [ConstructorFieldInit] constructor init of field d
|
||||
# 1486| Type = [DoubleType] double
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [FieldAccess] d
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| Type = [DoubleType] double
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getInitializer(2): [ConstructorFieldInit] constructor init of field b
|
||||
# 1486| Type = [IntType] unsigned int
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [FieldAccess] b
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| Type = [IntType] unsigned int
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getInitializer(3): [ConstructorFieldInit] constructor init of field r
|
||||
# 1486| Type = [LValueReferenceType] int &
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [FieldAccess] r
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| Type = [LValueReferenceType] int &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getInitializer(4): [ConstructorFieldInit] constructor init of field p
|
||||
# 1486| Type = [IntPointerType] int *
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [FieldAccess] p
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| Type = [IntPointerType] int *
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getInitializer(5): [ConstructorFieldInit] constructor init of field xs
|
||||
# 1486| Type = [CTypedefType,NestedTypedefType] ArrayType
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [FieldAccess] xs
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| Type = [CTypedefType,NestedTypedefType] ArrayType
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getInitializer(6): [ConstructorFieldInit] constructor init of field r_alt
|
||||
# 1486| Type = [CTypedefType,NestedTypedefType] RefType
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [FieldAccess] r_alt
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| Type = [CTypedefType,NestedTypedefType] RefType
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getInitializer(7): [ConstructorFieldInit] constructor init of field m
|
||||
# 1486| Type = [Struct] StructuredBindingDataMemberMemberStruct
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getExpr(): [FieldAccess] m
|
||||
# 1486| getExpr(): [Literal] Unknown literal
|
||||
# 1486| Type = [Struct] StructuredBindingDataMemberMemberStruct
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1486| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct &
|
||||
# 1486| ValueCategory = prvalue(load)
|
||||
# 1486| ValueCategory = prvalue
|
||||
# 1486| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1486| getStmt(0): [ReturnStmt] return ...
|
||||
# 1486| [MoveConstructor] void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct(StructuredBindingDataMemberStruct&&)
|
||||
@@ -12096,30 +12066,21 @@ ir.cpp:
|
||||
# 1539| getInitializer(0): [ConstructorFieldInit] constructor init of field i
|
||||
# 1539| Type = [IntType] int
|
||||
# 1539| ValueCategory = prvalue
|
||||
# 1539| getExpr(): [FieldAccess] i
|
||||
# 1539| getExpr(): [Literal] Unknown literal
|
||||
# 1539| Type = [IntType] int
|
||||
# 1539| ValueCategory = prvalue(load)
|
||||
# 1539| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1539| Type = [LValueReferenceType] const StructuredBindingTupleRefGet &
|
||||
# 1539| ValueCategory = prvalue(load)
|
||||
# 1539| ValueCategory = prvalue
|
||||
# 1539| getInitializer(1): [ConstructorFieldInit] constructor init of field d
|
||||
# 1539| Type = [DoubleType] double
|
||||
# 1539| ValueCategory = prvalue
|
||||
# 1539| getExpr(): [FieldAccess] d
|
||||
# 1539| getExpr(): [Literal] Unknown literal
|
||||
# 1539| Type = [DoubleType] double
|
||||
# 1539| ValueCategory = prvalue(load)
|
||||
# 1539| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1539| Type = [LValueReferenceType] const StructuredBindingTupleRefGet &
|
||||
# 1539| ValueCategory = prvalue(load)
|
||||
# 1539| ValueCategory = prvalue
|
||||
# 1539| getInitializer(2): [ConstructorFieldInit] constructor init of field r
|
||||
# 1539| Type = [LValueReferenceType] int &
|
||||
# 1539| ValueCategory = prvalue
|
||||
# 1539| getExpr(): [FieldAccess] r
|
||||
# 1539| getExpr(): [Literal] Unknown literal
|
||||
# 1539| Type = [LValueReferenceType] int &
|
||||
# 1539| ValueCategory = prvalue(load)
|
||||
# 1539| getQualifier(): [VariableAccess] (unnamed parameter 0)
|
||||
# 1539| Type = [LValueReferenceType] const StructuredBindingTupleRefGet &
|
||||
# 1539| ValueCategory = prvalue(load)
|
||||
# 1539| ValueCategory = prvalue
|
||||
# 1539| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1539| getStmt(0): [ReturnStmt] return ...
|
||||
# 1539| [MoveConstructor] void StructuredBindingTupleRefGet::StructuredBindingTupleRefGet(StructuredBindingTupleRefGet&&)
|
||||
@@ -13074,23 +13035,6 @@ ir.cpp:
|
||||
# 1689| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1689| getStmt(0): [EmptyStmt] ;
|
||||
# 1689| getStmt(1): [ReturnStmt] return ...
|
||||
# 1693| [TopLevelFunction] int goto_on_same_line()
|
||||
# 1693| <params>:
|
||||
# 1693| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1694| getStmt(0): [DeclStmt] declaration
|
||||
# 1694| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
|
||||
# 1694| Type = [IntType] int
|
||||
# 1694| getVariable().getInitializer(): [Initializer] initializer for x
|
||||
# 1694| getExpr(): [Literal] 42
|
||||
# 1694| Type = [IntType] int
|
||||
# 1694| Value = [Literal] 42
|
||||
# 1694| ValueCategory = prvalue
|
||||
# 1695| getStmt(1): [GotoStmt] goto ...
|
||||
# 1695| getStmt(2): [LabelStmt] label ...:
|
||||
# 1696| getStmt(3): [ReturnStmt] return ...
|
||||
# 1696| getExpr(): [VariableAccess] x
|
||||
# 1696| Type = [IntType] int
|
||||
# 1696| ValueCategory = prvalue(load)
|
||||
perf-regression.cpp:
|
||||
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
|
||||
# 4| <params>:
|
||||
|
||||
@@ -1690,10 +1690,4 @@ void captured_lambda(int x, int &y, int &&z)
|
||||
};
|
||||
}
|
||||
|
||||
int goto_on_same_line() {
|
||||
int x = 42;
|
||||
goto next; next:
|
||||
return x;
|
||||
}
|
||||
|
||||
// semmle-extractor-options: -std=c++17 --clang
|
||||
|
||||
@@ -41,35 +41,6 @@
|
||||
| bad_asts.cpp:16:7:16:23 | ChiTotal | total:m14_4 |
|
||||
| bad_asts.cpp:16:7:16:23 | SideEffect | ~m14_4 |
|
||||
| bad_asts.cpp:16:25:16:25 | Arg(0) | 0:r16_3 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_5 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_5 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_7 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_7 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_9 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_10 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_12 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_16 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_17 |
|
||||
| bad_asts.cpp:19:10:19:10 | Address | &:r19_19 |
|
||||
| bad_asts.cpp:19:10:19:10 | ChiPartial | partial:m19_3 |
|
||||
| bad_asts.cpp:19:10:19:10 | ChiPartial | partial:m19_14 |
|
||||
| bad_asts.cpp:19:10:19:10 | ChiPartial | partial:m19_21 |
|
||||
| bad_asts.cpp:19:10:19:10 | ChiTotal | total:m19_2 |
|
||||
| bad_asts.cpp:19:10:19:10 | ChiTotal | total:m19_8 |
|
||||
| bad_asts.cpp:19:10:19:10 | ChiTotal | total:m19_15 |
|
||||
| bad_asts.cpp:19:10:19:10 | Load | m0_2 |
|
||||
| bad_asts.cpp:19:10:19:10 | Load | m0_2 |
|
||||
| bad_asts.cpp:19:10:19:10 | Load | m19_6 |
|
||||
| bad_asts.cpp:19:10:19:10 | Load | ~m0_4 |
|
||||
| bad_asts.cpp:19:10:19:10 | Load | ~m0_4 |
|
||||
| bad_asts.cpp:19:10:19:10 | SideEffect | m19_3 |
|
||||
| bad_asts.cpp:19:10:19:10 | SideEffect | m19_22 |
|
||||
| bad_asts.cpp:19:10:19:10 | StoreValue | r19_13 |
|
||||
| bad_asts.cpp:19:10:19:10 | StoreValue | r19_20 |
|
||||
| bad_asts.cpp:19:10:19:10 | Unary | m19_6 |
|
||||
| bad_asts.cpp:19:10:19:10 | Unary | m19_6 |
|
||||
| bad_asts.cpp:19:10:19:10 | Unary | r19_11 |
|
||||
| bad_asts.cpp:19:10:19:10 | Unary | r19_18 |
|
||||
| bad_asts.cpp:22:5:22:9 | Address | &:r22_5 |
|
||||
| bad_asts.cpp:22:5:22:9 | Address | &:r22_5 |
|
||||
| bad_asts.cpp:22:5:22:9 | Address | &:r22_7 |
|
||||
@@ -662,12 +633,6 @@
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_2 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
@@ -678,12 +643,6 @@
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_5 |
|
||||
| file://:0:0:0:0 | Address | &:r0_5 |
|
||||
| file://:0:0:0:0 | Address | &:r0_5 |
|
||||
@@ -733,9 +692,6 @@
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m745_6 |
|
||||
| file://:0:0:0:0 | Load | m754_6 |
|
||||
| file://:0:0:0:0 | Load | m763_6 |
|
||||
@@ -750,9 +706,6 @@
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m1078_23 |
|
||||
| file://:0:0:0:0 | SideEffect | m1078_23 |
|
||||
| file://:0:0:0:0 | SideEffect | m1084_23 |
|
||||
@@ -6816,102 +6769,13 @@
|
||||
| ir.cpp:1482:8:1482:8 | SideEffect | m1482_8 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_5 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_5 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_5 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_5 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_7 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_7 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_7 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_7 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_9 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_10 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_12 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_16 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_17 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_19 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_23 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_24 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_26 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_30 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_31 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_33 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_37 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_38 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_40 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_44 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_45 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_47 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_51 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_52 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_54 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_58 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_59 |
|
||||
| ir.cpp:1486:8:1486:8 | Address | &:r1486_61 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_3 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_3 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_14 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_21 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_28 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_35 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_42 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_49 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_56 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiPartial | partial:m1486_63 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_2 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_2 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_8 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_15 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_22 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_29 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_36 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_43 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_50 |
|
||||
| ir.cpp:1486:8:1486:8 | ChiTotal | total:m1486_57 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m0_2 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1486:8:1486:8 | SideEffect | m1486_3 |
|
||||
| ir.cpp:1486:8:1486:8 | SideEffect | m1486_3 |
|
||||
| ir.cpp:1486:8:1486:8 | SideEffect | m1486_8 |
|
||||
| ir.cpp:1486:8:1486:8 | SideEffect | m1486_64 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_13 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_20 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_27 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_34 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_41 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_48 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_55 |
|
||||
| ir.cpp:1486:8:1486:8 | StoreValue | r1486_62 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | m1486_6 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_11 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_18 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_25 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_32 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_39 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_46 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_53 |
|
||||
| ir.cpp:1486:8:1486:8 | Unary | r1486_60 |
|
||||
| ir.cpp:1499:6:1499:35 | ChiPartial | partial:m1499_3 |
|
||||
| ir.cpp:1499:6:1499:35 | ChiTotal | total:m1499_2 |
|
||||
| ir.cpp:1499:6:1499:35 | SideEffect | ~m1525_7 |
|
||||
@@ -7084,52 +6948,13 @@
|
||||
| ir.cpp:1528:17:1528:17 | StoreValue | r1528_4 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_5 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_5 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_5 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_5 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_7 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_7 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_7 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_7 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_9 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_10 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_12 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_16 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_17 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_19 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_23 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_24 |
|
||||
| ir.cpp:1539:8:1539:8 | Address | &:r1539_26 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiPartial | partial:m1539_3 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiPartial | partial:m1539_3 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiPartial | partial:m1539_14 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiPartial | partial:m1539_21 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiPartial | partial:m1539_28 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiTotal | total:m1539_2 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiTotal | total:m1539_2 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiTotal | total:m1539_8 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiTotal | total:m1539_15 |
|
||||
| ir.cpp:1539:8:1539:8 | ChiTotal | total:m1539_22 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | m0_2 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | m0_2 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | m0_2 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | m1539_6 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | m1539_6 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1539:8:1539:8 | Load | ~m0_4 |
|
||||
| ir.cpp:1539:8:1539:8 | SideEffect | m1539_3 |
|
||||
| ir.cpp:1539:8:1539:8 | SideEffect | m1539_3 |
|
||||
| ir.cpp:1539:8:1539:8 | SideEffect | m1539_8 |
|
||||
| ir.cpp:1539:8:1539:8 | SideEffect | m1539_29 |
|
||||
| ir.cpp:1539:8:1539:8 | StoreValue | r1539_13 |
|
||||
| ir.cpp:1539:8:1539:8 | StoreValue | r1539_20 |
|
||||
| ir.cpp:1539:8:1539:8 | StoreValue | r1539_27 |
|
||||
| ir.cpp:1539:8:1539:8 | Unary | m1539_6 |
|
||||
| ir.cpp:1539:8:1539:8 | Unary | m1539_6 |
|
||||
| ir.cpp:1539:8:1539:8 | Unary | m1539_6 |
|
||||
| ir.cpp:1539:8:1539:8 | Unary | r1539_11 |
|
||||
| ir.cpp:1539:8:1539:8 | Unary | r1539_18 |
|
||||
| ir.cpp:1539:8:1539:8 | Unary | r1539_25 |
|
||||
| ir.cpp:1567:60:1567:95 | Address | &:r1567_5 |
|
||||
| ir.cpp:1567:60:1567:95 | Address | &:r1567_5 |
|
||||
| ir.cpp:1567:60:1567:95 | Address | &:r1567_7 |
|
||||
@@ -7702,17 +7527,6 @@
|
||||
| ir.cpp:1689:50:1689:50 | Load | m1689_6 |
|
||||
| ir.cpp:1689:50:1689:50 | SideEffect | m1689_3 |
|
||||
| ir.cpp:1689:50:1689:50 | SideEffect | m1689_8 |
|
||||
| ir.cpp:1693:5:1693:21 | Address | &:r1693_5 |
|
||||
| ir.cpp:1693:5:1693:21 | ChiPartial | partial:m1693_3 |
|
||||
| ir.cpp:1693:5:1693:21 | ChiTotal | total:m1693_2 |
|
||||
| ir.cpp:1693:5:1693:21 | Load | m1696_4 |
|
||||
| ir.cpp:1693:5:1693:21 | SideEffect | m1693_3 |
|
||||
| ir.cpp:1694:7:1694:7 | Address | &:r1694_1 |
|
||||
| ir.cpp:1694:10:1694:12 | StoreValue | r1694_2 |
|
||||
| ir.cpp:1696:3:1696:11 | Address | &:r1696_1 |
|
||||
| ir.cpp:1696:10:1696:10 | Address | &:r1696_2 |
|
||||
| ir.cpp:1696:10:1696:10 | Load | m1694_3 |
|
||||
| ir.cpp:1696:10:1696:10 | StoreValue | r1696_3 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |
|
||||
|
||||
@@ -49,38 +49,6 @@ bad_asts.cpp:
|
||||
# 14| v14_5(void) = AliasedUse : ~m?
|
||||
# 14| v14_6(void) = ExitFunction :
|
||||
|
||||
# 19| void Bad::Point::Point(Bad::Point const&)
|
||||
# 19| Block 0
|
||||
# 19| v19_1(void) = EnterFunction :
|
||||
# 19| mu19_2(unknown) = AliasedDefinition :
|
||||
# 19| mu19_3(unknown) = InitializeNonLocal :
|
||||
# 19| r19_4(glval<unknown>) = VariableAddress[#this] :
|
||||
# 19| mu19_5(glval<Point>) = InitializeParameter[#this] : &:r19_4
|
||||
# 19| r19_6(glval<Point>) = Load[#this] : &:r19_4, ~m?
|
||||
# 19| mu19_7(Point) = InitializeIndirection[#this] : &:r19_6
|
||||
#-----| r0_1(glval<Point &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
#-----| mu0_2(Point &) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
|
||||
#-----| r0_3(Point &) = Load[(unnamed parameter 0)] : &:r0_1, ~m?
|
||||
#-----| mu0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
|
||||
# 19| r19_8(glval<int>) = FieldAddress[x] : mu19_5
|
||||
# 19| r19_9(glval<Point &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 19| r19_10(Point &) = Load[(unnamed parameter 0)] : &:r19_9, ~m?
|
||||
# 19| r19_11(glval<int>) = FieldAddress[x] : r19_10
|
||||
# 19| r19_12(int) = Load[?] : &:r19_11, ~m?
|
||||
# 19| mu19_13(int) = Store[?] : &:r19_8, r19_12
|
||||
# 19| r19_14(glval<int>) = FieldAddress[y] : mu19_5
|
||||
# 19| r19_15(glval<Point &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 19| r19_16(Point &) = Load[(unnamed parameter 0)] : &:r19_15, ~m?
|
||||
# 19| r19_17(glval<int>) = FieldAddress[y] : r19_16
|
||||
# 19| r19_18(int) = Load[?] : &:r19_17, ~m?
|
||||
# 19| mu19_19(int) = Store[?] : &:r19_14, r19_18
|
||||
# 19| v19_20(void) = NoOp :
|
||||
# 19| v19_21(void) = ReturnIndirection[#this] : &:r19_6, ~m?
|
||||
#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, ~m?
|
||||
# 19| v19_22(void) = ReturnVoid :
|
||||
# 19| v19_23(void) = AliasedUse : ~m?
|
||||
# 19| v19_24(void) = ExitFunction :
|
||||
|
||||
# 22| void Bad::Point::Point()
|
||||
# 22| Block 0
|
||||
# 22| v22_1(void) = EnterFunction :
|
||||
@@ -8061,74 +8029,6 @@ ir.cpp:
|
||||
# 1486| v1486_16(void) = AliasedUse : ~m?
|
||||
# 1486| v1486_17(void) = ExitFunction :
|
||||
|
||||
# 1486| void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct(StructuredBindingDataMemberStruct const&)
|
||||
# 1486| Block 0
|
||||
# 1486| v1486_1(void) = EnterFunction :
|
||||
# 1486| mu1486_2(unknown) = AliasedDefinition :
|
||||
# 1486| mu1486_3(unknown) = InitializeNonLocal :
|
||||
# 1486| r1486_4(glval<unknown>) = VariableAddress[#this] :
|
||||
# 1486| mu1486_5(glval<StructuredBindingDataMemberStruct>) = InitializeParameter[#this] : &:r1486_4
|
||||
# 1486| r1486_6(glval<StructuredBindingDataMemberStruct>) = Load[#this] : &:r1486_4, ~m?
|
||||
# 1486| mu1486_7(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1486_6
|
||||
#-----| r0_1(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
#-----| mu0_2(StructuredBindingDataMemberStruct &) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
|
||||
#-----| r0_3(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r0_1, ~m?
|
||||
#-----| mu0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
|
||||
# 1486| r1486_8(glval<int>) = FieldAddress[i] : mu1486_5
|
||||
# 1486| r1486_9(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_10(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_9, ~m?
|
||||
# 1486| r1486_11(glval<int>) = FieldAddress[i] : r1486_10
|
||||
# 1486| r1486_12(int) = Load[?] : &:r1486_11, ~m?
|
||||
# 1486| mu1486_13(int) = Store[?] : &:r1486_8, r1486_12
|
||||
# 1486| r1486_14(glval<double>) = FieldAddress[d] : mu1486_5
|
||||
# 1486| r1486_15(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_16(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_15, ~m?
|
||||
# 1486| r1486_17(glval<double>) = FieldAddress[d] : r1486_16
|
||||
# 1486| r1486_18(double) = Load[?] : &:r1486_17, ~m?
|
||||
# 1486| mu1486_19(double) = Store[?] : &:r1486_14, r1486_18
|
||||
# 1486| r1486_20(glval<unsigned int>) = FieldAddress[b] : mu1486_5
|
||||
# 1486| r1486_21(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_22(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_21, ~m?
|
||||
# 1486| r1486_23(glval<unsigned int>) = FieldAddress[b] : r1486_22
|
||||
# 1486| r1486_24(unsigned int) = Load[?] : &:r1486_23, ~m?
|
||||
# 1486| mu1486_25(unsigned int) = Store[?] : &:r1486_20, r1486_24
|
||||
# 1486| r1486_26(glval<int &>) = FieldAddress[r] : mu1486_5
|
||||
# 1486| r1486_27(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_28(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_27, ~m?
|
||||
# 1486| r1486_29(glval<int &>) = FieldAddress[r] : r1486_28
|
||||
# 1486| r1486_30(int &) = Load[?] : &:r1486_29, ~m?
|
||||
# 1486| mu1486_31(int &) = Store[?] : &:r1486_26, r1486_30
|
||||
# 1486| r1486_32(glval<int *>) = FieldAddress[p] : mu1486_5
|
||||
# 1486| r1486_33(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_34(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_33, ~m?
|
||||
# 1486| r1486_35(glval<int *>) = FieldAddress[p] : r1486_34
|
||||
# 1486| r1486_36(int *) = Load[?] : &:r1486_35, ~m?
|
||||
# 1486| mu1486_37(int *) = Store[?] : &:r1486_32, r1486_36
|
||||
# 1486| r1486_38(glval<int[2]>) = FieldAddress[xs] : mu1486_5
|
||||
# 1486| r1486_39(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_40(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_39, ~m?
|
||||
# 1486| r1486_41(glval<int[2]>) = FieldAddress[xs] : r1486_40
|
||||
# 1486| r1486_42(int[2]) = Load[?] : &:r1486_41, ~m?
|
||||
# 1486| mu1486_43(int[2]) = Store[?] : &:r1486_38, r1486_42
|
||||
# 1486| r1486_44(glval<int &>) = FieldAddress[r_alt] : mu1486_5
|
||||
# 1486| r1486_45(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_46(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_45, ~m?
|
||||
# 1486| r1486_47(glval<int &>) = FieldAddress[r_alt] : r1486_46
|
||||
# 1486| r1486_48(int &) = Load[?] : &:r1486_47, ~m?
|
||||
# 1486| mu1486_49(int &) = Store[?] : &:r1486_44, r1486_48
|
||||
# 1486| r1486_50(glval<StructuredBindingDataMemberMemberStruct>) = FieldAddress[m] : mu1486_5
|
||||
# 1486| r1486_51(glval<StructuredBindingDataMemberStruct &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1486| r1486_52(StructuredBindingDataMemberStruct &) = Load[(unnamed parameter 0)] : &:r1486_51, ~m?
|
||||
# 1486| r1486_53(glval<StructuredBindingDataMemberMemberStruct>) = FieldAddress[m] : r1486_52
|
||||
# 1486| r1486_54(StructuredBindingDataMemberMemberStruct) = Load[?] : &:r1486_53, ~m?
|
||||
# 1486| mu1486_55(StructuredBindingDataMemberMemberStruct) = Store[?] : &:r1486_50, r1486_54
|
||||
# 1486| v1486_56(void) = NoOp :
|
||||
# 1486| v1486_57(void) = ReturnIndirection[#this] : &:r1486_6, ~m?
|
||||
#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, ~m?
|
||||
# 1486| v1486_58(void) = ReturnVoid :
|
||||
# 1486| v1486_59(void) = AliasedUse : ~m?
|
||||
# 1486| v1486_60(void) = ExitFunction :
|
||||
|
||||
# 1499| void data_member_structured_binding()
|
||||
# 1499| Block 0
|
||||
# 1499| v1499_1(void) = EnterFunction :
|
||||
@@ -8309,44 +8209,6 @@ ir.cpp:
|
||||
# 1539| v1539_11(void) = AliasedUse : ~m?
|
||||
# 1539| v1539_12(void) = ExitFunction :
|
||||
|
||||
# 1539| void StructuredBindingTupleRefGet::StructuredBindingTupleRefGet(StructuredBindingTupleRefGet const&)
|
||||
# 1539| Block 0
|
||||
# 1539| v1539_1(void) = EnterFunction :
|
||||
# 1539| mu1539_2(unknown) = AliasedDefinition :
|
||||
# 1539| mu1539_3(unknown) = InitializeNonLocal :
|
||||
# 1539| r1539_4(glval<unknown>) = VariableAddress[#this] :
|
||||
# 1539| mu1539_5(glval<StructuredBindingTupleRefGet>) = InitializeParameter[#this] : &:r1539_4
|
||||
# 1539| r1539_6(glval<StructuredBindingTupleRefGet>) = Load[#this] : &:r1539_4, ~m?
|
||||
# 1539| mu1539_7(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1539_6
|
||||
#-----| r0_1(glval<StructuredBindingTupleRefGet &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
#-----| mu0_2(StructuredBindingTupleRefGet &) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
|
||||
#-----| r0_3(StructuredBindingTupleRefGet &) = Load[(unnamed parameter 0)] : &:r0_1, ~m?
|
||||
#-----| mu0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
|
||||
# 1539| r1539_8(glval<int>) = FieldAddress[i] : mu1539_5
|
||||
# 1539| r1539_9(glval<StructuredBindingTupleRefGet &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1539| r1539_10(StructuredBindingTupleRefGet &) = Load[(unnamed parameter 0)] : &:r1539_9, ~m?
|
||||
# 1539| r1539_11(glval<int>) = FieldAddress[i] : r1539_10
|
||||
# 1539| r1539_12(int) = Load[?] : &:r1539_11, ~m?
|
||||
# 1539| mu1539_13(int) = Store[?] : &:r1539_8, r1539_12
|
||||
# 1539| r1539_14(glval<double>) = FieldAddress[d] : mu1539_5
|
||||
# 1539| r1539_15(glval<StructuredBindingTupleRefGet &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1539| r1539_16(StructuredBindingTupleRefGet &) = Load[(unnamed parameter 0)] : &:r1539_15, ~m?
|
||||
# 1539| r1539_17(glval<double>) = FieldAddress[d] : r1539_16
|
||||
# 1539| r1539_18(double) = Load[?] : &:r1539_17, ~m?
|
||||
# 1539| mu1539_19(double) = Store[?] : &:r1539_14, r1539_18
|
||||
# 1539| r1539_20(glval<int &>) = FieldAddress[r] : mu1539_5
|
||||
# 1539| r1539_21(glval<StructuredBindingTupleRefGet &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
# 1539| r1539_22(StructuredBindingTupleRefGet &) = Load[(unnamed parameter 0)] : &:r1539_21, ~m?
|
||||
# 1539| r1539_23(glval<int &>) = FieldAddress[r] : r1539_22
|
||||
# 1539| r1539_24(int &) = Load[?] : &:r1539_23, ~m?
|
||||
# 1539| mu1539_25(int &) = Store[?] : &:r1539_20, r1539_24
|
||||
# 1539| v1539_26(void) = NoOp :
|
||||
# 1539| v1539_27(void) = ReturnIndirection[#this] : &:r1539_6, ~m?
|
||||
#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, ~m?
|
||||
# 1539| v1539_28(void) = ReturnVoid :
|
||||
# 1539| v1539_29(void) = AliasedUse : ~m?
|
||||
# 1539| v1539_30(void) = ExitFunction :
|
||||
|
||||
# 1567| std::tuple_element<int 0, StructuredBindingTupleRefGet>::type& StructuredBindingTupleRefGet::get<int 0>()
|
||||
# 1567| Block 0
|
||||
# 1567| v1567_1(void) = EnterFunction :
|
||||
@@ -8980,25 +8842,6 @@ ir.cpp:
|
||||
# 1689| v1689_12(void) = AliasedUse : ~m?
|
||||
# 1689| v1689_13(void) = ExitFunction :
|
||||
|
||||
# 1693| int goto_on_same_line()
|
||||
# 1693| Block 0
|
||||
# 1693| v1693_1(void) = EnterFunction :
|
||||
# 1693| mu1693_2(unknown) = AliasedDefinition :
|
||||
# 1693| mu1693_3(unknown) = InitializeNonLocal :
|
||||
# 1694| r1694_1(glval<int>) = VariableAddress[x] :
|
||||
# 1694| r1694_2(int) = Constant[42] :
|
||||
# 1694| mu1694_3(int) = Store[x] : &:r1694_1, r1694_2
|
||||
# 1695| v1695_1(void) = NoOp :
|
||||
# 1695| v1695_2(void) = NoOp :
|
||||
# 1696| r1696_1(glval<int>) = VariableAddress[#return] :
|
||||
# 1696| r1696_2(glval<int>) = VariableAddress[x] :
|
||||
# 1696| r1696_3(int) = Load[x] : &:r1696_2, ~m?
|
||||
# 1696| mu1696_4(int) = Store[#return] : &:r1696_1, r1696_3
|
||||
# 1693| r1693_4(glval<int>) = VariableAddress[#return] :
|
||||
# 1693| v1693_5(void) = ReturnValue : &:r1693_4, ~m?
|
||||
# 1693| v1693_6(void) = AliasedUse : ~m?
|
||||
# 1693| v1693_7(void) = ExitFunction :
|
||||
|
||||
perf-regression.cpp:
|
||||
# 6| void Big::Big()
|
||||
# 6| Block 0
|
||||
|
||||
@@ -125,8 +125,8 @@
|
||||
| captures.cpp:22:19:22:19 | (unnamed constructor) |
|
||||
| captures.cpp:22:19:22:19 | (unnamed constructor) |
|
||||
| captures.cpp:22:19:22:19 | (unnamed constructor) |
|
||||
| captures.cpp:22:19:22:19 | (unnamed parameter 0) |
|
||||
| captures.cpp:22:19:22:19 | (unnamed parameter 0) |
|
||||
| captures.cpp:22:19:22:19 | Unknown literal |
|
||||
| captures.cpp:22:19:22:19 | Unknown literal |
|
||||
| captures.cpp:22:19:22:19 | constructor init of field x |
|
||||
| captures.cpp:22:19:22:19 | constructor init of field y |
|
||||
| captures.cpp:22:19:22:19 | declaration of (unnamed constructor) |
|
||||
@@ -135,8 +135,6 @@
|
||||
| captures.cpp:22:19:22:19 | definition of operator= |
|
||||
| captures.cpp:22:19:22:19 | operator= |
|
||||
| captures.cpp:22:19:22:19 | return ... |
|
||||
| captures.cpp:22:19:22:19 | x |
|
||||
| captures.cpp:22:19:22:19 | y |
|
||||
| captures.cpp:22:19:22:19 | { ... } |
|
||||
| captures.cpp:22:23:22:23 | definition of x |
|
||||
| captures.cpp:22:23:22:23 | x |
|
||||
@@ -187,13 +185,12 @@
|
||||
| end_pos.cpp:9:15:9:15 | (unnamed constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | (unnamed constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | (unnamed constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | (unnamed parameter 0) |
|
||||
| end_pos.cpp:9:15:9:15 | Unknown literal |
|
||||
| end_pos.cpp:9:15:9:15 | constructor init of field ii |
|
||||
| end_pos.cpp:9:15:9:15 | declaration of (unnamed constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | definition of (unnamed constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | definition of (unnamed constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | definition of operator= |
|
||||
| end_pos.cpp:9:15:9:15 | ii |
|
||||
| end_pos.cpp:9:15:9:15 | operator= |
|
||||
| end_pos.cpp:9:15:9:15 | return ... |
|
||||
| end_pos.cpp:9:15:9:15 | { ... } |
|
||||
|
||||
@@ -1498,8 +1498,6 @@ postWithInFlow
|
||||
| bad_asts.cpp:15:10:15:12 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:16:5:16:5 | s [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:16:5:16:5 | s [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:19:10:19:10 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:19:10:19:10 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:27:11:27:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| break_labels.c:3:9:3:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| break_labels.c:5:9:5:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -1628,15 +1626,11 @@ postWithInFlow
|
||||
| cpp11.cpp:60:15:60:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:65:10:65:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:65:19:65:45 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:65:20:65:20 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:65:35:65:43 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:77:19:77:21 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:77:19:77:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:11:82:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:11:82:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:17:82:17 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:17:82:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:17:82:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:17:82:55 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:17:82:55 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:82:17:82:55 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
|
||||
@@ -3,6 +3,7 @@ edges
|
||||
| tests.cpp:33:34:33:39 | call to getenv | tests.cpp:38:39:38:49 | environment indirection |
|
||||
| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:26:15:26:23 | ReturnValue |
|
||||
| tests.cpp:38:39:38:49 | environment indirection | tests.cpp:38:25:38:36 | strncat output argument |
|
||||
| tests.cpp:38:39:38:49 | environment indirection | tests.cpp:38:25:38:36 | strncat output argument |
|
||||
| tests.cpp:51:12:51:20 | call to badSource | tests.cpp:53:16:53:19 | data indirection |
|
||||
nodes
|
||||
| tests.cpp:26:15:26:23 | ReturnValue | semmle.label | ReturnValue |
|
||||
|
||||
@@ -2,55 +2,64 @@ edges
|
||||
| test.cpp:16:20:16:23 | argv | test.cpp:22:45:22:52 | userName indirection |
|
||||
| test.cpp:22:13:22:20 | sprintf output argument | test.cpp:23:12:23:19 | command1 indirection |
|
||||
| test.cpp:22:45:22:52 | userName indirection | test.cpp:22:13:22:20 | sprintf output argument |
|
||||
| test.cpp:22:45:22:52 | userName indirection | test.cpp:22:13:22:20 | sprintf output argument |
|
||||
| test.cpp:47:21:47:26 | call to getenv | test.cpp:50:35:50:43 | envCflags indirection |
|
||||
| test.cpp:50:11:50:17 | sprintf output argument | test.cpp:51:10:51:16 | command indirection |
|
||||
| test.cpp:50:35:50:43 | envCflags indirection | test.cpp:50:11:50:17 | sprintf output argument |
|
||||
| test.cpp:50:35:50:43 | envCflags indirection | test.cpp:50:11:50:17 | sprintf output argument |
|
||||
| test.cpp:62:9:62:16 | fread output argument | test.cpp:64:20:64:27 | filename indirection |
|
||||
| test.cpp:64:11:64:17 | strncat output argument | test.cpp:65:10:65:16 | command indirection |
|
||||
| test.cpp:64:20:64:27 | filename indirection | test.cpp:64:11:64:17 | strncat output argument |
|
||||
| test.cpp:64:20:64:27 | filename indirection | test.cpp:64:11:64:17 | strncat output argument |
|
||||
| test.cpp:82:9:82:16 | fread output argument | test.cpp:84:20:84:27 | filename indirection |
|
||||
| test.cpp:84:11:84:17 | strncat output argument | test.cpp:85:32:85:38 | command indirection |
|
||||
| test.cpp:84:20:84:27 | filename indirection | test.cpp:84:11:84:17 | strncat output argument |
|
||||
| test.cpp:84:20:84:27 | filename indirection | test.cpp:84:11:84:17 | strncat output argument |
|
||||
| test.cpp:91:9:91:16 | fread output argument | test.cpp:93:17:93:24 | filename indirection |
|
||||
| test.cpp:93:11:93:14 | strncat output argument | test.cpp:94:45:94:48 | path indirection |
|
||||
| test.cpp:93:17:93:24 | filename indirection | test.cpp:93:11:93:14 | strncat output argument |
|
||||
| test.cpp:93:17:93:24 | filename indirection | test.cpp:93:11:93:14 | strncat output argument |
|
||||
| test.cpp:106:20:106:25 | call to getenv | test.cpp:107:33:107:36 | path indirection |
|
||||
| test.cpp:107:31:107:31 | call to operator+ | test.cpp:108:18:108:22 | call to c_str indirection |
|
||||
| test.cpp:107:33:107:36 | path indirection | test.cpp:107:31:107:31 | call to operator+ |
|
||||
| test.cpp:107:33:107:36 | path indirection | test.cpp:107:31:107:31 | call to operator+ |
|
||||
| test.cpp:113:20:113:25 | call to getenv | test.cpp:114:19:114:22 | path indirection |
|
||||
| test.cpp:114:17:114:17 | Call | test.cpp:114:25:114:29 | call to c_str indirection |
|
||||
| test.cpp:114:19:114:22 | path indirection | test.cpp:114:17:114:17 | Call |
|
||||
| test.cpp:114:19:114:22 | path indirection | test.cpp:114:17:114:17 | Call |
|
||||
| test.cpp:119:20:119:25 | call to getenv | test.cpp:120:19:120:22 | path indirection |
|
||||
| test.cpp:120:17:120:17 | Call | test.cpp:120:10:120:30 | call to data indirection |
|
||||
| test.cpp:120:19:120:22 | path indirection | test.cpp:120:17:120:17 | Call |
|
||||
| test.cpp:120:19:120:22 | path indirection | test.cpp:120:17:120:17 | Call |
|
||||
| test.cpp:140:9:140:11 | fread output argument | test.cpp:142:31:142:33 | str indirection |
|
||||
| test.cpp:142:11:142:17 | sprintf output argument | test.cpp:143:10:143:16 | command indirection |
|
||||
| test.cpp:142:31:142:33 | str indirection | test.cpp:142:11:142:17 | sprintf output argument |
|
||||
| test.cpp:142:31:142:33 | str indirection | test.cpp:142:11:142:17 | sprintf output argument |
|
||||
| test.cpp:174:9:174:16 | fread output argument | test.cpp:177:20:177:27 | filename indirection |
|
||||
| test.cpp:174:9:174:16 | fread output argument | test.cpp:178:22:178:26 | flags indirection |
|
||||
| test.cpp:174:9:174:16 | fread output argument | test.cpp:180:22:180:29 | filename indirection |
|
||||
| test.cpp:177:13:177:17 | strncat output argument | test.cpp:183:32:183:38 | command indirection |
|
||||
| test.cpp:177:20:177:27 | filename indirection | test.cpp:177:13:177:17 | strncat output argument |
|
||||
| test.cpp:177:20:177:27 | filename indirection | test.cpp:177:13:177:17 | strncat output argument |
|
||||
| test.cpp:178:13:178:19 | strncat output argument | test.cpp:183:32:183:38 | command indirection |
|
||||
| test.cpp:178:22:178:26 | flags indirection | test.cpp:178:13:178:19 | strncat output argument |
|
||||
| test.cpp:178:22:178:26 | flags indirection | test.cpp:178:13:178:19 | strncat output argument |
|
||||
| test.cpp:180:13:180:19 | strncat output argument | test.cpp:183:32:183:38 | command indirection |
|
||||
| test.cpp:180:22:180:29 | filename indirection | test.cpp:180:13:180:19 | strncat output argument |
|
||||
| test.cpp:180:22:180:29 | filename indirection | test.cpp:180:13:180:19 | strncat output argument |
|
||||
| test.cpp:186:47:186:54 | *filename | test.cpp:187:18:187:25 | filename indirection |
|
||||
| test.cpp:186:47:186:54 | *filename | test.cpp:188:20:188:24 | flags indirection |
|
||||
| test.cpp:186:47:186:54 | filename | test.cpp:187:18:187:25 | filename indirection |
|
||||
| test.cpp:186:47:186:54 | filename | test.cpp:188:20:188:24 | flags indirection |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:187:18:187:25 | filename indirection | test.cpp:187:11:187:15 | strncat output argument |
|
||||
| test.cpp:187:18:187:25 | filename indirection | test.cpp:187:11:187:15 | strncat output argument |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:205:10:205:16 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | test.cpp:205:10:205:16 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | command [post update] |
|
||||
| test.cpp:188:20:188:24 | flags indirection | test.cpp:188:11:188:17 | strncat output argument |
|
||||
@@ -58,21 +67,9 @@ edges
|
||||
| test.cpp:194:9:194:16 | fread output argument | test.cpp:196:26:196:33 | filename |
|
||||
| test.cpp:194:9:194:16 | fread output argument | test.cpp:196:26:196:33 | filename indirection |
|
||||
| test.cpp:196:10:196:16 | command [post update] | test.cpp:198:32:198:38 | command indirection |
|
||||
| test.cpp:196:10:196:16 | command [post update] | test.cpp:198:32:198:38 | command indirection |
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename |
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:218:9:218:16 | fread output argument | test.cpp:220:19:220:26 | filename indirection |
|
||||
| test.cpp:218:9:218:16 | fread output argument | test.cpp:220:19:220:26 | filename indirection |
|
||||
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:222:32:222:38 | command indirection |
|
||||
| test.cpp:220:10:220:16 | strncat output argument | test.cpp:222:32:222:38 | command indirection |
|
||||
| test.cpp:220:19:220:26 | filename indirection | test.cpp:220:10:220:16 | strncat output argument |
|
||||
| test.cpp:220:19:220:26 | filename indirection | test.cpp:220:10:220:16 | strncat output argument |
|
||||
| test.cpp:220:19:220:26 | filename indirection | test.cpp:220:10:220:16 | strncat output argument |
|
||||
| test.cpp:220:19:220:26 | filename indirection | test.cpp:220:10:220:16 | strncat output argument |
|
||||
| test.cpp:205:10:205:16 | command [post update] | test.cpp:207:32:207:38 | command indirection |
|
||||
nodes
|
||||
| test.cpp:16:20:16:23 | argv | semmle.label | argv |
|
||||
| test.cpp:22:13:22:20 | sprintf output argument | semmle.label | sprintf output argument |
|
||||
@@ -118,48 +115,22 @@ nodes
|
||||
| test.cpp:180:13:180:19 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:180:22:180:29 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:183:32:183:38 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:183:32:183:38 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:183:32:183:38 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:186:47:186:54 | *filename | semmle.label | *filename |
|
||||
| test.cpp:186:47:186:54 | filename | semmle.label | filename |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:187:11:187:15 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:187:18:187:25 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:187:18:187:25 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:188:11:188:17 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:188:20:188:24 | flags indirection | semmle.label | flags indirection |
|
||||
| test.cpp:188:20:188:24 | flags indirection | semmle.label | flags indirection |
|
||||
| test.cpp:194:9:194:16 | fread output argument | semmle.label | fread output argument |
|
||||
| test.cpp:196:10:196:16 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:196:10:196:16 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename | semmle.label | filename |
|
||||
| test.cpp:196:26:196:33 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:198:32:198:38 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:198:32:198:38 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:218:9:218:16 | fread output argument | semmle.label | fread output argument |
|
||||
| test.cpp:220:10:220:16 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:220:10:220:16 | strncat output argument | semmle.label | strncat output argument |
|
||||
| test.cpp:220:19:220:26 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:220:19:220:26 | filename indirection | semmle.label | filename indirection |
|
||||
| test.cpp:222:32:222:38 | command indirection | semmle.label | command indirection |
|
||||
| test.cpp:205:10:205:16 | command [post update] | semmle.label | command [post update] |
|
||||
| test.cpp:207:32:207:38 | command indirection | semmle.label | command indirection |
|
||||
subpaths
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] |
|
||||
#select
|
||||
| test.cpp:23:12:23:19 | command1 | test.cpp:16:20:16:23 | argv | test.cpp:23:12:23:19 | command1 indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string) | test.cpp:16:20:16:23 | argv | user input (a command-line argument) | test.cpp:22:13:22:20 | sprintf output argument | sprintf output argument |
|
||||
| test.cpp:51:10:51:16 | command | test.cpp:47:21:47:26 | call to getenv | test.cpp:51:10:51:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string) | test.cpp:47:21:47:26 | call to getenv | user input (an environment variable) | test.cpp:50:11:50:17 | sprintf output argument | sprintf output argument |
|
||||
@@ -175,5 +146,5 @@ subpaths
|
||||
| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:174:9:174:16 | fread output argument | user input (String read by fread) | test.cpp:180:13:180:19 | strncat output argument | strncat output argument |
|
||||
| test.cpp:198:32:198:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:198:32:198:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:194:9:194:16 | fread output argument | user input (String read by fread) | test.cpp:187:11:187:15 | strncat output argument | strncat output argument |
|
||||
| test.cpp:198:32:198:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:198:32:198:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:194:9:194:16 | fread output argument | user input (String read by fread) | test.cpp:188:11:188:17 | strncat output argument | strncat output argument |
|
||||
| test.cpp:222:32:222:38 | command | test.cpp:218:9:218:16 | fread output argument | test.cpp:222:32:222:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:218:9:218:16 | fread output argument | user input (String read by fread) | test.cpp:220:10:220:16 | strncat output argument | strncat output argument |
|
||||
| test.cpp:222:32:222:38 | command | test.cpp:218:9:218:16 | fread output argument | test.cpp:222:32:222:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:218:9:218:16 | fread output argument | user input (String read by fread) | test.cpp:220:10:220:16 | strncat output argument | strncat output argument |
|
||||
| test.cpp:207:32:207:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:207:32:207:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:194:9:194:16 | fread output argument | user input (String read by fread) | test.cpp:187:11:187:15 | strncat output argument | strncat output argument |
|
||||
| test.cpp:207:32:207:38 | command | test.cpp:194:9:194:16 | fread output argument | test.cpp:207:32:207:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl | test.cpp:194:9:194:16 | fread output argument | user input (String read by fread) | test.cpp:188:11:188:17 | strncat output argument | strncat output argument |
|
||||
|
||||
@@ -199,7 +199,7 @@ void test17(FILE *f) {
|
||||
}
|
||||
|
||||
void test18() {
|
||||
// GOOD
|
||||
// GOOD [FALSE POSITIVE]
|
||||
char command[1000] = "ls ", flags[1000] = "-l", filename[1000] = ".";
|
||||
|
||||
concat(command, flags, filename);
|
||||
@@ -207,19 +207,4 @@ void test18() {
|
||||
execl("/bin/sh", "sh", "-c", command);
|
||||
}
|
||||
|
||||
#define CONCAT(COMMAND, FILENAME) \
|
||||
strncat(COMMAND, FILENAME, 1000); \
|
||||
strncat(COMMAND, " ", 1000); \
|
||||
strncat(COMMAND, FILENAME, 1000);
|
||||
|
||||
void test19(FILE *f) {
|
||||
// BAD: the user string is injected directly into a command
|
||||
char command[1000] = "mv ", filename[1000];
|
||||
fread(filename, 1, 1000, f);
|
||||
|
||||
CONCAT(command, filename)
|
||||
|
||||
execl("/bin/sh", "sh", "-c", command);
|
||||
}
|
||||
|
||||
// open question: do we want to report certain sources even when they're the start of the string?
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
edges
|
||||
| tests.c:57:21:57:28 | password | tests.c:70:70:70:77 | array to pointer conversion |
|
||||
nodes
|
||||
| tests.c:57:21:57:28 | password | semmle.label | password |
|
||||
| tests.c:70:70:70:77 | array to pointer conversion | semmle.label | array to pointer conversion |
|
||||
subpaths
|
||||
#select
|
||||
| tests.c:70:70:70:77 | array to pointer conversion | tests.c:57:21:57:28 | password | tests.c:70:70:70:77 | array to pointer conversion | This operation potentially exposes sensitive system data from $@. | tests.c:57:21:57:28 | password | password |
|
||||
@@ -1 +0,0 @@
|
||||
Security/CWE/CWE-497/PotentiallyExposedSystemData.ql
|
||||
@@ -67,6 +67,6 @@ void CWE535_Info_Exposure_Shell_Error__w32_char_01_bad()
|
||||
printLine("Unable to login.");
|
||||
}
|
||||
/* FLAW: Write sensitive data to stderr */
|
||||
fprintf(stderr, "User attempted access with password: %s\n", password);
|
||||
fprintf(stderr, "User attempted access with password: %s\n", password); // [NOT DETECTED]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,26 +2,15 @@ edges
|
||||
| tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:26 | (const char *)... |
|
||||
| tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:26 | (const char *)... |
|
||||
| tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:30 | (const char *)... |
|
||||
| tests2.cpp:66:13:66:18 | call to getenv | tests2.cpp:66:13:66:34 | (const char *)... |
|
||||
| tests2.cpp:78:18:78:38 | call to mysql_get_client_info | tests2.cpp:81:14:81:19 | (const char *)... |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info |
|
||||
| tests2.cpp:91:42:91:45 | str1 | tests2.cpp:93:14:93:17 | str1 |
|
||||
| tests2.cpp:101:8:101:15 | call to getpwuid | tests2.cpp:102:14:102:15 | pw |
|
||||
| tests2.cpp:109:3:109:4 | c1 [post update] [ptr] | tests2.cpp:111:14:111:15 | c1 [read] [ptr] |
|
||||
| tests2.cpp:109:6:109:8 | ptr [post update] | tests2.cpp:109:3:109:4 | c1 [post update] [ptr] |
|
||||
| tests2.cpp:109:12:109:17 | call to getenv | tests2.cpp:109:6:109:8 | ptr [post update] |
|
||||
| tests2.cpp:111:14:111:15 | c1 [read] [ptr] | tests2.cpp:111:14:111:19 | (const char *)... |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | (const void *)... |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | path |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | (const void *)... |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | path |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | (const void *)... |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | path |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | (const void *)... |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | path |
|
||||
| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | (const void *)... |
|
||||
| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf |
|
||||
| tests2.cpp:76:18:76:38 | call to mysql_get_client_info | tests2.cpp:79:14:79:19 | (const char *)... |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info |
|
||||
| tests2.cpp:89:42:89:45 | str1 | tests2.cpp:91:14:91:17 | str1 |
|
||||
| tests2.cpp:99:8:99:15 | call to getpwuid | tests2.cpp:100:14:100:15 | pw |
|
||||
| tests2.cpp:107:3:107:4 | c1 [post update] [ptr] | tests2.cpp:109:14:109:15 | c1 [read] [ptr] |
|
||||
| tests2.cpp:107:6:107:8 | ptr [post update] | tests2.cpp:107:3:107:4 | c1 [post update] [ptr] |
|
||||
| tests2.cpp:107:12:107:17 | call to getenv | tests2.cpp:107:6:107:8 | ptr [post update] |
|
||||
| tests2.cpp:109:14:109:15 | c1 [read] [ptr] | tests2.cpp:109:14:109:19 | (const char *)... |
|
||||
nodes
|
||||
| tests2.cpp:63:13:63:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:63:13:63:18 | call to getenv | semmle.label | call to getenv |
|
||||
@@ -32,49 +21,27 @@ nodes
|
||||
| tests2.cpp:65:13:65:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:65:13:65:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:65:13:65:30 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:66:13:66:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:66:13:66:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:66:13:66:34 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:78:18:78:38 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:81:14:81:19 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:91:42:91:45 | str1 | semmle.label | str1 |
|
||||
| tests2.cpp:93:14:93:17 | str1 | semmle.label | str1 |
|
||||
| tests2.cpp:101:8:101:15 | call to getpwuid | semmle.label | call to getpwuid |
|
||||
| tests2.cpp:102:14:102:15 | pw | semmle.label | pw |
|
||||
| tests2.cpp:109:3:109:4 | c1 [post update] [ptr] | semmle.label | c1 [post update] [ptr] |
|
||||
| tests2.cpp:109:6:109:8 | ptr [post update] | semmle.label | ptr [post update] |
|
||||
| tests2.cpp:109:12:109:17 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:111:14:111:15 | c1 [read] [ptr] | semmle.label | c1 [read] [ptr] |
|
||||
| tests2.cpp:111:14:111:19 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests_sockets.cpp:26:15:26:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests_sockets.cpp:39:19:39:22 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sockets.cpp:39:19:39:22 | path | semmle.label | path |
|
||||
| tests_sockets.cpp:43:20:43:23 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sockets.cpp:43:20:43:23 | path | semmle.label | path |
|
||||
| tests_sockets.cpp:63:15:63:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests_sockets.cpp:76:19:76:22 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sockets.cpp:76:19:76:22 | path | semmle.label | path |
|
||||
| tests_sockets.cpp:80:20:80:23 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sockets.cpp:80:20:80:23 | path | semmle.label | path |
|
||||
| tests_sysconf.cpp:36:21:36:27 | confstr output argument | semmle.label | confstr output argument |
|
||||
| tests_sysconf.cpp:39:19:39:25 | (const void *)... | semmle.label | (const void *)... |
|
||||
| tests_sysconf.cpp:39:19:39:25 | pathbuf | semmle.label | pathbuf |
|
||||
| tests2.cpp:76:18:76:38 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
|
||||
| tests2.cpp:79:14:79:19 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests2.cpp:89:42:89:45 | str1 | semmle.label | str1 |
|
||||
| tests2.cpp:91:14:91:17 | str1 | semmle.label | str1 |
|
||||
| tests2.cpp:99:8:99:15 | call to getpwuid | semmle.label | call to getpwuid |
|
||||
| tests2.cpp:100:14:100:15 | pw | semmle.label | pw |
|
||||
| tests2.cpp:107:3:107:4 | c1 [post update] [ptr] | semmle.label | c1 [post update] [ptr] |
|
||||
| tests2.cpp:107:6:107:8 | ptr [post update] | semmle.label | ptr [post update] |
|
||||
| tests2.cpp:107:12:107:17 | call to getenv | semmle.label | call to getenv |
|
||||
| tests2.cpp:109:14:109:15 | c1 [read] [ptr] | semmle.label | c1 [read] [ptr] |
|
||||
| tests2.cpp:109:14:109:19 | (const char *)... | semmle.label | (const char *)... |
|
||||
subpaths
|
||||
#select
|
||||
| tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:63:13:63:18 | call to getenv | call to getenv |
|
||||
| tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:64:13:64:18 | call to getenv | call to getenv |
|
||||
| tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:65:13:65:18 | call to getenv | call to getenv |
|
||||
| tests2.cpp:66:13:66:18 | call to getenv | tests2.cpp:66:13:66:18 | call to getenv | tests2.cpp:66:13:66:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:66:13:66:18 | call to getenv | call to getenv |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:81:14:81:19 | (const char *)... | tests2.cpp:78:18:78:38 | call to mysql_get_client_info | tests2.cpp:81:14:81:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:78:18:78:38 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:93:14:93:17 | str1 | tests2.cpp:91:42:91:45 | str1 | tests2.cpp:93:14:93:17 | str1 | This operation exposes system data from $@. | tests2.cpp:91:42:91:45 | str1 | str1 |
|
||||
| tests2.cpp:102:14:102:15 | pw | tests2.cpp:101:8:101:15 | call to getpwuid | tests2.cpp:102:14:102:15 | pw | This operation exposes system data from $@. | tests2.cpp:101:8:101:15 | call to getpwuid | call to getpwuid |
|
||||
| tests2.cpp:111:14:111:19 | (const char *)... | tests2.cpp:109:12:109:17 | call to getenv | tests2.cpp:111:14:111:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:109:12:109:17 | call to getenv | call to getenv |
|
||||
| tests_sockets.cpp:39:19:39:22 | path | tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | path | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv | call to getenv |
|
||||
| tests_sockets.cpp:43:20:43:23 | path | tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | path | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv | call to getenv |
|
||||
| tests_sockets.cpp:76:19:76:22 | path | tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | path | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv | call to getenv |
|
||||
| tests_sockets.cpp:80:20:80:23 | path | tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | path | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv | call to getenv |
|
||||
| tests_sysconf.cpp:39:19:39:25 | pathbuf | tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf | This operation exposes system data from $@. | tests_sysconf.cpp:36:21:36:27 | confstr output argument | confstr output argument |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:78:14:78:34 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:79:14:79:19 | (const char *)... | tests2.cpp:76:18:76:38 | call to mysql_get_client_info | tests2.cpp:79:14:79:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:76:18:76:38 | call to mysql_get_client_info | call to mysql_get_client_info |
|
||||
| tests2.cpp:91:14:91:17 | str1 | tests2.cpp:89:42:89:45 | str1 | tests2.cpp:91:14:91:17 | str1 | This operation exposes system data from $@. | tests2.cpp:89:42:89:45 | str1 | str1 |
|
||||
| tests2.cpp:100:14:100:15 | pw | tests2.cpp:99:8:99:15 | call to getpwuid | tests2.cpp:100:14:100:15 | pw | This operation exposes system data from $@. | tests2.cpp:99:8:99:15 | call to getpwuid | call to getpwuid |
|
||||
| tests2.cpp:109:14:109:19 | (const char *)... | tests2.cpp:107:12:107:17 | call to getenv | tests2.cpp:109:14:109:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:107:12:107:17 | call to getenv | call to getenv |
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
edges
|
||||
| tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:36 | (const char *)... |
|
||||
| tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:36 | (const char *)... |
|
||||
| tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:36 | (const char *)... |
|
||||
| tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:39 | (const char_type *)... |
|
||||
| tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:62 | (const char_type *)... |
|
||||
| tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:64 | (const char *)... |
|
||||
| tests.cpp:86:29:86:31 | *msg | tests.cpp:88:15:88:17 | msg |
|
||||
| tests.cpp:86:29:86:31 | msg | tests.cpp:88:15:88:17 | msg |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | (const char *)... |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | call to getenv |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | call to getenv indirection |
|
||||
| tests.cpp:97:13:97:34 | call to getenv | tests.cpp:86:29:86:31 | msg |
|
||||
| tests.cpp:97:13:97:34 | call to getenv indirection | tests.cpp:86:29:86:31 | *msg |
|
||||
| tests.cpp:107:30:107:32 | *msg | tests.cpp:111:15:111:17 | tmp |
|
||||
| tests.cpp:107:30:107:32 | msg | tests.cpp:111:15:111:17 | tmp |
|
||||
| tests.cpp:114:30:114:32 | *msg | tests.cpp:119:7:119:12 | (const char *)... |
|
||||
| tests.cpp:114:30:114:32 | msg | tests.cpp:119:7:119:12 | (const char *)... |
|
||||
| tests.cpp:122:30:122:32 | *msg | tests.cpp:124:15:124:17 | msg |
|
||||
| tests.cpp:122:30:122:32 | msg | tests.cpp:124:15:124:17 | msg |
|
||||
| tests.cpp:131:14:131:19 | call to getenv | tests.cpp:131:14:131:35 | call to getenv |
|
||||
| tests.cpp:131:14:131:19 | call to getenv | tests.cpp:131:14:131:35 | call to getenv indirection |
|
||||
| tests.cpp:131:14:131:35 | call to getenv | tests.cpp:107:30:107:32 | msg |
|
||||
| tests.cpp:131:14:131:35 | call to getenv indirection | tests.cpp:107:30:107:32 | *msg |
|
||||
| tests.cpp:132:14:132:19 | call to getenv | tests.cpp:132:14:132:35 | call to getenv |
|
||||
| tests.cpp:132:14:132:19 | call to getenv | tests.cpp:132:14:132:35 | call to getenv indirection |
|
||||
| tests.cpp:132:14:132:35 | call to getenv | tests.cpp:114:30:114:32 | msg |
|
||||
| tests.cpp:132:14:132:35 | call to getenv indirection | tests.cpp:114:30:114:32 | *msg |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | (const char *)... |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | call to getenv |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | call to getenv indirection |
|
||||
| tests.cpp:133:14:133:35 | call to getenv | tests.cpp:122:30:122:32 | msg |
|
||||
| tests.cpp:133:14:133:35 | call to getenv indirection | tests.cpp:122:30:122:32 | *msg |
|
||||
| tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:18:29:18:31 | pwd |
|
||||
| tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:19:26:19:28 | pwd |
|
||||
nodes
|
||||
| tests.cpp:48:15:48:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:48:15:48:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:48:15:48:36 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:49:15:49:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:49:15:49:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:49:15:49:36 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:50:15:50:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:50:15:50:20 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:50:15:50:36 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:57:18:57:23 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:57:18:57:23 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:57:18:57:39 | (const char_type *)... | semmle.label | (const char_type *)... |
|
||||
| tests.cpp:58:41:58:46 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:58:41:58:46 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:58:41:58:62 | (const char_type *)... | semmle.label | (const char_type *)... |
|
||||
| tests.cpp:59:43:59:48 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:59:43:59:48 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:59:43:59:64 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:86:29:86:31 | *msg | semmle.label | *msg |
|
||||
| tests.cpp:86:29:86:31 | msg | semmle.label | msg |
|
||||
| tests.cpp:88:15:88:17 | msg | semmle.label | msg |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:97:13:97:34 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:97:13:97:34 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:97:13:97:34 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests.cpp:107:30:107:32 | *msg | semmle.label | *msg |
|
||||
| tests.cpp:107:30:107:32 | msg | semmle.label | msg |
|
||||
| tests.cpp:111:15:111:17 | tmp | semmle.label | tmp |
|
||||
| tests.cpp:114:30:114:32 | *msg | semmle.label | *msg |
|
||||
| tests.cpp:114:30:114:32 | msg | semmle.label | msg |
|
||||
| tests.cpp:119:7:119:12 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:122:30:122:32 | *msg | semmle.label | *msg |
|
||||
| tests.cpp:122:30:122:32 | msg | semmle.label | msg |
|
||||
| tests.cpp:124:15:124:17 | msg | semmle.label | msg |
|
||||
| tests.cpp:131:14:131:19 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:131:14:131:35 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:131:14:131:35 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests.cpp:132:14:132:19 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:132:14:132:35 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:132:14:132:35 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:133:14:133:35 | (const char *)... | semmle.label | (const char *)... |
|
||||
| tests.cpp:133:14:133:35 | call to getenv | semmle.label | call to getenv |
|
||||
| tests.cpp:133:14:133:35 | call to getenv indirection | semmle.label | call to getenv indirection |
|
||||
| tests_passwd.cpp:16:8:16:15 | call to getpwnam | semmle.label | call to getpwnam |
|
||||
| tests_passwd.cpp:18:29:18:31 | pwd | semmle.label | pwd |
|
||||
| tests_passwd.cpp:19:26:19:28 | pwd | semmle.label | pwd |
|
||||
subpaths
|
||||
#select
|
||||
| tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:20 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:48:15:48:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:48:15:48:36 | (const char *)... | tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:36 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:48:15:48:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:20 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:49:15:49:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:49:15:49:36 | (const char *)... | tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:36 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:49:15:49:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:20 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:50:15:50:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:50:15:50:36 | (const char *)... | tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:36 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:50:15:50:20 | call to getenv | call to getenv |
|
||||
| tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:23 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:57:18:57:23 | call to getenv | call to getenv |
|
||||
| tests.cpp:57:18:57:39 | (const char_type *)... | tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:39 | (const char_type *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:57:18:57:23 | call to getenv | call to getenv |
|
||||
| tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:46 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:58:41:58:46 | call to getenv | call to getenv |
|
||||
| tests.cpp:58:41:58:62 | (const char_type *)... | tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:62 | (const char_type *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:58:41:58:46 | call to getenv | call to getenv |
|
||||
| tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:48 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:59:43:59:48 | call to getenv | call to getenv |
|
||||
| tests.cpp:59:43:59:64 | (const char *)... | tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:64 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:59:43:59:48 | call to getenv | call to getenv |
|
||||
| tests.cpp:88:15:88:17 | msg | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:88:15:88:17 | msg | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv |
|
||||
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:18 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv |
|
||||
| tests.cpp:97:13:97:34 | (const char *)... | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv |
|
||||
| tests.cpp:111:15:111:17 | tmp | tests.cpp:131:14:131:19 | call to getenv | tests.cpp:111:15:111:17 | tmp | This operation potentially exposes sensitive system data from $@. | tests.cpp:131:14:131:19 | call to getenv | call to getenv |
|
||||
| tests.cpp:119:7:119:12 | (const char *)... | tests.cpp:132:14:132:19 | call to getenv | tests.cpp:119:7:119:12 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:132:14:132:19 | call to getenv | call to getenv |
|
||||
| tests.cpp:124:15:124:17 | msg | tests.cpp:133:14:133:19 | call to getenv | tests.cpp:124:15:124:17 | msg | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv | call to getenv |
|
||||
| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:19 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv | call to getenv |
|
||||
| tests.cpp:133:14:133:35 | (const char *)... | tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv | call to getenv |
|
||||
| tests_passwd.cpp:18:29:18:31 | pwd | tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:18:29:18:31 | pwd | This operation potentially exposes sensitive system data from $@. | tests_passwd.cpp:16:8:16:15 | call to getpwnam | call to getpwnam |
|
||||
| tests_passwd.cpp:19:26:19:28 | pwd | tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:19:26:19:28 | pwd | This operation potentially exposes sensitive system data from $@. | tests_passwd.cpp:16:8:16:15 | call to getpwnam | call to getpwnam |
|
||||
@@ -1 +0,0 @@
|
||||
Security/CWE/CWE-497/PotentiallyExposedSystemData.ql
|
||||
@@ -1,134 +0,0 @@
|
||||
// test cases for rule CWE-497
|
||||
|
||||
// library functions etc
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
|
||||
typedef struct {} FILE;
|
||||
FILE *stdout;
|
||||
|
||||
int puts(const char *s);
|
||||
int printf(const char *format, ...);
|
||||
int sprintf(char *s, const char *format, ...);
|
||||
int snprintf(char *s, size_t n, const char *format, ...);
|
||||
size_t strlen(const char *s);
|
||||
char *getenv(const char *name);
|
||||
|
||||
extern std::ostream someotherostream;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define NULL (0)
|
||||
|
||||
// test cases
|
||||
|
||||
void test1()
|
||||
{
|
||||
std::ostream cout_copy = std::cout;
|
||||
|
||||
std::cout << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable
|
||||
std::cerr << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable
|
||||
std::clog << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable
|
||||
someotherostream << getenv("SECRET_TOKEN"); // GOOD: not output
|
||||
cout_copy << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable [NOT DETECTED]
|
||||
|
||||
std::cout << getenv("USERPROFILE"); // BAD: outputs PATH environment variable [NOT DETECTED]
|
||||
std::cout << getenv("PATH"); // BAD: outputs PATH environment variable [NOT DETECTED]
|
||||
|
||||
std::cout.write(getenv("SECRET_TOKEN"), strlen(getenv("SECRET_TOKEN"))); // BAD: outputs SECRET_TOKEN environment variable
|
||||
(std::cout << "SECRET_TOKEN = ").write(getenv("SECRET_TOKEN"), strlen(getenv("SECRET_TOKEN"))); // BAD: outputs SECRET_TOKEN environment variable
|
||||
std::cout.write("SECRET_TOKEN = ", 7) << getenv("SECRET_TOKEN"); // BAD: outputs SECRET_TOKEN environment variable
|
||||
}
|
||||
|
||||
char *global_token = getenv("SECRET_TOKEN");
|
||||
char *global_other = "Hello, world!";
|
||||
|
||||
void test2(bool cond)
|
||||
{
|
||||
char *maybe;
|
||||
|
||||
maybe = cond ? global_token : global_other;
|
||||
|
||||
printf("token = '%s'\n", global_token); // BAD: outputs SECRET_TOKEN environment variable [NOT DETECTED]
|
||||
printf("other = '%s'\n", global_other);
|
||||
printf("maybe = '%s'\n", maybe); // BAD: may output SECRET_TOKEN environment variable [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test3()
|
||||
{
|
||||
char *path_string = getenv("PATH");
|
||||
char buf[4096];
|
||||
|
||||
// ...
|
||||
snprintf(buf, 4096, "invalid path '%s'\n", path_string);
|
||||
puts(buf); // BAD: outputs PATH environment variable [NOT DETECTED]
|
||||
}
|
||||
|
||||
void myOutputFn(const char *msg)
|
||||
{
|
||||
printf("%s", msg);
|
||||
}
|
||||
|
||||
void myOtherFn(const char *msg)
|
||||
{
|
||||
}
|
||||
|
||||
void test4()
|
||||
{
|
||||
myOutputFn(getenv("SECRET_TOKEN")); // BAD: outputs the SECRET_TOKEN environment variable
|
||||
myOtherFn(getenv("SECRET_TOKEN")); // GOOD: does not output anything.
|
||||
}
|
||||
|
||||
void myOutputFn2(const char *msg)
|
||||
{
|
||||
msg = "";
|
||||
printf("%s", msg);
|
||||
}
|
||||
|
||||
void myOutputFn3(const char *msg)
|
||||
{
|
||||
const char *tmp = msg;
|
||||
|
||||
printf("%s", tmp);
|
||||
}
|
||||
|
||||
void myOutputFn4(const char *msg)
|
||||
{
|
||||
char buffer[4096];
|
||||
|
||||
sprintf(buffer, "log: %s\n", msg);
|
||||
puts(buffer);
|
||||
}
|
||||
|
||||
void myOutputFn5(const char *msg)
|
||||
{
|
||||
printf("%s", msg);
|
||||
msg = "";
|
||||
}
|
||||
|
||||
void test5()
|
||||
{
|
||||
myOutputFn2(getenv("SECRET_TOKEN")); // GOOD: myOutputFn2 doesn't actually output the parameter
|
||||
myOutputFn3(getenv("SECRET_TOKEN")); // BAD: outputs the SECRET_TOKEN environment variable
|
||||
myOutputFn4(getenv("SECRET_TOKEN")); // BAD: outputs the SECRET_TOKEN environment variable
|
||||
myOutputFn5(getenv("SECRET_TOKEN")); // BAD: outputs the SECRET_TOKEN environment variable
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
namespace std
|
||||
{
|
||||
typedef size_t streamsize;
|
||||
|
||||
template<class charT> struct char_traits;
|
||||
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
typedef charT char_type;
|
||||
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
|
||||
|
||||
basic_ostream<charT, traits>& operator<<(int n);
|
||||
};
|
||||
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
|
||||
|
||||
typedef basic_ostream<char> ostream;
|
||||
|
||||
extern ostream cout;
|
||||
extern ostream cerr;
|
||||
extern ostream clog;
|
||||
}
|
||||
@@ -2,24 +2,24 @@
|
||||
|
||||
// library functions etc
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
char *getenv(const char *name);
|
||||
char *strcpy(char *s1, const char *s2);
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<class charT> struct char_traits;
|
||||
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
};
|
||||
|
||||
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
|
||||
|
||||
typedef basic_ostream<char> ostream;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern ostream cout;
|
||||
}
|
||||
|
||||
int socket(int p1, int p2, int p3);
|
||||
void send(int sock, const char *buffer, int p3, int p4);
|
||||
@@ -63,12 +63,10 @@ void test1()
|
||||
send(sock, getenv("HOME"), val(), val()); // BAD
|
||||
send(sock, getenv("PATH"), val(), val()); // BAD
|
||||
send(sock, getenv("USERNAME"), val(), val()); // BAD
|
||||
send(sock, getenv("APP_PASSWORD"), val(), val()); // BAD
|
||||
send(sock, getenv("HARMLESS"), val(), val()); // GOOD: harmless information
|
||||
send(sock, "HOME", val(), val()); // GOOD: not system data
|
||||
send(sock, "PATH", val(), val()); // GOOD: not system data
|
||||
send(sock, "USERNAME", val(), val()); // GOOD: not system data
|
||||
send(sock, "APP_PASSWORD", val(), val()); // GOOD: not system data
|
||||
send(sock, "HARMLESS", val(), val()); // GOOD: not system data
|
||||
|
||||
// tests for `mysql_get_client_info`, including via a global
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
int printf(const char *format, ...);
|
||||
|
||||
struct passwd {
|
||||
char *pw_passwd;
|
||||
char *pw_dir;
|
||||
// ...
|
||||
};
|
||||
|
||||
struct passwd *getpwnam(const char *name);
|
||||
|
||||
void test6(char *username)
|
||||
{
|
||||
passwd *pwd;
|
||||
|
||||
pwd = getpwnam(username);
|
||||
|
||||
printf("pw_passwd = %s\n", pwd->pw_passwd); // BAD
|
||||
printf("pw_dir = %s\n", pwd->pw_dir); // BAD
|
||||
printf("sizeof(passwd) = %i\n", sizeof(passwd)); // GOOD
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
size_t strlen(const char *s);
|
||||
char *getenv(const char *name);
|
||||
|
||||
#define AF_INET (2)
|
||||
#define SOCK_STREAM (1)
|
||||
|
||||
struct sockaddr {
|
||||
int sa_family;
|
||||
|
||||
// ...
|
||||
};
|
||||
|
||||
int socket(int domain, int type, int protocol);
|
||||
int connect(int socket, const struct sockaddr *address, size_t address_len);
|
||||
size_t send(int socket, const void *buffer, size_t length, int flags);
|
||||
int write(int handle, const void *buffer, size_t length);
|
||||
|
||||
void test_sockets1()
|
||||
{
|
||||
int sockfd;
|
||||
sockaddr addr_remote;
|
||||
char *msg = "Hello, world!";
|
||||
char *path = getenv("PATH");
|
||||
|
||||
// create socket
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) return;
|
||||
|
||||
// connect socket to a remote address
|
||||
addr_remote.sa_family = AF_INET;
|
||||
// ...
|
||||
if (connect(sockfd, &addr_remote, sizeof(addr_remote)) != 0) return;
|
||||
|
||||
// send something using 'send'
|
||||
if (send(sockfd, msg, strlen(msg) + 1, 0) < 0) return; // GOOD
|
||||
if (send(sockfd, path, strlen(path) + 1, 0) < 0) return; // BAD
|
||||
|
||||
// send something using 'write'
|
||||
if (write(sockfd, msg, strlen(msg) + 1) < 0) return; // GOOD
|
||||
if (write(sockfd, path, strlen(path) + 1) < 0) return; // BAD
|
||||
|
||||
// clean up
|
||||
// ...
|
||||
}
|
||||
|
||||
int mksocket()
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void test_sockets2()
|
||||
{
|
||||
int sockfd;
|
||||
sockaddr addr_remote;
|
||||
char *msg = "Hello, world!";
|
||||
char *path = getenv("PATH");
|
||||
|
||||
// create socket
|
||||
sockfd = mksocket();
|
||||
if (sockfd < 0) return;
|
||||
|
||||
// connect socket to a remote address
|
||||
addr_remote.sa_family = AF_INET;
|
||||
// ...
|
||||
if (connect(sockfd, &addr_remote, sizeof(addr_remote)) != 0) return;
|
||||
|
||||
// send something using 'send'
|
||||
if (send(sockfd, msg, strlen(msg) + 1, 0) < 0) return; // GOOD
|
||||
if (send(sockfd, path, strlen(path) + 1, 0) < 0) return; // BAD
|
||||
|
||||
// send something using 'write'
|
||||
if (write(sockfd, msg, strlen(msg) + 1) < 0) return; // GOOD
|
||||
if (write(sockfd, path, strlen(path) + 1) < 0) return; // BAD
|
||||
|
||||
// clean up
|
||||
// ...
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
typedef signed long ssize_t;
|
||||
void *malloc(size_t size);
|
||||
#define NULL (0)
|
||||
|
||||
int printf(const char *format, ...);
|
||||
size_t strlen(const char *s);
|
||||
|
||||
int get_fd();
|
||||
int write(int handle, const void *buffer, size_t length);
|
||||
|
||||
long sysconf(int name);
|
||||
#define _SC_CHILD_MAX (2)
|
||||
|
||||
size_t confstr(int name, char *buffer, size_t length);
|
||||
#define _CS_PATH (1)
|
||||
|
||||
void test_sc_1()
|
||||
{
|
||||
int value = sysconf(_SC_CHILD_MAX);
|
||||
|
||||
printf("_SC_CHILD_MAX = %i\n", _SC_CHILD_MAX); // GOOD
|
||||
printf("_SC_CHILD_MAX = %i\n", value); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_sc_2()
|
||||
{
|
||||
char *pathbuf;
|
||||
size_t n;
|
||||
|
||||
n = confstr(_CS_PATH, NULL, (size_t)0);
|
||||
pathbuf = (char *)malloc(n);
|
||||
if (pathbuf != NULL)
|
||||
{
|
||||
confstr(_CS_PATH, pathbuf, n);
|
||||
|
||||
printf("path: %s", pathbuf); // BAD [NOT DETECTED]
|
||||
write(get_fd(), pathbuf, strlen(pathbuf)); // BAD
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
/** Provides classes for collections. */
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.frameworks.system.Collections
|
||||
|
||||
private string modifyMethodName() {
|
||||
result =
|
||||
@@ -67,12 +66,6 @@ class CollectionType extends RefType {
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `t` is a collection type. */
|
||||
predicate isCollectionType(ValueOrRefType t) {
|
||||
t.getABaseType*() instanceof SystemCollectionsIEnumerableInterface and
|
||||
not t instanceof StringType
|
||||
}
|
||||
|
||||
/** An object creation that creates an empty collection. */
|
||||
class EmptyCollectionCreation extends ObjectCreation {
|
||||
EmptyCollectionCreation() {
|
||||
|
||||
@@ -161,13 +161,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
this.getASuccessor() = result and
|
||||
not this.immediatelyDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.dominanceFrontier() |
|
||||
this.immediatelyDominates(prev) and
|
||||
not this.immediatelyDominates(result)
|
||||
)
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,13 +201,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postDominanceFrontier() {
|
||||
this.getAPredecessor() = result and
|
||||
not this.immediatelyPostDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.postDominanceFrontier() |
|
||||
this.immediatelyPostDominates(prev) and
|
||||
not this.immediatelyPostDominates(result)
|
||||
)
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -161,13 +161,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
this.getASuccessor() = result and
|
||||
not this.immediatelyDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.dominanceFrontier() |
|
||||
this.immediatelyDominates(prev) and
|
||||
not this.immediatelyDominates(result)
|
||||
)
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,13 +201,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postDominanceFrontier() {
|
||||
this.getAPredecessor() = result and
|
||||
not this.immediatelyPostDominates(result)
|
||||
or
|
||||
exists(IRBlock prev | result = prev.postDominanceFrontier() |
|
||||
this.immediatelyPostDominates(prev) and
|
||||
not this.immediatelyPostDominates(result)
|
||||
)
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.csharp.commons.Util
|
||||
private import semmle.code.csharp.commons.Collections
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
|
||||
|
||||
@@ -29,8 +28,14 @@ predicate asPartialModel = Csv::asPartialModel/1;
|
||||
*/
|
||||
predicate isRelevantType(Type t) { not t instanceof Enum }
|
||||
|
||||
private predicate isPrimitiveTypeUsedForBulkData(Type t) {
|
||||
t.getName().regexpMatch("byte|char|Byte|Char")
|
||||
}
|
||||
|
||||
private string parameterAccess(Parameter p) {
|
||||
if isCollectionType(p.getType())
|
||||
if
|
||||
p.getType() instanceof ArrayType and
|
||||
not isPrimitiveTypeUsedForBulkData(p.getType().(ArrayType).getElementType())
|
||||
then result = "Argument[" + p.getPosition() + "].Element"
|
||||
else result = "Argument[" + p.getPosition() + "]"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
| NoSummaries;PublicClassFlow;false;PublicReturn;(System.Int32);Argument[0];ReturnValue;taint |
|
||||
| Summaries;BaseClassFlow;true;ReturnParam;(System.Int32);Argument[0];ReturnValue;taint |
|
||||
| Summaries;BasicFlow;false;AssignFieldToArray;(System.Object[]);Argument[Qualifier];Argument[0].Element;taint |
|
||||
| Summaries;BasicFlow;false;AssignToArray;(System.Int32,System.Int32[]);Argument[0];Argument[1].Element;taint |
|
||||
| Summaries;BasicFlow;false;ReturnArrayElement;(System.Int32[]);Argument[0].Element;ReturnValue;taint |
|
||||
| Summaries;BasicFlow;false;ReturnField;();Argument[Qualifier];ReturnValue;taint |
|
||||
| Summaries;BasicFlow;false;ReturnParam0;(System.String,System.Object);Argument[0];ReturnValue;taint |
|
||||
| Summaries;BasicFlow;false;ReturnParam1;(System.String,System.Object);Argument[1];ReturnValue;taint |
|
||||
@@ -8,23 +9,3 @@
|
||||
| Summaries;BasicFlow;false;ReturnSubstring;(System.String);Argument[0];ReturnValue;taint |
|
||||
| Summaries;BasicFlow;false;ReturnThis;(System.Object);Argument[Qualifier];ReturnValue;value |
|
||||
| Summaries;BasicFlow;false;SetField;(System.String);Argument[0];Argument[Qualifier];taint |
|
||||
| Summaries;CollectionFlow;false;AddFieldToList;(System.Collections.Generic.List<System.String>);Argument[Qualifier];Argument[0].Element;taint |
|
||||
| Summaries;CollectionFlow;false;AddToList;(System.Collections.Generic.List<System.Object>,System.Object);Argument[1];Argument[0].Element;taint |
|
||||
| Summaries;CollectionFlow;false;AssignFieldToArray;(System.Object[]);Argument[Qualifier];Argument[0].Element;taint |
|
||||
| Summaries;CollectionFlow;false;AssignToArray;(System.Int32,System.Int32[]);Argument[0];Argument[1].Element;taint |
|
||||
| Summaries;CollectionFlow;false;ReturnArrayElement;(System.Int32[]);Argument[0].Element;ReturnValue;taint |
|
||||
| Summaries;CollectionFlow;false;ReturnFieldInAList;();Argument[Qualifier];ReturnValue;taint |
|
||||
| Summaries;CollectionFlow;false;ReturnListElement;(System.Collections.Generic.List<System.Object>);Argument[0].Element;ReturnValue;taint |
|
||||
| Summaries;DerivedClass1Flow;false;ReturnParam1;(System.Int32,System.Int32);Argument[1];ReturnValue;taint |
|
||||
| Summaries;DerivedClass2Flow;false;ReturnParam0;(System.Int32,System.Int32);Argument[0];ReturnValue;taint |
|
||||
| Summaries;DerivedClass2Flow;false;ReturnParam;(System.Int32);Argument[0];ReturnValue;taint |
|
||||
| Summaries;GenericFlow<>;false;AddFieldToGenericList;(System.Collections.Generic.List<T>);Argument[Qualifier];Argument[0].Element;taint |
|
||||
| Summaries;GenericFlow<>;false;AddToGenericList<>;(System.Collections.Generic.List<S>,S);Argument[1];Argument[0].Element;taint |
|
||||
| Summaries;GenericFlow<>;false;ReturnFieldInGenericList;();Argument[Qualifier];ReturnValue;taint |
|
||||
| Summaries;GenericFlow<>;false;ReturnGenericElement<>;(System.Collections.Generic.List<S>);Argument[0].Element;ReturnValue;taint |
|
||||
| Summaries;GenericFlow<>;false;ReturnGenericField;();Argument[Qualifier];ReturnValue;taint |
|
||||
| Summaries;GenericFlow<>;false;ReturnGenericParam<>;(S);Argument[0];ReturnValue;taint |
|
||||
| Summaries;GenericFlow<>;false;SetGenericField;(T);Argument[0];Argument[Qualifier];taint |
|
||||
| Summaries;IEnumerableFlow;false;ReturnFieldInIEnumerable;();Argument[Qualifier];ReturnValue;taint |
|
||||
| Summaries;IEnumerableFlow;false;ReturnIEnumerable;(System.Collections.Generic.IEnumerable<System.String>);Argument[0].Element;ReturnValue;taint |
|
||||
| Summaries;IEnumerableFlow;false;ReturnIEnumerableElement;(System.Collections.Generic.IEnumerable<System.Object>);Argument[0].Element;ReturnValue;taint |
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace NoSummaries;
|
||||
|
||||
// Single class with a method that produces a flow summary.
|
||||
// Just to prove that, if a method like this is correctly exposed, a flow summary will be captured.
|
||||
public class PublicClassFlow
|
||||
{
|
||||
public int PublicReturn(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PublicClassNoFlow
|
||||
{
|
||||
private int PrivateReturn(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
internal int InternalReturn(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
private class PrivateClassNoFlow
|
||||
{
|
||||
public int ReturnParam(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
private class PrivateClassNestedPublicClassNoFlow
|
||||
{
|
||||
public class NestedPublicClassFlow
|
||||
{
|
||||
public int ReturnParam(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Summaries;
|
||||
|
||||
@@ -33,21 +31,6 @@ public class BasicFlow
|
||||
return s.Substring(0, 1);
|
||||
}
|
||||
|
||||
public void SetField(string s)
|
||||
{
|
||||
tainted = s;
|
||||
}
|
||||
|
||||
public string ReturnField()
|
||||
{
|
||||
return tainted;
|
||||
}
|
||||
}
|
||||
|
||||
public class CollectionFlow
|
||||
{
|
||||
private string tainted;
|
||||
|
||||
public int ReturnArrayElement(int[] input)
|
||||
{
|
||||
return input[0];
|
||||
@@ -58,117 +41,18 @@ public class CollectionFlow
|
||||
target[0] = data;
|
||||
}
|
||||
|
||||
public void AssignFieldToArray(object[] target)
|
||||
public void SetField(string s)
|
||||
{
|
||||
target[0] = tainted;
|
||||
tainted = s;
|
||||
}
|
||||
|
||||
public object ReturnListElement(List<object> input)
|
||||
{
|
||||
return input[0];
|
||||
}
|
||||
|
||||
public void AddToList(List<object> input, object data)
|
||||
{
|
||||
input.Add(data);
|
||||
}
|
||||
|
||||
public void AddFieldToList(List<string> input)
|
||||
{
|
||||
input.Add(tainted);
|
||||
}
|
||||
|
||||
public List<string> ReturnFieldInAList()
|
||||
{
|
||||
return new List<string> { tainted };
|
||||
}
|
||||
}
|
||||
|
||||
public class IEnumerableFlow
|
||||
{
|
||||
private string tainted;
|
||||
|
||||
public IEnumerable<string> ReturnIEnumerable(IEnumerable<string> input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
public object ReturnIEnumerableElement(IEnumerable<object> input)
|
||||
{
|
||||
return input.First();
|
||||
}
|
||||
|
||||
public IEnumerable<string> ReturnFieldInIEnumerable()
|
||||
{
|
||||
return new List<string> { tainted };
|
||||
}
|
||||
}
|
||||
|
||||
public class GenericFlow<T>
|
||||
{
|
||||
private T tainted;
|
||||
|
||||
public void SetGenericField(T t)
|
||||
{
|
||||
tainted = t;
|
||||
}
|
||||
|
||||
public T ReturnGenericField()
|
||||
public string ReturnField()
|
||||
{
|
||||
return tainted;
|
||||
}
|
||||
|
||||
public void AddFieldToGenericList(List<T> input)
|
||||
public void AssignFieldToArray(object[] target)
|
||||
{
|
||||
input.Add(tainted);
|
||||
}
|
||||
|
||||
public List<T> ReturnFieldInGenericList()
|
||||
{
|
||||
return new List<T> { tainted };
|
||||
}
|
||||
|
||||
public S ReturnGenericParam<S>(S input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
public S ReturnGenericElement<S>(List<S> input)
|
||||
{
|
||||
return input[0];
|
||||
}
|
||||
|
||||
public void AddToGenericList<S>(List<S> input, S data)
|
||||
{
|
||||
input.Add(data);
|
||||
target[0] = tainted;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class BaseClassFlow
|
||||
{
|
||||
public virtual int ReturnParam(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
public class DerivedClass1Flow : BaseClassFlow
|
||||
{
|
||||
public int ReturnParam1(int input0, int input1)
|
||||
{
|
||||
return input1;
|
||||
}
|
||||
}
|
||||
|
||||
public class DerivedClass2Flow : BaseClassFlow
|
||||
{
|
||||
public override int ReturnParam(int input)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
public int ReturnParam0(int input0, int input1)
|
||||
{
|
||||
return input0;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
semmle-extractor-options: /r:System.Linq.dll
|
||||
@@ -7,8 +7,8 @@ When analyzing a Go program, CodeQL does not examine the source code for
|
||||
external packages. To track the flow of untrusted data through a library, you
|
||||
can create a model of the library.
|
||||
|
||||
You can find existing models in the ``ql/lib/semmle/go/frameworks/`` folder of the
|
||||
`CodeQL for Go repository <https://github.com/github/codeql-go/tree/main/ql/lib/semmle/go/frameworks>`__.
|
||||
You can find existing models in the ``ql/src/semmle/go/frameworks/`` folder of the
|
||||
`CodeQL for Go repository <https://github.com/github/codeql-go/tree/main/ql/src/semmle/go/frameworks>`__.
|
||||
To add a new model, you should make a new file in that folder, named after the library.
|
||||
|
||||
Sources
|
||||
@@ -102,8 +102,8 @@ Data-flow sinks are specified by queries rather than by library models.
|
||||
However, you can use library models to indicate when functions belong to
|
||||
special categories. Queries can then use these categories when specifying
|
||||
sinks. Classes representing these special categories are contained in
|
||||
``ql/lib/semmle/go/Concepts.qll`` in the `CodeQL for Go repository
|
||||
<https://github.com/github/codeql-go/blob/main/ql/lib/semmle/go/Concepts.qll>`__.
|
||||
``ql/src/semmle/go/Concepts.qll`` in the `CodeQL for Go repository
|
||||
<https://github.com/github/codeql-go/blob/main/ql/src/semmle/go/Concepts.qll>`__.
|
||||
``Concepts.qll`` includes classes for logger mechanisms,
|
||||
HTTP response writers, HTTP redirects, and marshaling and unmarshaling
|
||||
functions.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* There are now QL classes ErrorExpr and ErrorStmt. These may be generated by upgrade or downgrade scripts when databases cannot be fully converted.
|
||||
@@ -528,7 +528,6 @@ case @stmt.kind of
|
||||
| 21 = @case
|
||||
| 22 = @catchclause
|
||||
| 23 = @yieldstmt
|
||||
| 24 = @errorstmt
|
||||
;
|
||||
|
||||
#keyset[parent,idx]
|
||||
@@ -629,7 +628,6 @@ case @expr.kind of
|
||||
| 71 = @typeannotation
|
||||
| 72 = @intersectiontypeaccess
|
||||
| 73 = @switchexpr
|
||||
| 74 = @errorexpr
|
||||
;
|
||||
|
||||
@classinstancexpr = @newexpr | @lambdaexpr | @memberref
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<dbstats>
|
||||
<typesizes>
|
||||
<e>
|
||||
<typesizes><e>
|
||||
<k>@compilation</k>
|
||||
<v>8629</v>
|
||||
</e>
|
||||
@@ -22,7 +21,7 @@
|
||||
</e>
|
||||
<e>
|
||||
<k>@location_default</k>
|
||||
<v>17430587</v>
|
||||
<v>13306607</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@file</k>
|
||||
@@ -150,7 +149,7 @@
|
||||
</e>
|
||||
<e>
|
||||
<k>@emptystmt</k>
|
||||
<v>1562</v>
|
||||
<v>886</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@exprstmt</k>
|
||||
@@ -192,10 +191,6 @@
|
||||
<k>@yieldstmt</k>
|
||||
<v>1</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@errorstmt</k>
|
||||
<v>1</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@arrayaccess</k>
|
||||
<v>181399</v>
|
||||
@@ -270,7 +265,7 @@
|
||||
</e>
|
||||
<e>
|
||||
<k>@mulexpr</k>
|
||||
<v>204610</v>
|
||||
<v>85898</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@divexpr</k>
|
||||
@@ -286,7 +281,7 @@
|
||||
</e>
|
||||
<e>
|
||||
<k>@subexpr</k>
|
||||
<v>84397</v>
|
||||
<v>57171</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@lshiftexpr</k>
|
||||
@@ -488,10 +483,6 @@
|
||||
<k>@switchexpr</k>
|
||||
<v>1</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@errorexpr</k>
|
||||
<v>1</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@localvar</k>
|
||||
<v>385335</v>
|
||||
@@ -528,6 +519,10 @@
|
||||
<k>@javadocTag</k>
|
||||
<v>335863</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@javadocText</k>
|
||||
<v>2503256</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@xmldtd</k>
|
||||
<v>569</v>
|
||||
@@ -536,10 +531,6 @@
|
||||
<k>@xmlelement</k>
|
||||
<v>1199832</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@javadocText</k>
|
||||
<v>2503256</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@xmlattribute</k>
|
||||
<v>1841492</v>
|
||||
@@ -569,8 +560,7 @@
|
||||
<v>1</v>
|
||||
</e>
|
||||
</typesizes>
|
||||
<stats>
|
||||
<relation>
|
||||
<stats><relation>
|
||||
<name>compilations</name>
|
||||
<cardinality>8629</cardinality>
|
||||
<columnsizes>
|
||||
@@ -16759,11 +16749,11 @@
|
||||
</relation>
|
||||
<relation>
|
||||
<name>isParenthesized</name>
|
||||
<cardinality>94666</cardinality>
|
||||
<cardinality>84274</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>id</k>
|
||||
<v>94666</v>
|
||||
<v>84274</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>parentheses</k>
|
||||
@@ -16781,7 +16771,7 @@
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>94666</v>
|
||||
<v>84274</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
@@ -16795,13 +16785,13 @@
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>58</a>
|
||||
<b>59</b>
|
||||
<a>12</a>
|
||||
<b>13</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>34605</a>
|
||||
<b>34606</b>
|
||||
<a>31863</a>
|
||||
<b>31864</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
|
||||
@@ -377,18 +377,6 @@ class CompileTimeConstantExpr extends Expr {
|
||||
/** An expression parent is an element that may have an expression as its child. */
|
||||
class ExprParent extends @exprparent, Top { }
|
||||
|
||||
/**
|
||||
* An error expression.
|
||||
*
|
||||
* These may be generated by upgrade or downgrade scripts when databases
|
||||
* cannot be fully converted.
|
||||
*/
|
||||
class ErrorExpr extends Expr, @errorexpr {
|
||||
override string toString() { result = "<error expr>" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ErrorExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An array access.
|
||||
*
|
||||
|
||||
@@ -59,18 +59,6 @@ class Stmt extends StmtParent, ExprParent, @stmt {
|
||||
/** A statement parent is any element that can have a statement as its child. */
|
||||
class StmtParent extends @stmtparent, Top { }
|
||||
|
||||
/**
|
||||
* An error statement.
|
||||
*
|
||||
* These may be generated by upgrade or downgrade scripts when databases
|
||||
* cannot be fully converted.
|
||||
*/
|
||||
class ErrorStmt extends Stmt, @errorstmt {
|
||||
override string toString() { result = "<error stmt>" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ErrorStmt" }
|
||||
}
|
||||
|
||||
/** A block of statements. */
|
||||
class BlockStmt extends Stmt, @block {
|
||||
/** Gets a statement that is an immediate child of this block. */
|
||||
|
||||
@@ -1,982 +0,0 @@
|
||||
/**
|
||||
* An invocation of the compiler. Note that more than one file may be
|
||||
* compiled per invocation. For example, this command compiles three
|
||||
* source files:
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*
|
||||
* The `id` simply identifies the invocation, while `cwd` is the working
|
||||
* directory from which the compiler was invoked.
|
||||
*/
|
||||
compilations(
|
||||
/**
|
||||
* An invocation of the compiler. Note that more than one file may
|
||||
* be compiled per invocation. For example, this command compiles
|
||||
* three source files:
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*/
|
||||
unique int id : @compilation,
|
||||
string cwd : string ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The arguments that were passed to the extractor for a compiler
|
||||
* invocation. If `id` is for the compiler invocation
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*
|
||||
* then typically there will be rows for
|
||||
*
|
||||
* num | arg
|
||||
* --- | ---
|
||||
* 0 | *path to extractor*
|
||||
* 1 | `--javac-args`
|
||||
* 2 | A.java
|
||||
* 3 | B.java
|
||||
* 4 | C.java
|
||||
*/
|
||||
#keyset[id, num]
|
||||
compilation_args(
|
||||
int id : @compilation ref,
|
||||
int num : int ref,
|
||||
string arg : string ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The source files that are compiled by a compiler invocation.
|
||||
* If `id` is for the compiler invocation
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*
|
||||
* then there will be rows for
|
||||
*
|
||||
* num | arg
|
||||
* --- | ---
|
||||
* 0 | A.java
|
||||
* 1 | B.java
|
||||
* 2 | C.java
|
||||
*/
|
||||
#keyset[id, num]
|
||||
compilation_compiling_files(
|
||||
int id : @compilation ref,
|
||||
int num : int ref,
|
||||
int file : @file ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The time taken by the extractor for a compiler invocation.
|
||||
*
|
||||
* For each file `num`, there will be rows for
|
||||
*
|
||||
* kind | seconds
|
||||
* ---- | ---
|
||||
* 1 | CPU seconds used by the extractor frontend
|
||||
* 2 | Elapsed seconds during the extractor frontend
|
||||
* 3 | CPU seconds used by the extractor backend
|
||||
* 4 | Elapsed seconds during the extractor backend
|
||||
*/
|
||||
#keyset[id, num, kind]
|
||||
compilation_time(
|
||||
int id : @compilation ref,
|
||||
int num : int ref,
|
||||
/* kind:
|
||||
1 = frontend_cpu_seconds
|
||||
2 = frontend_elapsed_seconds
|
||||
3 = extractor_cpu_seconds
|
||||
4 = extractor_elapsed_seconds
|
||||
*/
|
||||
int kind : int ref,
|
||||
float seconds : float ref
|
||||
);
|
||||
|
||||
/**
|
||||
* An error or warning generated by the extractor.
|
||||
* The diagnostic message `diagnostic` was generated during compiler
|
||||
* invocation `compilation`, and is the `file_number_diagnostic_number`th
|
||||
* message generated while extracting the `file_number`th file of that
|
||||
* invocation.
|
||||
*/
|
||||
#keyset[compilation, file_number, file_number_diagnostic_number]
|
||||
diagnostic_for(
|
||||
unique int diagnostic : @diagnostic ref,
|
||||
int compilation : @compilation ref,
|
||||
int file_number : int ref,
|
||||
int file_number_diagnostic_number : int ref
|
||||
);
|
||||
|
||||
/**
|
||||
* If extraction was successful, then `cpu_seconds` and
|
||||
* `elapsed_seconds` are the CPU time and elapsed time (respectively)
|
||||
* that extraction took for compiler invocation `id`.
|
||||
*/
|
||||
compilation_finished(
|
||||
unique int id : @compilation ref,
|
||||
float cpu_seconds : float ref,
|
||||
float elapsed_seconds : float ref
|
||||
);
|
||||
|
||||
diagnostics(
|
||||
unique int id: @diagnostic,
|
||||
int severity: int ref,
|
||||
string error_tag: string ref,
|
||||
string error_message: string ref,
|
||||
string full_error_message: string ref,
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
/*
|
||||
* External artifacts
|
||||
*/
|
||||
|
||||
externalData(
|
||||
int id : @externalDataElement,
|
||||
string path : string ref,
|
||||
int column: int ref,
|
||||
string value : string ref
|
||||
);
|
||||
|
||||
snapshotDate(
|
||||
unique date snapshotDate : date ref
|
||||
);
|
||||
|
||||
sourceLocationPrefix(
|
||||
string prefix : string ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Duplicate code
|
||||
*/
|
||||
|
||||
duplicateCode(
|
||||
unique int id : @duplication,
|
||||
string relativePath : string ref,
|
||||
int equivClass : int ref
|
||||
);
|
||||
|
||||
similarCode(
|
||||
unique int id : @similarity,
|
||||
string relativePath : string ref,
|
||||
int equivClass : int ref
|
||||
);
|
||||
|
||||
@duplication_or_similarity = @duplication | @similarity
|
||||
|
||||
tokens(
|
||||
int id : @duplication_or_similarity ref,
|
||||
int offset : int ref,
|
||||
int beginLine : int ref,
|
||||
int beginColumn : int ref,
|
||||
int endLine : int ref,
|
||||
int endColumn : int ref
|
||||
);
|
||||
|
||||
/*
|
||||
* SMAP
|
||||
*/
|
||||
|
||||
smap_header(
|
||||
int outputFileId: @file ref,
|
||||
string outputFilename: string ref,
|
||||
string defaultStratum: string ref
|
||||
);
|
||||
|
||||
smap_files(
|
||||
int outputFileId: @file ref,
|
||||
string stratum: string ref,
|
||||
int inputFileNum: int ref,
|
||||
string inputFileName: string ref,
|
||||
int inputFileId: @file ref
|
||||
);
|
||||
|
||||
smap_lines(
|
||||
int outputFileId: @file ref,
|
||||
string stratum: string ref,
|
||||
int inputFileNum: int ref,
|
||||
int inputStartLine: int ref,
|
||||
int inputLineCount: int ref,
|
||||
int outputStartLine: int ref,
|
||||
int outputLineIncrement: int ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Locations and files
|
||||
*/
|
||||
|
||||
@location = @location_default ;
|
||||
|
||||
locations_default(
|
||||
unique int id: @location_default,
|
||||
int file: @file ref,
|
||||
int beginLine: int ref,
|
||||
int beginColumn: int ref,
|
||||
int endLine: int ref,
|
||||
int endColumn: int ref
|
||||
);
|
||||
|
||||
hasLocation(
|
||||
int locatableid: @locatable ref,
|
||||
int id: @location ref
|
||||
);
|
||||
|
||||
@sourceline = @locatable ;
|
||||
|
||||
#keyset[element_id]
|
||||
numlines(
|
||||
int element_id: @sourceline ref,
|
||||
int num_lines: int ref,
|
||||
int num_code: int ref,
|
||||
int num_comment: int ref
|
||||
);
|
||||
|
||||
files(
|
||||
unique int id: @file,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
folders(
|
||||
unique int id: @folder,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
@container = @folder | @file
|
||||
|
||||
containerparent(
|
||||
int parent: @container ref,
|
||||
unique int child: @container ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Java
|
||||
*/
|
||||
|
||||
cupackage(
|
||||
unique int id: @file ref,
|
||||
int packageid: @package ref
|
||||
);
|
||||
|
||||
#keyset[fileid,keyName]
|
||||
jarManifestMain(
|
||||
int fileid: @file ref,
|
||||
string keyName: string ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
#keyset[fileid,entryName,keyName]
|
||||
jarManifestEntries(
|
||||
int fileid: @file ref,
|
||||
string entryName: string ref,
|
||||
string keyName: string ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
packages(
|
||||
unique int id: @package,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
primitives(
|
||||
unique int id: @primitive,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
modifiers(
|
||||
unique int id: @modifier,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
classes(
|
||||
unique int id: @class,
|
||||
string nodeName: string ref,
|
||||
int parentid: @package ref,
|
||||
int sourceid: @class ref
|
||||
);
|
||||
|
||||
isRecord(
|
||||
unique int id: @class ref
|
||||
);
|
||||
|
||||
interfaces(
|
||||
unique int id: @interface,
|
||||
string nodeName: string ref,
|
||||
int parentid: @package ref,
|
||||
int sourceid: @interface ref
|
||||
);
|
||||
|
||||
fielddecls(
|
||||
unique int id: @fielddecl,
|
||||
int parentid: @reftype ref
|
||||
);
|
||||
|
||||
#keyset[fieldId] #keyset[fieldDeclId,pos]
|
||||
fieldDeclaredIn(
|
||||
int fieldId: @field ref,
|
||||
int fieldDeclId: @fielddecl ref,
|
||||
int pos: int ref
|
||||
);
|
||||
|
||||
fields(
|
||||
unique int id: @field,
|
||||
string nodeName: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @reftype ref,
|
||||
int sourceid: @field ref
|
||||
);
|
||||
|
||||
constrs(
|
||||
unique int id: @constructor,
|
||||
string nodeName: string ref,
|
||||
string signature: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @reftype ref,
|
||||
int sourceid: @constructor ref
|
||||
);
|
||||
|
||||
methods(
|
||||
unique int id: @method,
|
||||
string nodeName: string ref,
|
||||
string signature: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @reftype ref,
|
||||
int sourceid: @method ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
params(
|
||||
unique int id: @param,
|
||||
int typeid: @type ref,
|
||||
int pos: int ref,
|
||||
int parentid: @callable ref,
|
||||
int sourceid: @param ref
|
||||
);
|
||||
|
||||
paramName(
|
||||
unique int id: @param ref,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
isVarargsParam(
|
||||
int param: @param ref
|
||||
);
|
||||
|
||||
exceptions(
|
||||
unique int id: @exception,
|
||||
int typeid: @type ref,
|
||||
int parentid: @callable ref
|
||||
);
|
||||
|
||||
isAnnotType(
|
||||
int interfaceid: @interface ref
|
||||
);
|
||||
|
||||
isAnnotElem(
|
||||
int methodid: @method ref
|
||||
);
|
||||
|
||||
annotValue(
|
||||
int parentid: @annotation ref,
|
||||
int id2: @method ref,
|
||||
unique int value: @expr ref
|
||||
);
|
||||
|
||||
isEnumType(
|
||||
int classid: @class ref
|
||||
);
|
||||
|
||||
isEnumConst(
|
||||
int fieldid: @field ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
typeVars(
|
||||
unique int id: @typevariable,
|
||||
string nodeName: string ref,
|
||||
int pos: int ref,
|
||||
int kind: int ref, // deprecated
|
||||
int parentid: @classorinterfaceorcallable ref
|
||||
);
|
||||
|
||||
wildcards(
|
||||
unique int id: @wildcard,
|
||||
string nodeName: string ref,
|
||||
int kind: int ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
typeBounds(
|
||||
unique int id: @typebound,
|
||||
int typeid: @reftype ref,
|
||||
int pos: int ref,
|
||||
int parentid: @boundedtype ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
typeArgs(
|
||||
int argumentid: @reftype ref,
|
||||
int pos: int ref,
|
||||
int parentid: @classorinterfaceorcallable ref
|
||||
);
|
||||
|
||||
isParameterized(
|
||||
int memberid: @member ref
|
||||
);
|
||||
|
||||
isRaw(
|
||||
int memberid: @member ref
|
||||
);
|
||||
|
||||
erasure(
|
||||
unique int memberid: @member ref,
|
||||
int erasureid: @member ref
|
||||
);
|
||||
|
||||
#keyset[classid] #keyset[parent]
|
||||
isAnonymClass(
|
||||
int classid: @class ref,
|
||||
int parent: @classinstancexpr ref
|
||||
);
|
||||
|
||||
#keyset[typeid] #keyset[parent]
|
||||
isLocalClassOrInterface(
|
||||
int typeid: @classorinterface ref,
|
||||
int parent: @localtypedeclstmt ref
|
||||
);
|
||||
|
||||
isDefConstr(
|
||||
int constructorid: @constructor ref
|
||||
);
|
||||
|
||||
#keyset[exprId]
|
||||
lambdaKind(
|
||||
int exprId: @lambdaexpr ref,
|
||||
int bodyKind: int ref
|
||||
);
|
||||
|
||||
arrays(
|
||||
unique int id: @array,
|
||||
string nodeName: string ref,
|
||||
int elementtypeid: @type ref,
|
||||
int dimension: int ref,
|
||||
int componenttypeid: @type ref
|
||||
);
|
||||
|
||||
enclInReftype(
|
||||
unique int child: @reftype ref,
|
||||
int parent: @reftype ref
|
||||
);
|
||||
|
||||
extendsReftype(
|
||||
int id1: @reftype ref,
|
||||
int id2: @classorinterface ref
|
||||
);
|
||||
|
||||
implInterface(
|
||||
int id1: @classorarray ref,
|
||||
int id2: @interface ref
|
||||
);
|
||||
|
||||
permits(
|
||||
int id1: @classorinterface ref,
|
||||
int id2: @classorinterface ref
|
||||
);
|
||||
|
||||
hasModifier(
|
||||
int id1: @modifiable ref,
|
||||
int id2: @modifier ref
|
||||
);
|
||||
|
||||
imports(
|
||||
unique int id: @import,
|
||||
int holder: @classorinterfaceorpackage ref,
|
||||
string name: string ref,
|
||||
int kind: int ref
|
||||
);
|
||||
|
||||
#keyset[parent,idx]
|
||||
stmts(
|
||||
unique int id: @stmt,
|
||||
int kind: int ref,
|
||||
int parent: @stmtparent ref,
|
||||
int idx: int ref,
|
||||
int bodydecl: @callable ref
|
||||
);
|
||||
|
||||
@stmtparent = @callable | @stmt | @switchexpr;
|
||||
|
||||
case @stmt.kind of
|
||||
0 = @block
|
||||
| 1 = @ifstmt
|
||||
| 2 = @forstmt
|
||||
| 3 = @enhancedforstmt
|
||||
| 4 = @whilestmt
|
||||
| 5 = @dostmt
|
||||
| 6 = @trystmt
|
||||
| 7 = @switchstmt
|
||||
| 8 = @synchronizedstmt
|
||||
| 9 = @returnstmt
|
||||
| 10 = @throwstmt
|
||||
| 11 = @breakstmt
|
||||
| 12 = @continuestmt
|
||||
| 13 = @emptystmt
|
||||
| 14 = @exprstmt
|
||||
| 15 = @labeledstmt
|
||||
| 16 = @assertstmt
|
||||
| 17 = @localvariabledeclstmt
|
||||
| 18 = @localtypedeclstmt
|
||||
| 19 = @constructorinvocationstmt
|
||||
| 20 = @superconstructorinvocationstmt
|
||||
| 21 = @case
|
||||
| 22 = @catchclause
|
||||
| 23 = @yieldstmt
|
||||
;
|
||||
|
||||
#keyset[parent,idx]
|
||||
exprs(
|
||||
unique int id: @expr,
|
||||
int kind: int ref,
|
||||
int typeid: @type ref,
|
||||
int parent: @exprparent ref,
|
||||
int idx: int ref
|
||||
);
|
||||
|
||||
callableEnclosingExpr(
|
||||
unique int id: @expr ref,
|
||||
int callable_id: @callable ref
|
||||
);
|
||||
|
||||
statementEnclosingExpr(
|
||||
unique int id: @expr ref,
|
||||
int statement_id: @stmt ref
|
||||
);
|
||||
|
||||
isParenthesized(
|
||||
unique int id: @expr ref,
|
||||
int parentheses: int ref
|
||||
);
|
||||
|
||||
case @expr.kind of
|
||||
1 = @arrayaccess
|
||||
| 2 = @arraycreationexpr
|
||||
| 3 = @arrayinit
|
||||
| 4 = @assignexpr
|
||||
| 5 = @assignaddexpr
|
||||
| 6 = @assignsubexpr
|
||||
| 7 = @assignmulexpr
|
||||
| 8 = @assigndivexpr
|
||||
| 9 = @assignremexpr
|
||||
| 10 = @assignandexpr
|
||||
| 11 = @assignorexpr
|
||||
| 12 = @assignxorexpr
|
||||
| 13 = @assignlshiftexpr
|
||||
| 14 = @assignrshiftexpr
|
||||
| 15 = @assignurshiftexpr
|
||||
| 16 = @booleanliteral
|
||||
| 17 = @integerliteral
|
||||
| 18 = @longliteral
|
||||
| 19 = @floatingpointliteral
|
||||
| 20 = @doubleliteral
|
||||
| 21 = @characterliteral
|
||||
| 22 = @stringliteral
|
||||
| 23 = @nullliteral
|
||||
| 24 = @mulexpr
|
||||
| 25 = @divexpr
|
||||
| 26 = @remexpr
|
||||
| 27 = @addexpr
|
||||
| 28 = @subexpr
|
||||
| 29 = @lshiftexpr
|
||||
| 30 = @rshiftexpr
|
||||
| 31 = @urshiftexpr
|
||||
| 32 = @andbitexpr
|
||||
| 33 = @orbitexpr
|
||||
| 34 = @xorbitexpr
|
||||
| 35 = @andlogicalexpr
|
||||
| 36 = @orlogicalexpr
|
||||
| 37 = @ltexpr
|
||||
| 38 = @gtexpr
|
||||
| 39 = @leexpr
|
||||
| 40 = @geexpr
|
||||
| 41 = @eqexpr
|
||||
| 42 = @neexpr
|
||||
| 43 = @postincexpr
|
||||
| 44 = @postdecexpr
|
||||
| 45 = @preincexpr
|
||||
| 46 = @predecexpr
|
||||
| 47 = @minusexpr
|
||||
| 48 = @plusexpr
|
||||
| 49 = @bitnotexpr
|
||||
| 50 = @lognotexpr
|
||||
| 51 = @castexpr
|
||||
| 52 = @newexpr
|
||||
| 53 = @conditionalexpr
|
||||
| 54 = @parexpr // deprecated
|
||||
| 55 = @instanceofexpr
|
||||
| 56 = @localvariabledeclexpr
|
||||
| 57 = @typeliteral
|
||||
| 58 = @thisaccess
|
||||
| 59 = @superaccess
|
||||
| 60 = @varaccess
|
||||
| 61 = @methodaccess
|
||||
| 62 = @unannotatedtypeaccess
|
||||
| 63 = @arraytypeaccess
|
||||
| 64 = @packageaccess
|
||||
| 65 = @wildcardtypeaccess
|
||||
| 66 = @declannotation
|
||||
| 67 = @uniontypeaccess
|
||||
| 68 = @lambdaexpr
|
||||
| 69 = @memberref
|
||||
| 70 = @annotatedtypeaccess
|
||||
| 71 = @typeannotation
|
||||
| 72 = @intersectiontypeaccess
|
||||
| 73 = @switchexpr
|
||||
;
|
||||
|
||||
@classinstancexpr = @newexpr | @lambdaexpr | @memberref
|
||||
|
||||
@annotation = @declannotation | @typeannotation
|
||||
@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess
|
||||
|
||||
@assignment = @assignexpr
|
||||
| @assignop;
|
||||
|
||||
@unaryassignment = @postincexpr
|
||||
| @postdecexpr
|
||||
| @preincexpr
|
||||
| @predecexpr;
|
||||
|
||||
@assignop = @assignaddexpr
|
||||
| @assignsubexpr
|
||||
| @assignmulexpr
|
||||
| @assigndivexpr
|
||||
| @assignremexpr
|
||||
| @assignandexpr
|
||||
| @assignorexpr
|
||||
| @assignxorexpr
|
||||
| @assignlshiftexpr
|
||||
| @assignrshiftexpr
|
||||
| @assignurshiftexpr;
|
||||
|
||||
@literal = @booleanliteral
|
||||
| @integerliteral
|
||||
| @longliteral
|
||||
| @floatingpointliteral
|
||||
| @doubleliteral
|
||||
| @characterliteral
|
||||
| @stringliteral
|
||||
| @nullliteral;
|
||||
|
||||
@binaryexpr = @mulexpr
|
||||
| @divexpr
|
||||
| @remexpr
|
||||
| @addexpr
|
||||
| @subexpr
|
||||
| @lshiftexpr
|
||||
| @rshiftexpr
|
||||
| @urshiftexpr
|
||||
| @andbitexpr
|
||||
| @orbitexpr
|
||||
| @xorbitexpr
|
||||
| @andlogicalexpr
|
||||
| @orlogicalexpr
|
||||
| @ltexpr
|
||||
| @gtexpr
|
||||
| @leexpr
|
||||
| @geexpr
|
||||
| @eqexpr
|
||||
| @neexpr;
|
||||
|
||||
@unaryexpr = @postincexpr
|
||||
| @postdecexpr
|
||||
| @preincexpr
|
||||
| @predecexpr
|
||||
| @minusexpr
|
||||
| @plusexpr
|
||||
| @bitnotexpr
|
||||
| @lognotexpr;
|
||||
|
||||
@caller = @classinstancexpr
|
||||
| @methodaccess
|
||||
| @constructorinvocationstmt
|
||||
| @superconstructorinvocationstmt;
|
||||
|
||||
callableBinding(
|
||||
unique int callerid: @caller ref,
|
||||
int callee: @callable ref
|
||||
);
|
||||
|
||||
memberRefBinding(
|
||||
unique int id: @expr ref,
|
||||
int callable: @callable ref
|
||||
);
|
||||
|
||||
@exprparent = @stmt | @expr | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable;
|
||||
|
||||
variableBinding(
|
||||
unique int expr: @varaccess ref,
|
||||
int variable: @variable ref
|
||||
);
|
||||
|
||||
@variable = @localscopevariable | @field;
|
||||
|
||||
@localscopevariable = @localvar | @param;
|
||||
|
||||
localvars(
|
||||
unique int id: @localvar,
|
||||
string nodeName: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @localvariabledeclexpr ref
|
||||
);
|
||||
|
||||
@namedexprorstmt = @breakstmt
|
||||
| @continuestmt
|
||||
| @labeledstmt
|
||||
| @literal;
|
||||
|
||||
namestrings(
|
||||
string name: string ref,
|
||||
string value: string ref,
|
||||
unique int parent: @namedexprorstmt ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Modules
|
||||
*/
|
||||
|
||||
#keyset[name]
|
||||
modules(
|
||||
unique int id: @module,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
isOpen(
|
||||
int id: @module ref
|
||||
);
|
||||
|
||||
#keyset[fileId]
|
||||
cumodule(
|
||||
int fileId: @file ref,
|
||||
int moduleId: @module ref
|
||||
);
|
||||
|
||||
@directive = @requires
|
||||
| @exports
|
||||
| @opens
|
||||
| @uses
|
||||
| @provides
|
||||
|
||||
#keyset[directive]
|
||||
directives(
|
||||
int id: @module ref,
|
||||
int directive: @directive ref
|
||||
);
|
||||
|
||||
requires(
|
||||
unique int id: @requires,
|
||||
int target: @module ref
|
||||
);
|
||||
|
||||
isTransitive(
|
||||
int id: @requires ref
|
||||
);
|
||||
|
||||
isStatic(
|
||||
int id: @requires ref
|
||||
);
|
||||
|
||||
exports(
|
||||
unique int id: @exports,
|
||||
int target: @package ref
|
||||
);
|
||||
|
||||
exportsTo(
|
||||
int id: @exports ref,
|
||||
int target: @module ref
|
||||
);
|
||||
|
||||
opens(
|
||||
unique int id: @opens,
|
||||
int target: @package ref
|
||||
);
|
||||
|
||||
opensTo(
|
||||
int id: @opens ref,
|
||||
int target: @module ref
|
||||
);
|
||||
|
||||
uses(
|
||||
unique int id: @uses,
|
||||
string serviceInterface: string ref
|
||||
);
|
||||
|
||||
provides(
|
||||
unique int id: @provides,
|
||||
string serviceInterface: string ref
|
||||
);
|
||||
|
||||
providesWith(
|
||||
int id: @provides ref,
|
||||
string serviceImpl: string ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Javadoc
|
||||
*/
|
||||
|
||||
javadoc(
|
||||
unique int id: @javadoc
|
||||
);
|
||||
|
||||
isNormalComment(
|
||||
int commentid : @javadoc ref
|
||||
);
|
||||
|
||||
isEolComment(
|
||||
int commentid : @javadoc ref
|
||||
);
|
||||
|
||||
hasJavadoc(
|
||||
int documentableid: @member ref,
|
||||
int javadocid: @javadoc ref
|
||||
);
|
||||
|
||||
#keyset[parentid,idx]
|
||||
javadocTag(
|
||||
unique int id: @javadocTag,
|
||||
string name: string ref,
|
||||
int parentid: @javadocParent ref,
|
||||
int idx: int ref
|
||||
);
|
||||
|
||||
#keyset[parentid,idx]
|
||||
javadocText(
|
||||
unique int id: @javadocText,
|
||||
string text: string ref,
|
||||
int parentid: @javadocParent ref,
|
||||
int idx: int ref
|
||||
);
|
||||
|
||||
@javadocParent = @javadoc | @javadocTag;
|
||||
@javadocElement = @javadocTag | @javadocText;
|
||||
|
||||
@classorinterface = @interface | @class;
|
||||
@classorinterfaceorpackage = @classorinterface | @package;
|
||||
@classorinterfaceorcallable = @classorinterface | @callable;
|
||||
@boundedtype = @typevariable | @wildcard;
|
||||
@reftype = @classorinterface | @array | @boundedtype;
|
||||
@classorarray = @class | @array;
|
||||
@type = @primitive | @reftype;
|
||||
@callable = @method | @constructor;
|
||||
@element = @file | @package | @primitive | @class | @interface | @method | @constructor | @modifier | @param | @exception | @field |
|
||||
@annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl;
|
||||
|
||||
@modifiable = @member_modifiable| @param | @localvar ;
|
||||
|
||||
@member_modifiable = @class | @interface | @method | @constructor | @field ;
|
||||
|
||||
@member = @method | @constructor | @field | @reftype ;
|
||||
|
||||
@locatable = @file | @class | @interface | @fielddecl | @field | @constructor | @method | @param | @exception
|
||||
| @boundedtype | @typebound | @array | @primitive
|
||||
| @import | @stmt | @expr | @localvar | @javadoc | @javadocTag | @javadocText
|
||||
| @xmllocatable;
|
||||
|
||||
@top = @element | @locatable | @folder;
|
||||
|
||||
/*
|
||||
* XML Files
|
||||
*/
|
||||
|
||||
xmlEncoding(
|
||||
unique int id: @file ref,
|
||||
string encoding: string ref
|
||||
);
|
||||
|
||||
xmlDTDs(
|
||||
unique int id: @xmldtd,
|
||||
string root: string ref,
|
||||
string publicId: string ref,
|
||||
string systemId: string ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlElements(
|
||||
unique int id: @xmlelement,
|
||||
string name: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int idx: int ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlAttrs(
|
||||
unique int id: @xmlattribute,
|
||||
int elementid: @xmlelement ref,
|
||||
string name: string ref,
|
||||
string value: string ref,
|
||||
int idx: int ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlNs(
|
||||
int id: @xmlnamespace,
|
||||
string prefixName: string ref,
|
||||
string URI: string ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlHasNs(
|
||||
int elementId: @xmlnamespaceable ref,
|
||||
int nsId: @xmlnamespace ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlComments(
|
||||
unique int id: @xmlcomment,
|
||||
string text: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlChars(
|
||||
unique int id: @xmlcharacters,
|
||||
string text: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int idx: int ref,
|
||||
int isCDATA: int ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
@xmlparent = @file | @xmlelement;
|
||||
@xmlnamespaceable = @xmlelement | @xmlattribute;
|
||||
|
||||
xmllocations(
|
||||
int xmlElement: @xmllocatable ref,
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
|
||||
|
||||
/*
|
||||
* configuration files with key value pairs
|
||||
*/
|
||||
|
||||
configs(
|
||||
unique int id: @config
|
||||
);
|
||||
|
||||
configNames(
|
||||
unique int id: @configName,
|
||||
int config: @config ref,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
configValues(
|
||||
unique int id: @configValue,
|
||||
int config: @config ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
configLocations(
|
||||
int locatable: @configLocatable ref,
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
@configLocatable = @config | @configName | @configValue;
|
||||
@@ -1,984 +0,0 @@
|
||||
/**
|
||||
* An invocation of the compiler. Note that more than one file may be
|
||||
* compiled per invocation. For example, this command compiles three
|
||||
* source files:
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*
|
||||
* The `id` simply identifies the invocation, while `cwd` is the working
|
||||
* directory from which the compiler was invoked.
|
||||
*/
|
||||
compilations(
|
||||
/**
|
||||
* An invocation of the compiler. Note that more than one file may
|
||||
* be compiled per invocation. For example, this command compiles
|
||||
* three source files:
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*/
|
||||
unique int id : @compilation,
|
||||
string cwd : string ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The arguments that were passed to the extractor for a compiler
|
||||
* invocation. If `id` is for the compiler invocation
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*
|
||||
* then typically there will be rows for
|
||||
*
|
||||
* num | arg
|
||||
* --- | ---
|
||||
* 0 | *path to extractor*
|
||||
* 1 | `--javac-args`
|
||||
* 2 | A.java
|
||||
* 3 | B.java
|
||||
* 4 | C.java
|
||||
*/
|
||||
#keyset[id, num]
|
||||
compilation_args(
|
||||
int id : @compilation ref,
|
||||
int num : int ref,
|
||||
string arg : string ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The source files that are compiled by a compiler invocation.
|
||||
* If `id` is for the compiler invocation
|
||||
*
|
||||
* javac A.java B.java C.java
|
||||
*
|
||||
* then there will be rows for
|
||||
*
|
||||
* num | arg
|
||||
* --- | ---
|
||||
* 0 | A.java
|
||||
* 1 | B.java
|
||||
* 2 | C.java
|
||||
*/
|
||||
#keyset[id, num]
|
||||
compilation_compiling_files(
|
||||
int id : @compilation ref,
|
||||
int num : int ref,
|
||||
int file : @file ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The time taken by the extractor for a compiler invocation.
|
||||
*
|
||||
* For each file `num`, there will be rows for
|
||||
*
|
||||
* kind | seconds
|
||||
* ---- | ---
|
||||
* 1 | CPU seconds used by the extractor frontend
|
||||
* 2 | Elapsed seconds during the extractor frontend
|
||||
* 3 | CPU seconds used by the extractor backend
|
||||
* 4 | Elapsed seconds during the extractor backend
|
||||
*/
|
||||
#keyset[id, num, kind]
|
||||
compilation_time(
|
||||
int id : @compilation ref,
|
||||
int num : int ref,
|
||||
/* kind:
|
||||
1 = frontend_cpu_seconds
|
||||
2 = frontend_elapsed_seconds
|
||||
3 = extractor_cpu_seconds
|
||||
4 = extractor_elapsed_seconds
|
||||
*/
|
||||
int kind : int ref,
|
||||
float seconds : float ref
|
||||
);
|
||||
|
||||
/**
|
||||
* An error or warning generated by the extractor.
|
||||
* The diagnostic message `diagnostic` was generated during compiler
|
||||
* invocation `compilation`, and is the `file_number_diagnostic_number`th
|
||||
* message generated while extracting the `file_number`th file of that
|
||||
* invocation.
|
||||
*/
|
||||
#keyset[compilation, file_number, file_number_diagnostic_number]
|
||||
diagnostic_for(
|
||||
unique int diagnostic : @diagnostic ref,
|
||||
int compilation : @compilation ref,
|
||||
int file_number : int ref,
|
||||
int file_number_diagnostic_number : int ref
|
||||
);
|
||||
|
||||
/**
|
||||
* If extraction was successful, then `cpu_seconds` and
|
||||
* `elapsed_seconds` are the CPU time and elapsed time (respectively)
|
||||
* that extraction took for compiler invocation `id`.
|
||||
*/
|
||||
compilation_finished(
|
||||
unique int id : @compilation ref,
|
||||
float cpu_seconds : float ref,
|
||||
float elapsed_seconds : float ref
|
||||
);
|
||||
|
||||
diagnostics(
|
||||
unique int id: @diagnostic,
|
||||
int severity: int ref,
|
||||
string error_tag: string ref,
|
||||
string error_message: string ref,
|
||||
string full_error_message: string ref,
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
/*
|
||||
* External artifacts
|
||||
*/
|
||||
|
||||
externalData(
|
||||
int id : @externalDataElement,
|
||||
string path : string ref,
|
||||
int column: int ref,
|
||||
string value : string ref
|
||||
);
|
||||
|
||||
snapshotDate(
|
||||
unique date snapshotDate : date ref
|
||||
);
|
||||
|
||||
sourceLocationPrefix(
|
||||
string prefix : string ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Duplicate code
|
||||
*/
|
||||
|
||||
duplicateCode(
|
||||
unique int id : @duplication,
|
||||
string relativePath : string ref,
|
||||
int equivClass : int ref
|
||||
);
|
||||
|
||||
similarCode(
|
||||
unique int id : @similarity,
|
||||
string relativePath : string ref,
|
||||
int equivClass : int ref
|
||||
);
|
||||
|
||||
@duplication_or_similarity = @duplication | @similarity
|
||||
|
||||
tokens(
|
||||
int id : @duplication_or_similarity ref,
|
||||
int offset : int ref,
|
||||
int beginLine : int ref,
|
||||
int beginColumn : int ref,
|
||||
int endLine : int ref,
|
||||
int endColumn : int ref
|
||||
);
|
||||
|
||||
/*
|
||||
* SMAP
|
||||
*/
|
||||
|
||||
smap_header(
|
||||
int outputFileId: @file ref,
|
||||
string outputFilename: string ref,
|
||||
string defaultStratum: string ref
|
||||
);
|
||||
|
||||
smap_files(
|
||||
int outputFileId: @file ref,
|
||||
string stratum: string ref,
|
||||
int inputFileNum: int ref,
|
||||
string inputFileName: string ref,
|
||||
int inputFileId: @file ref
|
||||
);
|
||||
|
||||
smap_lines(
|
||||
int outputFileId: @file ref,
|
||||
string stratum: string ref,
|
||||
int inputFileNum: int ref,
|
||||
int inputStartLine: int ref,
|
||||
int inputLineCount: int ref,
|
||||
int outputStartLine: int ref,
|
||||
int outputLineIncrement: int ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Locations and files
|
||||
*/
|
||||
|
||||
@location = @location_default ;
|
||||
|
||||
locations_default(
|
||||
unique int id: @location_default,
|
||||
int file: @file ref,
|
||||
int beginLine: int ref,
|
||||
int beginColumn: int ref,
|
||||
int endLine: int ref,
|
||||
int endColumn: int ref
|
||||
);
|
||||
|
||||
hasLocation(
|
||||
int locatableid: @locatable ref,
|
||||
int id: @location ref
|
||||
);
|
||||
|
||||
@sourceline = @locatable ;
|
||||
|
||||
#keyset[element_id]
|
||||
numlines(
|
||||
int element_id: @sourceline ref,
|
||||
int num_lines: int ref,
|
||||
int num_code: int ref,
|
||||
int num_comment: int ref
|
||||
);
|
||||
|
||||
files(
|
||||
unique int id: @file,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
folders(
|
||||
unique int id: @folder,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
@container = @folder | @file
|
||||
|
||||
containerparent(
|
||||
int parent: @container ref,
|
||||
unique int child: @container ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Java
|
||||
*/
|
||||
|
||||
cupackage(
|
||||
unique int id: @file ref,
|
||||
int packageid: @package ref
|
||||
);
|
||||
|
||||
#keyset[fileid,keyName]
|
||||
jarManifestMain(
|
||||
int fileid: @file ref,
|
||||
string keyName: string ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
#keyset[fileid,entryName,keyName]
|
||||
jarManifestEntries(
|
||||
int fileid: @file ref,
|
||||
string entryName: string ref,
|
||||
string keyName: string ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
packages(
|
||||
unique int id: @package,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
primitives(
|
||||
unique int id: @primitive,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
modifiers(
|
||||
unique int id: @modifier,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
classes(
|
||||
unique int id: @class,
|
||||
string nodeName: string ref,
|
||||
int parentid: @package ref,
|
||||
int sourceid: @class ref
|
||||
);
|
||||
|
||||
isRecord(
|
||||
unique int id: @class ref
|
||||
);
|
||||
|
||||
interfaces(
|
||||
unique int id: @interface,
|
||||
string nodeName: string ref,
|
||||
int parentid: @package ref,
|
||||
int sourceid: @interface ref
|
||||
);
|
||||
|
||||
fielddecls(
|
||||
unique int id: @fielddecl,
|
||||
int parentid: @reftype ref
|
||||
);
|
||||
|
||||
#keyset[fieldId] #keyset[fieldDeclId,pos]
|
||||
fieldDeclaredIn(
|
||||
int fieldId: @field ref,
|
||||
int fieldDeclId: @fielddecl ref,
|
||||
int pos: int ref
|
||||
);
|
||||
|
||||
fields(
|
||||
unique int id: @field,
|
||||
string nodeName: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @reftype ref,
|
||||
int sourceid: @field ref
|
||||
);
|
||||
|
||||
constrs(
|
||||
unique int id: @constructor,
|
||||
string nodeName: string ref,
|
||||
string signature: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @reftype ref,
|
||||
int sourceid: @constructor ref
|
||||
);
|
||||
|
||||
methods(
|
||||
unique int id: @method,
|
||||
string nodeName: string ref,
|
||||
string signature: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @reftype ref,
|
||||
int sourceid: @method ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
params(
|
||||
unique int id: @param,
|
||||
int typeid: @type ref,
|
||||
int pos: int ref,
|
||||
int parentid: @callable ref,
|
||||
int sourceid: @param ref
|
||||
);
|
||||
|
||||
paramName(
|
||||
unique int id: @param ref,
|
||||
string nodeName: string ref
|
||||
);
|
||||
|
||||
isVarargsParam(
|
||||
int param: @param ref
|
||||
);
|
||||
|
||||
exceptions(
|
||||
unique int id: @exception,
|
||||
int typeid: @type ref,
|
||||
int parentid: @callable ref
|
||||
);
|
||||
|
||||
isAnnotType(
|
||||
int interfaceid: @interface ref
|
||||
);
|
||||
|
||||
isAnnotElem(
|
||||
int methodid: @method ref
|
||||
);
|
||||
|
||||
annotValue(
|
||||
int parentid: @annotation ref,
|
||||
int id2: @method ref,
|
||||
unique int value: @expr ref
|
||||
);
|
||||
|
||||
isEnumType(
|
||||
int classid: @class ref
|
||||
);
|
||||
|
||||
isEnumConst(
|
||||
int fieldid: @field ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
typeVars(
|
||||
unique int id: @typevariable,
|
||||
string nodeName: string ref,
|
||||
int pos: int ref,
|
||||
int kind: int ref, // deprecated
|
||||
int parentid: @classorinterfaceorcallable ref
|
||||
);
|
||||
|
||||
wildcards(
|
||||
unique int id: @wildcard,
|
||||
string nodeName: string ref,
|
||||
int kind: int ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
typeBounds(
|
||||
unique int id: @typebound,
|
||||
int typeid: @reftype ref,
|
||||
int pos: int ref,
|
||||
int parentid: @boundedtype ref
|
||||
);
|
||||
|
||||
#keyset[parentid,pos]
|
||||
typeArgs(
|
||||
int argumentid: @reftype ref,
|
||||
int pos: int ref,
|
||||
int parentid: @classorinterfaceorcallable ref
|
||||
);
|
||||
|
||||
isParameterized(
|
||||
int memberid: @member ref
|
||||
);
|
||||
|
||||
isRaw(
|
||||
int memberid: @member ref
|
||||
);
|
||||
|
||||
erasure(
|
||||
unique int memberid: @member ref,
|
||||
int erasureid: @member ref
|
||||
);
|
||||
|
||||
#keyset[classid] #keyset[parent]
|
||||
isAnonymClass(
|
||||
int classid: @class ref,
|
||||
int parent: @classinstancexpr ref
|
||||
);
|
||||
|
||||
#keyset[typeid] #keyset[parent]
|
||||
isLocalClassOrInterface(
|
||||
int typeid: @classorinterface ref,
|
||||
int parent: @localtypedeclstmt ref
|
||||
);
|
||||
|
||||
isDefConstr(
|
||||
int constructorid: @constructor ref
|
||||
);
|
||||
|
||||
#keyset[exprId]
|
||||
lambdaKind(
|
||||
int exprId: @lambdaexpr ref,
|
||||
int bodyKind: int ref
|
||||
);
|
||||
|
||||
arrays(
|
||||
unique int id: @array,
|
||||
string nodeName: string ref,
|
||||
int elementtypeid: @type ref,
|
||||
int dimension: int ref,
|
||||
int componenttypeid: @type ref
|
||||
);
|
||||
|
||||
enclInReftype(
|
||||
unique int child: @reftype ref,
|
||||
int parent: @reftype ref
|
||||
);
|
||||
|
||||
extendsReftype(
|
||||
int id1: @reftype ref,
|
||||
int id2: @classorinterface ref
|
||||
);
|
||||
|
||||
implInterface(
|
||||
int id1: @classorarray ref,
|
||||
int id2: @interface ref
|
||||
);
|
||||
|
||||
permits(
|
||||
int id1: @classorinterface ref,
|
||||
int id2: @classorinterface ref
|
||||
);
|
||||
|
||||
hasModifier(
|
||||
int id1: @modifiable ref,
|
||||
int id2: @modifier ref
|
||||
);
|
||||
|
||||
imports(
|
||||
unique int id: @import,
|
||||
int holder: @classorinterfaceorpackage ref,
|
||||
string name: string ref,
|
||||
int kind: int ref
|
||||
);
|
||||
|
||||
#keyset[parent,idx]
|
||||
stmts(
|
||||
unique int id: @stmt,
|
||||
int kind: int ref,
|
||||
int parent: @stmtparent ref,
|
||||
int idx: int ref,
|
||||
int bodydecl: @callable ref
|
||||
);
|
||||
|
||||
@stmtparent = @callable | @stmt | @switchexpr;
|
||||
|
||||
case @stmt.kind of
|
||||
0 = @block
|
||||
| 1 = @ifstmt
|
||||
| 2 = @forstmt
|
||||
| 3 = @enhancedforstmt
|
||||
| 4 = @whilestmt
|
||||
| 5 = @dostmt
|
||||
| 6 = @trystmt
|
||||
| 7 = @switchstmt
|
||||
| 8 = @synchronizedstmt
|
||||
| 9 = @returnstmt
|
||||
| 10 = @throwstmt
|
||||
| 11 = @breakstmt
|
||||
| 12 = @continuestmt
|
||||
| 13 = @emptystmt
|
||||
| 14 = @exprstmt
|
||||
| 15 = @labeledstmt
|
||||
| 16 = @assertstmt
|
||||
| 17 = @localvariabledeclstmt
|
||||
| 18 = @localtypedeclstmt
|
||||
| 19 = @constructorinvocationstmt
|
||||
| 20 = @superconstructorinvocationstmt
|
||||
| 21 = @case
|
||||
| 22 = @catchclause
|
||||
| 23 = @yieldstmt
|
||||
| 24 = @errorstmt
|
||||
;
|
||||
|
||||
#keyset[parent,idx]
|
||||
exprs(
|
||||
unique int id: @expr,
|
||||
int kind: int ref,
|
||||
int typeid: @type ref,
|
||||
int parent: @exprparent ref,
|
||||
int idx: int ref
|
||||
);
|
||||
|
||||
callableEnclosingExpr(
|
||||
unique int id: @expr ref,
|
||||
int callable_id: @callable ref
|
||||
);
|
||||
|
||||
statementEnclosingExpr(
|
||||
unique int id: @expr ref,
|
||||
int statement_id: @stmt ref
|
||||
);
|
||||
|
||||
isParenthesized(
|
||||
unique int id: @expr ref,
|
||||
int parentheses: int ref
|
||||
);
|
||||
|
||||
case @expr.kind of
|
||||
1 = @arrayaccess
|
||||
| 2 = @arraycreationexpr
|
||||
| 3 = @arrayinit
|
||||
| 4 = @assignexpr
|
||||
| 5 = @assignaddexpr
|
||||
| 6 = @assignsubexpr
|
||||
| 7 = @assignmulexpr
|
||||
| 8 = @assigndivexpr
|
||||
| 9 = @assignremexpr
|
||||
| 10 = @assignandexpr
|
||||
| 11 = @assignorexpr
|
||||
| 12 = @assignxorexpr
|
||||
| 13 = @assignlshiftexpr
|
||||
| 14 = @assignrshiftexpr
|
||||
| 15 = @assignurshiftexpr
|
||||
| 16 = @booleanliteral
|
||||
| 17 = @integerliteral
|
||||
| 18 = @longliteral
|
||||
| 19 = @floatingpointliteral
|
||||
| 20 = @doubleliteral
|
||||
| 21 = @characterliteral
|
||||
| 22 = @stringliteral
|
||||
| 23 = @nullliteral
|
||||
| 24 = @mulexpr
|
||||
| 25 = @divexpr
|
||||
| 26 = @remexpr
|
||||
| 27 = @addexpr
|
||||
| 28 = @subexpr
|
||||
| 29 = @lshiftexpr
|
||||
| 30 = @rshiftexpr
|
||||
| 31 = @urshiftexpr
|
||||
| 32 = @andbitexpr
|
||||
| 33 = @orbitexpr
|
||||
| 34 = @xorbitexpr
|
||||
| 35 = @andlogicalexpr
|
||||
| 36 = @orlogicalexpr
|
||||
| 37 = @ltexpr
|
||||
| 38 = @gtexpr
|
||||
| 39 = @leexpr
|
||||
| 40 = @geexpr
|
||||
| 41 = @eqexpr
|
||||
| 42 = @neexpr
|
||||
| 43 = @postincexpr
|
||||
| 44 = @postdecexpr
|
||||
| 45 = @preincexpr
|
||||
| 46 = @predecexpr
|
||||
| 47 = @minusexpr
|
||||
| 48 = @plusexpr
|
||||
| 49 = @bitnotexpr
|
||||
| 50 = @lognotexpr
|
||||
| 51 = @castexpr
|
||||
| 52 = @newexpr
|
||||
| 53 = @conditionalexpr
|
||||
| 54 = @parexpr // deprecated
|
||||
| 55 = @instanceofexpr
|
||||
| 56 = @localvariabledeclexpr
|
||||
| 57 = @typeliteral
|
||||
| 58 = @thisaccess
|
||||
| 59 = @superaccess
|
||||
| 60 = @varaccess
|
||||
| 61 = @methodaccess
|
||||
| 62 = @unannotatedtypeaccess
|
||||
| 63 = @arraytypeaccess
|
||||
| 64 = @packageaccess
|
||||
| 65 = @wildcardtypeaccess
|
||||
| 66 = @declannotation
|
||||
| 67 = @uniontypeaccess
|
||||
| 68 = @lambdaexpr
|
||||
| 69 = @memberref
|
||||
| 70 = @annotatedtypeaccess
|
||||
| 71 = @typeannotation
|
||||
| 72 = @intersectiontypeaccess
|
||||
| 73 = @switchexpr
|
||||
| 74 = @errorexpr
|
||||
;
|
||||
|
||||
@classinstancexpr = @newexpr | @lambdaexpr | @memberref
|
||||
|
||||
@annotation = @declannotation | @typeannotation
|
||||
@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess
|
||||
|
||||
@assignment = @assignexpr
|
||||
| @assignop;
|
||||
|
||||
@unaryassignment = @postincexpr
|
||||
| @postdecexpr
|
||||
| @preincexpr
|
||||
| @predecexpr;
|
||||
|
||||
@assignop = @assignaddexpr
|
||||
| @assignsubexpr
|
||||
| @assignmulexpr
|
||||
| @assigndivexpr
|
||||
| @assignremexpr
|
||||
| @assignandexpr
|
||||
| @assignorexpr
|
||||
| @assignxorexpr
|
||||
| @assignlshiftexpr
|
||||
| @assignrshiftexpr
|
||||
| @assignurshiftexpr;
|
||||
|
||||
@literal = @booleanliteral
|
||||
| @integerliteral
|
||||
| @longliteral
|
||||
| @floatingpointliteral
|
||||
| @doubleliteral
|
||||
| @characterliteral
|
||||
| @stringliteral
|
||||
| @nullliteral;
|
||||
|
||||
@binaryexpr = @mulexpr
|
||||
| @divexpr
|
||||
| @remexpr
|
||||
| @addexpr
|
||||
| @subexpr
|
||||
| @lshiftexpr
|
||||
| @rshiftexpr
|
||||
| @urshiftexpr
|
||||
| @andbitexpr
|
||||
| @orbitexpr
|
||||
| @xorbitexpr
|
||||
| @andlogicalexpr
|
||||
| @orlogicalexpr
|
||||
| @ltexpr
|
||||
| @gtexpr
|
||||
| @leexpr
|
||||
| @geexpr
|
||||
| @eqexpr
|
||||
| @neexpr;
|
||||
|
||||
@unaryexpr = @postincexpr
|
||||
| @postdecexpr
|
||||
| @preincexpr
|
||||
| @predecexpr
|
||||
| @minusexpr
|
||||
| @plusexpr
|
||||
| @bitnotexpr
|
||||
| @lognotexpr;
|
||||
|
||||
@caller = @classinstancexpr
|
||||
| @methodaccess
|
||||
| @constructorinvocationstmt
|
||||
| @superconstructorinvocationstmt;
|
||||
|
||||
callableBinding(
|
||||
unique int callerid: @caller ref,
|
||||
int callee: @callable ref
|
||||
);
|
||||
|
||||
memberRefBinding(
|
||||
unique int id: @expr ref,
|
||||
int callable: @callable ref
|
||||
);
|
||||
|
||||
@exprparent = @stmt | @expr | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable;
|
||||
|
||||
variableBinding(
|
||||
unique int expr: @varaccess ref,
|
||||
int variable: @variable ref
|
||||
);
|
||||
|
||||
@variable = @localscopevariable | @field;
|
||||
|
||||
@localscopevariable = @localvar | @param;
|
||||
|
||||
localvars(
|
||||
unique int id: @localvar,
|
||||
string nodeName: string ref,
|
||||
int typeid: @type ref,
|
||||
int parentid: @localvariabledeclexpr ref
|
||||
);
|
||||
|
||||
@namedexprorstmt = @breakstmt
|
||||
| @continuestmt
|
||||
| @labeledstmt
|
||||
| @literal;
|
||||
|
||||
namestrings(
|
||||
string name: string ref,
|
||||
string value: string ref,
|
||||
unique int parent: @namedexprorstmt ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Modules
|
||||
*/
|
||||
|
||||
#keyset[name]
|
||||
modules(
|
||||
unique int id: @module,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
isOpen(
|
||||
int id: @module ref
|
||||
);
|
||||
|
||||
#keyset[fileId]
|
||||
cumodule(
|
||||
int fileId: @file ref,
|
||||
int moduleId: @module ref
|
||||
);
|
||||
|
||||
@directive = @requires
|
||||
| @exports
|
||||
| @opens
|
||||
| @uses
|
||||
| @provides
|
||||
|
||||
#keyset[directive]
|
||||
directives(
|
||||
int id: @module ref,
|
||||
int directive: @directive ref
|
||||
);
|
||||
|
||||
requires(
|
||||
unique int id: @requires,
|
||||
int target: @module ref
|
||||
);
|
||||
|
||||
isTransitive(
|
||||
int id: @requires ref
|
||||
);
|
||||
|
||||
isStatic(
|
||||
int id: @requires ref
|
||||
);
|
||||
|
||||
exports(
|
||||
unique int id: @exports,
|
||||
int target: @package ref
|
||||
);
|
||||
|
||||
exportsTo(
|
||||
int id: @exports ref,
|
||||
int target: @module ref
|
||||
);
|
||||
|
||||
opens(
|
||||
unique int id: @opens,
|
||||
int target: @package ref
|
||||
);
|
||||
|
||||
opensTo(
|
||||
int id: @opens ref,
|
||||
int target: @module ref
|
||||
);
|
||||
|
||||
uses(
|
||||
unique int id: @uses,
|
||||
string serviceInterface: string ref
|
||||
);
|
||||
|
||||
provides(
|
||||
unique int id: @provides,
|
||||
string serviceInterface: string ref
|
||||
);
|
||||
|
||||
providesWith(
|
||||
int id: @provides ref,
|
||||
string serviceImpl: string ref
|
||||
);
|
||||
|
||||
/*
|
||||
* Javadoc
|
||||
*/
|
||||
|
||||
javadoc(
|
||||
unique int id: @javadoc
|
||||
);
|
||||
|
||||
isNormalComment(
|
||||
int commentid : @javadoc ref
|
||||
);
|
||||
|
||||
isEolComment(
|
||||
int commentid : @javadoc ref
|
||||
);
|
||||
|
||||
hasJavadoc(
|
||||
int documentableid: @member ref,
|
||||
int javadocid: @javadoc ref
|
||||
);
|
||||
|
||||
#keyset[parentid,idx]
|
||||
javadocTag(
|
||||
unique int id: @javadocTag,
|
||||
string name: string ref,
|
||||
int parentid: @javadocParent ref,
|
||||
int idx: int ref
|
||||
);
|
||||
|
||||
#keyset[parentid,idx]
|
||||
javadocText(
|
||||
unique int id: @javadocText,
|
||||
string text: string ref,
|
||||
int parentid: @javadocParent ref,
|
||||
int idx: int ref
|
||||
);
|
||||
|
||||
@javadocParent = @javadoc | @javadocTag;
|
||||
@javadocElement = @javadocTag | @javadocText;
|
||||
|
||||
@classorinterface = @interface | @class;
|
||||
@classorinterfaceorpackage = @classorinterface | @package;
|
||||
@classorinterfaceorcallable = @classorinterface | @callable;
|
||||
@boundedtype = @typevariable | @wildcard;
|
||||
@reftype = @classorinterface | @array | @boundedtype;
|
||||
@classorarray = @class | @array;
|
||||
@type = @primitive | @reftype;
|
||||
@callable = @method | @constructor;
|
||||
@element = @file | @package | @primitive | @class | @interface | @method | @constructor | @modifier | @param | @exception | @field |
|
||||
@annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl;
|
||||
|
||||
@modifiable = @member_modifiable| @param | @localvar ;
|
||||
|
||||
@member_modifiable = @class | @interface | @method | @constructor | @field ;
|
||||
|
||||
@member = @method | @constructor | @field | @reftype ;
|
||||
|
||||
@locatable = @file | @class | @interface | @fielddecl | @field | @constructor | @method | @param | @exception
|
||||
| @boundedtype | @typebound | @array | @primitive
|
||||
| @import | @stmt | @expr | @localvar | @javadoc | @javadocTag | @javadocText
|
||||
| @xmllocatable;
|
||||
|
||||
@top = @element | @locatable | @folder;
|
||||
|
||||
/*
|
||||
* XML Files
|
||||
*/
|
||||
|
||||
xmlEncoding(
|
||||
unique int id: @file ref,
|
||||
string encoding: string ref
|
||||
);
|
||||
|
||||
xmlDTDs(
|
||||
unique int id: @xmldtd,
|
||||
string root: string ref,
|
||||
string publicId: string ref,
|
||||
string systemId: string ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlElements(
|
||||
unique int id: @xmlelement,
|
||||
string name: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int idx: int ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlAttrs(
|
||||
unique int id: @xmlattribute,
|
||||
int elementid: @xmlelement ref,
|
||||
string name: string ref,
|
||||
string value: string ref,
|
||||
int idx: int ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlNs(
|
||||
int id: @xmlnamespace,
|
||||
string prefixName: string ref,
|
||||
string URI: string ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlHasNs(
|
||||
int elementId: @xmlnamespaceable ref,
|
||||
int nsId: @xmlnamespace ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlComments(
|
||||
unique int id: @xmlcomment,
|
||||
string text: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
xmlChars(
|
||||
unique int id: @xmlcharacters,
|
||||
string text: string ref,
|
||||
int parentid: @xmlparent ref,
|
||||
int idx: int ref,
|
||||
int isCDATA: int ref,
|
||||
int fileid: @file ref
|
||||
);
|
||||
|
||||
@xmlparent = @file | @xmlelement;
|
||||
@xmlnamespaceable = @xmlelement | @xmlattribute;
|
||||
|
||||
xmllocations(
|
||||
int xmlElement: @xmllocatable ref,
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
|
||||
|
||||
/*
|
||||
* configuration files with key value pairs
|
||||
*/
|
||||
|
||||
configs(
|
||||
unique int id: @config
|
||||
);
|
||||
|
||||
configNames(
|
||||
unique int id: @configName,
|
||||
int config: @config ref,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
configValues(
|
||||
unique int id: @configValue,
|
||||
int config: @config ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
configLocations(
|
||||
int locatable: @configLocatable ref,
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
@configLocatable = @config | @configName | @configValue;
|
||||
@@ -1,3 +0,0 @@
|
||||
description: Add @errorstmt, @errorexpr
|
||||
compatibility: backwards
|
||||
|
||||
@@ -1,15 +1,178 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import sys
|
||||
import json
|
||||
import os
|
||||
import os.path
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
# Add Model as Data script directory to sys.path.
|
||||
gitroot = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip()
|
||||
madpath = os.path.join(gitroot, "misc/scripts/models-as-data/")
|
||||
sys.path.append(madpath)
|
||||
|
||||
import generate_flow_model as model
|
||||
def printHelp():
|
||||
print("""Usage:
|
||||
GenerateFlowModel.py <library-database> <outputQll> [--with-sinks] [--with-sources] [--with-summaries]
|
||||
|
||||
language = "java"
|
||||
model.Generator.make(language).run()
|
||||
This generates summary, source and sink models for the code in the database.
|
||||
The files will be placed in `java/ql/lib/semmle/code/java/frameworks/<outputQll>` where
|
||||
outputQll is the name (and path) of the output QLL file. Usually, models are grouped by their
|
||||
respective frameworks.
|
||||
|
||||
Which models are generated is controlled by the flags:
|
||||
--with-sinks
|
||||
--with-sources
|
||||
--with-summaries
|
||||
If none of these flags are specified, all models are generated.
|
||||
|
||||
Example invocations:
|
||||
$ GenerateFlowModel.py /tmp/dbs/apache_commons-codec_45649c8 "apache/Codec.qll"
|
||||
$ GenerateFlowModel.py /tmp/dbs/jdk15_db "javase/jdk_sinks.qll" --with-sinks
|
||||
|
||||
Requirements: `codeql` should both appear on your path.
|
||||
""")
|
||||
|
||||
|
||||
if any(s == "--help" for s in sys.argv):
|
||||
printHelp()
|
||||
sys.exit(0)
|
||||
|
||||
generateSinks = False
|
||||
generateSources = False
|
||||
generateSummaries = False
|
||||
if "--with-sinks" in sys.argv:
|
||||
sys.argv.remove("--with-sinks")
|
||||
generateSinks = True
|
||||
|
||||
if "--with-sources" in sys.argv:
|
||||
sys.argv.remove("--with-sources")
|
||||
generateSources = True
|
||||
|
||||
if "--with-summaries" in sys.argv:
|
||||
sys.argv.remove("--with-summaries")
|
||||
generateSummaries = True
|
||||
|
||||
if not generateSinks and not generateSources and not generateSummaries:
|
||||
generateSinks = generateSources = generateSummaries = True
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
printHelp()
|
||||
sys.exit(1)
|
||||
|
||||
codeQlRoot = subprocess.check_output(
|
||||
["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip()
|
||||
targetQll = sys.argv[2]
|
||||
if not targetQll.endswith(".qll"):
|
||||
targetQll += ".qll"
|
||||
filename = os.path.basename(targetQll)
|
||||
shortname = filename[:-4]
|
||||
generatedFrameworks = os.path.join(
|
||||
codeQlRoot, "java/ql/lib/semmle/code/java/frameworks/")
|
||||
frameworkTarget = os.path.join(generatedFrameworks, targetQll)
|
||||
|
||||
workDir = tempfile.mkdtemp()
|
||||
os.makedirs(generatedFrameworks, exist_ok=True)
|
||||
|
||||
|
||||
def runQuery(infoMessage, query):
|
||||
print("########## Querying " + infoMessage + "...")
|
||||
database = sys.argv[1]
|
||||
queryFile = os.path.join(os.path.dirname(
|
||||
__file__), query)
|
||||
resultBqrs = os.path.join(workDir, "out.bqrs")
|
||||
cmd = ['codeql', 'query', 'run', queryFile, '--database',
|
||||
database, '--output', resultBqrs, '--threads', '8']
|
||||
|
||||
ret = subprocess.call(cmd)
|
||||
if ret != 0:
|
||||
print("Failed to generate " + infoMessage +
|
||||
". Failed command was: " + shlex.join(cmd))
|
||||
sys.exit(1)
|
||||
return readRows(resultBqrs)
|
||||
|
||||
|
||||
def readRows(bqrsFile):
|
||||
generatedJson = os.path.join(workDir, "out.json")
|
||||
cmd = ['codeql', 'bqrs', 'decode', bqrsFile,
|
||||
'--format=json', '--output', generatedJson]
|
||||
ret = subprocess.call(cmd)
|
||||
if ret != 0:
|
||||
print("Failed to decode BQRS. Failed command was: " + shlex.join(cmd))
|
||||
sys.exit(1)
|
||||
|
||||
with open(generatedJson) as f:
|
||||
results = json.load(f)
|
||||
|
||||
try:
|
||||
results['#select']['tuples']
|
||||
except KeyError:
|
||||
print('Unexpected JSON output - no tuples found')
|
||||
exit(1)
|
||||
|
||||
rows = ""
|
||||
for (row) in results['#select']['tuples']:
|
||||
rows += " \"" + row[0] + "\",\n"
|
||||
|
||||
return rows[:-2]
|
||||
|
||||
|
||||
def asCsvModel(superclass, kind, rows):
|
||||
classTemplate = """
|
||||
private class {0}{1}Csv extends {2} {{
|
||||
override predicate row(string row) {{
|
||||
row =
|
||||
[
|
||||
{3}
|
||||
]
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
if rows.strip() == "":
|
||||
return ""
|
||||
return classTemplate.format(shortname[0].upper() + shortname[1:], kind.capitalize(), superclass, rows)
|
||||
|
||||
|
||||
if generateSummaries:
|
||||
summaryRows = runQuery("summary models", "CaptureSummaryModels.ql")
|
||||
summaryCsv = asCsvModel("SummaryModelCsv", "summary", summaryRows)
|
||||
else:
|
||||
summaryCsv = ""
|
||||
|
||||
if generateSinks:
|
||||
sinkRows = runQuery("sink models", "CaptureSinkModels.ql")
|
||||
sinkCsv = asCsvModel("SinkModelCsv", "sinks", sinkRows)
|
||||
else:
|
||||
sinkCsv = ""
|
||||
|
||||
if generateSources:
|
||||
sourceRows = runQuery("source models", "CaptureSourceModels.ql")
|
||||
sourceCsv = asCsvModel("SourceModelCsv", "sources", sourceRows)
|
||||
else:
|
||||
sourceCsv = ""
|
||||
|
||||
qllTemplate = """
|
||||
/** Definitions of taint steps in the {0} framework */
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
{1}
|
||||
{2}
|
||||
{3}
|
||||
|
||||
"""
|
||||
|
||||
|
||||
qllContents = qllTemplate.format(shortname, sinkCsv, sourceCsv, summaryCsv)
|
||||
|
||||
|
||||
with open(frameworkTarget, "w") as frameworkQll:
|
||||
frameworkQll.write(qllContents)
|
||||
|
||||
cmd = ['codeql', 'query', 'format', '--in-place', frameworkTarget]
|
||||
ret = subprocess.call(cmd)
|
||||
if ret != 0:
|
||||
print("Failed to format query. Failed command was: " + shlex.join(cmd))
|
||||
sys.exit(1)
|
||||
|
||||
print("")
|
||||
print("CSV model written to " + frameworkTarget)
|
||||
|
||||
@@ -192,8 +192,8 @@ class Test {
|
||||
sink(StringUtils.rotate(taint(), 0)); // $hasTaintFlow
|
||||
sink(StringUtils.split(taint())); // $hasTaintFlow
|
||||
sink(StringUtils.split(taint(), ' ')); // $hasTaintFlow
|
||||
sink(StringUtils.split(taint(), " ,;")); // $hasTaintFlow
|
||||
sink(StringUtils.split(taint(), " ,;", 0)); // $hasTaintFlow
|
||||
sink(StringUtils.split(taint(), " ,; // $hasTaintFlow")); // $hasTaintFlow
|
||||
sink(StringUtils.split(taint(), " ,; // $hasTaintFlow", 0)); // $hasTaintFlow
|
||||
sink(StringUtils.splitByCharacterType(taint())); // $hasTaintFlow
|
||||
sink(StringUtils.splitByCharacterTypeCamelCase(taint())); // $hasTaintFlow
|
||||
sink(StringUtils.splitByWholeSeparator(taint(), "separator")); // $hasTaintFlow
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/javascript-experimental-atm-lib
|
||||
version: 0.2.1
|
||||
version: 0.1.1
|
||||
extractor: javascript
|
||||
library: true
|
||||
groups:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: codeql/javascript-experimental-atm-model
|
||||
version: 0.1.1
|
||||
version: 0.0.6
|
||||
groups:
|
||||
- javascript
|
||||
- experimental
|
||||
mlModels:
|
||||
- "resources/*.codeqlmodel"
|
||||
- "resources/*.codeqlmodel"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-model:
|
||||
version: 0.1.0
|
||||
version: 0.0.6
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
|
||||
@@ -75,11 +75,7 @@ private DataFlow::Node getANotASink(NotASinkReason reason) {
|
||||
*/
|
||||
private DataFlow::Node getAnUnknown(Query query) {
|
||||
getAtmCfg(query).isEffectiveSink(result) and
|
||||
// Effective sinks should exclude sinks but this is a defensive requirement
|
||||
not result = getASink(query) and
|
||||
// Effective sinks should exclude NotASink but for some queries (e.g. Xss) this is currently not always the case and
|
||||
// so this is a defensive requirement
|
||||
not result = getANotASink(_) and
|
||||
// Only consider the source code for the project being analyzed.
|
||||
exists(result.getFile().getRelativePath())
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ groups:
|
||||
- experimental
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-lib: "*"
|
||||
codeql/javascript-experimental-atm-model: "0.1.0"
|
||||
codeql/javascript-experimental-atm-model: "0.0.6"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-model:
|
||||
version: 0.1.0
|
||||
version: 0.0.6
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: codeql/javascript-experimental-atm-queries
|
||||
language: javascript
|
||||
version: 0.2.1
|
||||
version: 0.1.1
|
||||
suites: codeql-suites
|
||||
defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls
|
||||
groups:
|
||||
@@ -8,4 +8,4 @@ groups:
|
||||
- experimental
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-lib: "*"
|
||||
codeql/javascript-experimental-atm-model: "0.1.0"
|
||||
codeql/javascript-experimental-atm-model: "0.0.6"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
dependencies:
|
||||
codeql/javascript-experimental-atm-model:
|
||||
version: 0.1.0
|
||||
version: 0.0.6
|
||||
compiled: false
|
||||
lockVersion: 1.0.0
|
||||
|
||||
@@ -8434,24 +8434,24 @@ tokenFeatures
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:14:15:14:29 | d => getTaint() | enclosingFunctionBody | d3 select #main attr width 100 style color red html getTaint html d getTaint call otherFunction html d getTaint |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:14:15:14:29 | d => getTaint() | enclosingFunctionName | doSomething |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | argumentIndex | 0 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeAccessPath | d3 select attr style html html call selection attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeAccessPath | d3 select attr style html html call selection attr d3 select attr style html html selection attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn functionalarg param selection member attr instanceorreturn d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeApiName | d3 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeName | attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | enclosingFunctionBody | selection selection attr foo bar html getTaint |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | enclosingFunctionName | otherFunction |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | receiverName | selection |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | argumentIndex | 1 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeAccessPath | d3 select attr style html html call selection attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeAccessPath | d3 select attr style html html call selection attr d3 select attr style html html selection attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn functionalarg param selection member attr instanceorreturn d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeApiName | d3 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeName | attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | enclosingFunctionBody | selection selection attr foo bar html getTaint |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | enclosingFunctionName | otherFunction |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | receiverName | selection |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | argumentIndex | 0 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPath | d3 select attr style html html call selection attr html |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn member html instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPath | d3 select attr style html html call selection attr html d3 select attr style html html selection attr html |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn functionalarg param selection member attr instanceorreturn member html instanceorreturn d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn member html instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeApiName | d3 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeName | html |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | enclosingFunctionBody | selection selection attr foo bar html getTaint |
|
||||
|
||||
@@ -37241,24 +37241,24 @@ tokenFeatures
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:14:20:14:29 | getTaint() | enclosingFunctionName | doSomething |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:14:20:14:29 | getTaint() | receiverName | |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | argumentIndex | 0 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeAccessPath | d3 select attr style html html call selection attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeAccessPath | d3 select attr style html html call selection attr d3 select attr style html html selection attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn functionalarg param selection member attr instanceorreturn d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeApiName | d3 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeName | attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | enclosingFunctionBody | selection selection attr foo bar html getTaint |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | enclosingFunctionName | otherFunction |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | receiverName | selection |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | argumentIndex | 1 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeAccessPath | d3 select attr style html html call selection attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeAccessPath | d3 select attr style html html call selection attr d3 select attr style html html selection attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn functionalarg param selection member attr instanceorreturn d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeApiName | d3 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeName | attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | enclosingFunctionBody | selection selection attr foo bar html getTaint |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | enclosingFunctionName | otherFunction |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | receiverName | selection |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | argumentIndex | 0 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPath | d3 select attr style html html call selection attr html |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn member html instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPath | d3 select attr style html html call selection attr html d3 select attr style html html selection attr html |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn functionalarg param selection member attr instanceorreturn member html instanceorreturn d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn member html instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeApiName | d3 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeName | html |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | enclosingFunctionBody | selection selection attr foo bar html getTaint |
|
||||
|
||||
@@ -37241,24 +37241,24 @@ tokenFeatures
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:14:20:14:29 | getTaint() | enclosingFunctionName | doSomething |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:14:20:14:29 | getTaint() | receiverName | |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | argumentIndex | 0 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeAccessPath | d3 select attr style html html call selection attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeAccessPath | d3 select attr style html html call selection attr d3 select attr style html html selection attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn functionalarg param selection member attr instanceorreturn d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeApiName | d3 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | calleeName | attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | enclosingFunctionBody | selection selection attr foo bar html getTaint |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | enclosingFunctionName | otherFunction |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:15:20:19 | 'foo' | receiverName | selection |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | argumentIndex | 1 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeAccessPath | d3 select attr style html html call selection attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeAccessPath | d3 select attr style html html call selection attr d3 select attr style html html selection attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn functionalarg param selection member attr instanceorreturn d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeApiName | d3 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | calleeName | attr |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | enclosingFunctionBody | selection selection attr foo bar html getTaint |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | enclosingFunctionName | otherFunction |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:20:22:20:26 | 'bar' | receiverName | selection |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | argumentIndex | 0 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPath | d3 select attr style html html call selection attr html |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn member html instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPath | d3 select attr style html html call selection attr html d3 select attr style html html selection attr html |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn functionalarg param selection member attr instanceorreturn member html instanceorreturn d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn member html instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeApiName | d3 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeName | html |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | enclosingFunctionBody | selection selection attr foo bar html getTaint |
|
||||
|
||||
@@ -9393,8 +9393,8 @@ tokenFeatures
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:14:20:14:29 | getTaint() | enclosingFunctionName | doSomething |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:14:20:14:29 | getTaint() | receiverName | |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | argumentIndex | 0 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPath | d3 select attr style html html call selection attr html |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn member html instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPath | d3 select attr style html html call selection attr html d3 select attr style html html selection attr html |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeAccessPathWithStructuralInfo | d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn functionalarg param selection member attr instanceorreturn member html instanceorreturn d3 member select instanceorreturn member attr instanceorreturn member style instanceorreturn member html instanceorreturn member html instanceorreturn member call functionalarg param selection member attr instanceorreturn member html instanceorreturn |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeApiName | d3 |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | calleeName | html |
|
||||
| autogenerated/Xss/DomBasedXss/d3.js:21:15:21:24 | getTaint() | enclosingFunctionBody | selection selection attr foo bar html getTaint |
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* The following predicates on `API::Node` have been changed so as not to include the receiver. The receiver should now only be accessed via `getReceiver()`.
|
||||
- `getParameter(int i)` previously included the receiver when `i = -1`
|
||||
- `getAParameter()` previously included the receiver
|
||||
- `getLastParameter()` previously included the receiver for calls with no arguments
|
||||
@@ -187,7 +187,8 @@ module API {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node representing a parameter of the function represented by this node.
|
||||
* Gets a node representing a parameter or the receiver of the function represented by this
|
||||
* node.
|
||||
*
|
||||
* This predicate may result in a mix of parameters from different call sites in cases where
|
||||
* there are multiple invocations of this API component.
|
||||
@@ -197,6 +198,8 @@ module API {
|
||||
Node getAParameter() {
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getParameter(_)
|
||||
or
|
||||
result = this.getReceiver()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -558,10 +561,9 @@ module API {
|
||||
rhs = f.getExceptionalReturn()
|
||||
)
|
||||
or
|
||||
exists(int i | argumentPassing(base, i, rhs) |
|
||||
lbl = Label::parameter(i)
|
||||
or
|
||||
i = -1 and lbl = Label::receiver()
|
||||
exists(int i |
|
||||
lbl = Label::parameter(i) and
|
||||
argumentPassing(base, i, rhs)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::SourceNode src, DataFlow::PropWrite pw |
|
||||
@@ -1094,8 +1096,8 @@ module API {
|
||||
*/
|
||||
LabelParameter parameter(int i) { result.getIndex() = i }
|
||||
|
||||
/** Gets the edge label for the receiver. */
|
||||
LabelReceiver receiver() { any() }
|
||||
/** Gets the `parameter` edge label for the receiver. */
|
||||
LabelParameter receiver() { result = parameter(-1) }
|
||||
|
||||
/** Gets the `return` edge label. */
|
||||
LabelReturn return() { any() }
|
||||
@@ -1130,13 +1132,12 @@ module API {
|
||||
MkLabelUnknownMember() or
|
||||
MkLabelParameter(int i) {
|
||||
i =
|
||||
[0 .. max(int args |
|
||||
[-1 .. max(int args |
|
||||
args = any(InvokeExpr invk).getNumArgument() or
|
||||
args = any(Function f).getNumParameter()
|
||||
)] or
|
||||
i = [0 .. 10]
|
||||
} or
|
||||
MkLabelReceiver() or
|
||||
MkLabelReturn() or
|
||||
MkLabelPromised() or
|
||||
MkLabelPromisedError() or
|
||||
@@ -1224,11 +1225,6 @@ module API {
|
||||
/** Gets the index of the parameter for this label. */
|
||||
int getIndex() { result = i }
|
||||
}
|
||||
|
||||
/** A label for the receiver of call, that is, the value passed as `this`. */
|
||||
class LabelReceiver extends ApiLabel, MkLabelReceiver {
|
||||
override string toString() { result = "receiver" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,35 +354,6 @@ module DOM {
|
||||
call.getNumArgument() = 1 and
|
||||
unique(InferredType t | t = getArgumentTypeFromJQueryMethodGet(call)) = TTNumber()
|
||||
)
|
||||
or
|
||||
// A `this` node from a callback given to a `$().each(callback)` call.
|
||||
// purposely not using JQuery::MethodCall to avoid `jquery.each()`.
|
||||
exists(DataFlow::CallNode eachCall | eachCall = JQuery::objectRef().getAMethodCall("each") |
|
||||
this = DataFlow::thisNode(eachCall.getCallback(0).getFunction()) or
|
||||
this = eachCall.getABoundCallbackParameter(0, 1)
|
||||
)
|
||||
or
|
||||
// A read of an array-element from a JQuery object. E.g. `$("#foo")[0]`
|
||||
exists(DataFlow::PropRead read |
|
||||
read = this and read = JQuery::objectRef().getAPropertyRead()
|
||||
|
|
||||
unique(InferredType t | t = read.getPropertyNameExpr().analyze().getAType()) = TTNumber()
|
||||
)
|
||||
or
|
||||
// A receiver node of an event handler on a DOM node
|
||||
exists(DataFlow::SourceNode domNode, DataFlow::FunctionNode eventHandler |
|
||||
// NOTE: we do not use `getABoundFunctionValue()`, since bound functions tend to have
|
||||
// a different receiver anyway
|
||||
eventHandler = domNode.getAPropertySource(any(string n | n.matches("on%")))
|
||||
or
|
||||
eventHandler =
|
||||
domNode.getAMethodCall("addEventListener").getArgument(1).getAFunctionValue()
|
||||
|
|
||||
domNode = domValueRef() and
|
||||
this = eventHandler.getReceiver()
|
||||
)
|
||||
or
|
||||
this = DataFlow::thisNode(any(EventHandlerCode evt))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -416,11 +387,6 @@ module DOM {
|
||||
or
|
||||
t.start() and
|
||||
result = domValueRef().getAMethodCall(["item", "namedItem"])
|
||||
or
|
||||
t.startInProp("target") and
|
||||
result = domEventSource()
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = domValueRef(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a data flow node that may refer to a value from the DOM. */
|
||||
|
||||
@@ -183,12 +183,12 @@ module Promises {
|
||||
/**
|
||||
* Gets the pseudo-field used to describe resolved values in a promise.
|
||||
*/
|
||||
string valueProp() { result = "$PromiseResolveField$" }
|
||||
string valueProp() { none() }
|
||||
|
||||
/**
|
||||
* Gets the pseudo-field used to describe rejected values in a promise.
|
||||
*/
|
||||
string errorProp() { result = "$PromiseRejectField$" }
|
||||
string errorProp() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -756,10 +756,10 @@ private class AdditionalFlowStepAsSharedStep extends SharedFlowStep {
|
||||
*/
|
||||
module PseudoProperties {
|
||||
bindingset[s]
|
||||
private string pseudoProperty(string s) { result = "$" + s + "$" }
|
||||
private string pseudoProperty(string s) { none() }
|
||||
|
||||
bindingset[s, v]
|
||||
private string pseudoProperty(string s, string v) { result = "$" + s + "|" + v + "$" }
|
||||
private string pseudoProperty(string s, string v) { none() }
|
||||
|
||||
/**
|
||||
* Gets a pseudo-property for the location of elements in a `Set`
|
||||
|
||||
@@ -136,7 +136,7 @@ module Angular2 {
|
||||
|
||||
/** Gets a reference to a `DomSanitizer` object. */
|
||||
DataFlow::SourceNode domSanitizer() {
|
||||
result.hasUnderlyingType(["@angular/platform-browser", "@angular/core"], "DomSanitizer")
|
||||
result.hasUnderlyingType("@angular/platform-browser", "DomSanitizer")
|
||||
}
|
||||
|
||||
/** A value that is about to be promoted to a trusted HTML or CSS value. */
|
||||
|
||||
@@ -927,28 +927,6 @@ module Express {
|
||||
override string getCredentialsKind() { result = kind }
|
||||
}
|
||||
|
||||
/** A call to `response.sendFile`, considered as a file system access. */
|
||||
private class ResponseSendFileAsFileSystemAccess extends FileSystemReadAccess,
|
||||
DataFlow::MethodCallNode {
|
||||
ResponseSendFileAsFileSystemAccess() {
|
||||
exists(string name | name = "sendFile" or name = "sendfile" |
|
||||
this.calls(any(ResponseExpr res).flow(), name)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getADataNode() { none() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getRootPathArgument() {
|
||||
result = this.(DataFlow::CallNode).getOptionArgument(1, "root")
|
||||
}
|
||||
|
||||
override predicate isUpwardNavigationRejected(DataFlow::Node argument) {
|
||||
argument = this.getAPathArgument()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that flows to a route setup.
|
||||
*/
|
||||
|
||||
@@ -4,23 +4,6 @@
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* A call that can produce a file name.
|
||||
*/
|
||||
abstract private class FileNameProducer extends DataFlow::Node {
|
||||
/**
|
||||
* Gets a file name produced by this producer.
|
||||
*/
|
||||
abstract DataFlow::Node getAFileName();
|
||||
}
|
||||
|
||||
/**
|
||||
* A node that contains a file name, and is produced by a `ProducesFileNames`.
|
||||
*/
|
||||
private class ProducedFileName extends FileNameSource {
|
||||
ProducedFileName() { this = any(FileNameProducer producer).getAFileName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A file name from the `walk-sync` library.
|
||||
*/
|
||||
@@ -118,319 +101,3 @@ private API::Node fastGlobFileName() {
|
||||
private class FastGlobFileNameSource extends FileNameSource {
|
||||
FastGlobFileNameSource() { this = fastGlobFileName().getAnImmediateUse() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Classes and predicates for modeling the `fstream` library (https://www.npmjs.com/package/fstream).
|
||||
*/
|
||||
private module FStream {
|
||||
/**
|
||||
* Gets a reference to a method in the `fstream` library.
|
||||
*/
|
||||
private DataFlow::SourceNode getAnFStreamProperty(boolean writer) {
|
||||
exists(DataFlow::SourceNode mod, string readOrWrite, string subMod |
|
||||
mod = DataFlow::moduleImport("fstream") and
|
||||
(
|
||||
readOrWrite = "Reader" and writer = false
|
||||
or
|
||||
readOrWrite = "Writer" and writer = true
|
||||
) and
|
||||
subMod = ["File", "Dir", "Link", "Proxy"]
|
||||
|
|
||||
result = mod.getAPropertyRead(readOrWrite) or
|
||||
result = mod.getAPropertyRead(readOrWrite).getAPropertyRead(subMod) or
|
||||
result = mod.getAPropertyRead(subMod).getAPropertyRead(readOrWrite)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An invocation of a method defined in the `fstream` library.
|
||||
*/
|
||||
private class FStream extends FileSystemAccess, DataFlow::InvokeNode {
|
||||
boolean writer;
|
||||
|
||||
FStream() { this = getAnFStreamProperty(writer).getAnInvocation() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
result = this.getOptionArgument(0, "path")
|
||||
or
|
||||
not exists(this.getOptionArgument(0, "path")) and
|
||||
result = this.getArgument(0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An invocation of an `fstream` method that writes to a file.
|
||||
*/
|
||||
private class FStreamWriter extends FileSystemWriteAccess, FStream {
|
||||
FStreamWriter() { writer = true }
|
||||
|
||||
override DataFlow::Node getADataNode() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An invocation of an `fstream` method that reads a file.
|
||||
*/
|
||||
private class FStreamReader extends FileSystemReadAccess, FStream {
|
||||
FStreamReader() { writer = false }
|
||||
|
||||
override DataFlow::Node getADataNode() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the library `write-file-atomic`.
|
||||
*/
|
||||
private class WriteFileAtomic extends FileSystemWriteAccess, DataFlow::CallNode {
|
||||
WriteFileAtomic() {
|
||||
this = DataFlow::moduleImport("write-file-atomic").getACall()
|
||||
or
|
||||
this = DataFlow::moduleMember("write-file-atomic", "sync").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getADataNode() { result = this.getArgument(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the library `recursive-readdir`.
|
||||
*/
|
||||
private class RecursiveReadDir extends FileSystemAccess, FileNameProducer, API::CallNode {
|
||||
RecursiveReadDir() { this = API::moduleImport("recursive-readdir").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getAFileName() { result = this.trackFileSource().getAnImmediateUse() }
|
||||
|
||||
private API::Node trackFileSource() {
|
||||
result = this.getParameter([1 .. 2]).getParameter(1)
|
||||
or
|
||||
not exists(this.getCallback([1 .. 2])) and result = this.getReturn().getPromised()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Classes and predicates for modeling the `jsonfile` library (https://www.npmjs.com/package/jsonfile).
|
||||
*/
|
||||
private module JsonFile {
|
||||
/**
|
||||
* A reader for JSON files.
|
||||
*/
|
||||
class JsonFileReader extends FileSystemReadAccess, API::CallNode {
|
||||
JsonFileReader() {
|
||||
this = API::moduleImport("jsonfile").getMember(["readFile", "readFileSync"]).getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getADataNode() { result = this.trackRead().getAnImmediateUse() }
|
||||
|
||||
private API::Node trackRead() {
|
||||
this.getCalleeName() = "readFile" and
|
||||
(
|
||||
result = this.getParameter([1 .. 2]).getParameter(1)
|
||||
or
|
||||
not exists(this.getCallback([1 .. 2])) and result = this.getReturn().getPromised()
|
||||
)
|
||||
or
|
||||
this.getCalleeName() = "readFileSync" and
|
||||
result = this.getReturn()
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonFileReader */
|
||||
deprecated class JSONFileReader = JsonFileReader;
|
||||
|
||||
/**
|
||||
* A writer for JSON files.
|
||||
*/
|
||||
class JsonFileWriter extends FileSystemWriteAccess, DataFlow::CallNode {
|
||||
JsonFileWriter() {
|
||||
this =
|
||||
DataFlow::moduleMember("jsonfile", any(string s | s = "writeFile" or s = "writeFileSync"))
|
||||
.getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getADataNode() { result = this.getArgument(1) }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsonFileWriter */
|
||||
deprecated class JSONFileWriter = JsonFileWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the library `load-json-file`.
|
||||
*/
|
||||
private class LoadJsonFile extends FileSystemReadAccess, API::CallNode {
|
||||
LoadJsonFile() {
|
||||
this = API::moduleImport("load-json-file").getACall()
|
||||
or
|
||||
this = API::moduleImport("load-json-file").getMember("sync").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getADataNode() { result = this.trackRead().getAnImmediateUse() }
|
||||
|
||||
private API::Node trackRead() {
|
||||
this.getCalleeName() = "sync" and result = this.getReturn()
|
||||
or
|
||||
not this.getCalleeName() = "sync" and result = this.getReturn().getPromised()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the library `write-json-file`.
|
||||
*/
|
||||
private class WriteJsonFile extends FileSystemWriteAccess, DataFlow::CallNode {
|
||||
WriteJsonFile() {
|
||||
this = DataFlow::moduleImport("write-json-file").getACall()
|
||||
or
|
||||
this = DataFlow::moduleMember("write-json-file", "sync").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getADataNode() { result = this.getArgument(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the library `walkdir`.
|
||||
*/
|
||||
private class WalkDir extends FileNameProducer, FileSystemAccess, API::CallNode {
|
||||
WalkDir() {
|
||||
this = API::moduleImport("walkdir").getACall()
|
||||
or
|
||||
this = API::moduleImport("walkdir").getMember("sync").getACall()
|
||||
or
|
||||
this = API::moduleImport("walkdir").getMember("async").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getAFileName() { result = this.trackFileSource().getAnImmediateUse() }
|
||||
|
||||
private API::Node trackFileSource() {
|
||||
not this.getCalleeName() = ["sync", "async"] and
|
||||
(
|
||||
result = this.getParameter(this.getNumArgument() - 1).getParameter(0)
|
||||
or
|
||||
result = this.getReturn().getMember(EventEmitter::on()).getParameter(1).getParameter(0)
|
||||
)
|
||||
or
|
||||
this.getCalleeName() = "sync" and result = this.getReturn()
|
||||
or
|
||||
this.getCalleeName() = "async" and result = this.getReturn().getPromised()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the library `globule`.
|
||||
*/
|
||||
private class Globule extends FileNameProducer, FileSystemAccess, DataFlow::CallNode {
|
||||
Globule() {
|
||||
this = DataFlow::moduleMember("globule", "find").getACall()
|
||||
or
|
||||
this = DataFlow::moduleMember("globule", "match").getACall()
|
||||
or
|
||||
this = DataFlow::moduleMember("globule", "isMatch").getACall()
|
||||
or
|
||||
this = DataFlow::moduleMember("globule", "mapping").getACall()
|
||||
or
|
||||
this = DataFlow::moduleMember("globule", "findMapping").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() {
|
||||
(this.getCalleeName() = "match" or this.getCalleeName() = "isMatch") and
|
||||
result = this.getArgument(1)
|
||||
or
|
||||
this.getCalleeName() = "mapping" and
|
||||
(
|
||||
result = this.getAnArgument() and
|
||||
not exists(result.getALocalSource().getAPropertyWrite("src"))
|
||||
or
|
||||
result = this.getAnArgument().getALocalSource().getAPropertyWrite("src").getRhs()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getAFileName() {
|
||||
result = this and
|
||||
(
|
||||
this.getCalleeName() = "find" or
|
||||
this.getCalleeName() = "match" or
|
||||
this.getCalleeName() = "findMapping" or
|
||||
this.getCalleeName() = "mapping"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A file system access made by a NodeJS library.
|
||||
* This class models multiple NodeJS libraries that access files.
|
||||
*/
|
||||
private class LibraryAccess extends FileSystemAccess, DataFlow::InvokeNode {
|
||||
int pathArgument; // The index of the path argument.
|
||||
|
||||
LibraryAccess() {
|
||||
pathArgument = 0 and
|
||||
(
|
||||
this = DataFlow::moduleImport("path-exists").getACall()
|
||||
or
|
||||
this = DataFlow::moduleImport("rimraf").getACall()
|
||||
or
|
||||
this = DataFlow::moduleImport("readdirp").getACall()
|
||||
or
|
||||
this = DataFlow::moduleImport("walker").getACall()
|
||||
or
|
||||
this =
|
||||
DataFlow::moduleMember("node-dir",
|
||||
["readFiles", "readFilesStream", "files", "promiseFiles", "subdirs", "paths"]).getACall()
|
||||
)
|
||||
or
|
||||
pathArgument = 0 and
|
||||
this =
|
||||
DataFlow::moduleMember("vinyl-fs", any(string s | s = "src" or s = "dest" or s = "symlink"))
|
||||
.getACall()
|
||||
or
|
||||
pathArgument = [0 .. 1] and
|
||||
(
|
||||
this = DataFlow::moduleImport("ncp").getACall() or
|
||||
this = DataFlow::moduleMember("ncp", "ncp").getACall()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(pathArgument) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the library [`chokidar`](https://www.npmjs.com/package/chokidar), where a call to `on` receives file names.
|
||||
*/
|
||||
class Chokidar extends FileNameProducer, FileSystemAccess, API::CallNode {
|
||||
Chokidar() { this = API::moduleImport("chokidar").getMember("watch").getACall() }
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getAFileName() {
|
||||
exists(DataFlow::CallNode onCall, int pathIndex |
|
||||
onCall = this.getAChainedMethodCall("on") and
|
||||
if onCall.getArgument(0).mayHaveStringValue("all") then pathIndex = 1 else pathIndex = 0
|
||||
|
|
||||
result = onCall.getCallback(1).getParameter(pathIndex)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the [`mkdirp`](https://www.npmjs.com/package/mkdirp) library.
|
||||
*/
|
||||
private class Mkdirp extends FileSystemAccess, API::CallNode {
|
||||
Mkdirp() {
|
||||
this = API::moduleImport("mkdirp").getACall()
|
||||
or
|
||||
this = API::moduleImport("mkdirp").getMember("sync").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
@@ -8,20 +8,7 @@ import semmle.javascript.Promises
|
||||
/** Provices classes for modelling NoSQL query sinks. */
|
||||
module NoSql {
|
||||
/** An expression that is interpreted as a NoSQL query. */
|
||||
abstract class Query extends Expr {
|
||||
/** Gets an expression that is interpreted as a code operator in this query. */
|
||||
DataFlow::Node getACodeOperator() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for NoSql */
|
||||
deprecated module NoSQL = NoSql;
|
||||
|
||||
/**
|
||||
* Gets a value that has been assigned to the "$where" property of an object that flows to `queryArg`.
|
||||
*/
|
||||
private DataFlow::Node getADollarWhereProperty(API::Node queryArg) {
|
||||
result = queryArg.getMember("$where").getARhs()
|
||||
abstract class Query extends Expr { }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,123 +16,112 @@ private DataFlow::Node getADollarWhereProperty(API::Node queryArg) {
|
||||
*/
|
||||
private module MongoDB {
|
||||
/**
|
||||
* Gets an access to `mongodb.MongoClient` or a database.
|
||||
*
|
||||
* In Mongo version 2.x, a client and a database handle were the same concept, but in 3.x
|
||||
* they were separated. To handle everything with a single model, we treat them as the same here.
|
||||
* Gets an import of MongoDB.
|
||||
*/
|
||||
private API::Node getAMongoClientOrDatabase() {
|
||||
result = API::moduleImport("mongodb").getMember("MongoClient")
|
||||
DataFlow::ModuleImportNode mongodb() { result.getPath() = "mongodb" }
|
||||
|
||||
/**
|
||||
* Gets an access to `mongodb.MongoClient`.
|
||||
*/
|
||||
private DataFlow::SourceNode getAMongoClient(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = mongodb().getAPropertyRead("MongoClient")
|
||||
or
|
||||
result = getAMongoClientOrDatabase().getMember("db").getReturn()
|
||||
exists(DataFlow::TypeTracker t2 | result = getAMongoClient(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an access to `mongodb.MongoClient`.
|
||||
*/
|
||||
DataFlow::SourceNode getAMongoClient() { result = getAMongoClient(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** Gets a data flow node that leads to a `connect` callback. */
|
||||
private DataFlow::SourceNode getAMongoDbCallback(DataFlow::TypeBackTracker t) {
|
||||
t.start() and
|
||||
result = getAMongoClient().getAMemberCall("connect").getArgument(1).getALocalSource()
|
||||
or
|
||||
result = getAMongoClientOrDatabase().getMember("connect").getLastParameter().getParameter(1)
|
||||
exists(DataFlow::TypeBackTracker t2 | result = getAMongoDbCallback(t2).backtrack(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a data flow node that leads to a `connect` callback. */
|
||||
private DataFlow::FunctionNode getAMongoDbCallback() {
|
||||
result = getAMongoDbCallback(DataFlow::TypeBackTracker::end())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expression that may refer to a MongoDB database connection.
|
||||
*/
|
||||
private DataFlow::SourceNode getAMongoDb(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = getAMongoDbCallback().getParameter(1)
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = getAMongoDb(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expression that may refer to a MongoDB database connection.
|
||||
*/
|
||||
DataFlow::SourceNode getAMongoDb() { result = getAMongoDb(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/**
|
||||
* A data flow node that may hold a MongoDB collection.
|
||||
*/
|
||||
abstract class Collection extends DataFlow::SourceNode { }
|
||||
|
||||
/**
|
||||
* A collection resulting from calling `Db.collection(...)`.
|
||||
*/
|
||||
private class CollectionFromDb extends Collection {
|
||||
CollectionFromDb() {
|
||||
this = getAMongoDb().getAMethodCall("collection")
|
||||
or
|
||||
this = getAMongoDb().getAMethodCall("collection").getCallback(1).getParameter(0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection based on the type `mongodb.Collection`.
|
||||
*
|
||||
* Note that this also covers `mongoose` models since they are subtypes
|
||||
* of `mongodb.Collection`.
|
||||
*/
|
||||
private class CollectionFromType extends Collection {
|
||||
CollectionFromType() { hasUnderlyingType("mongodb", "Collection") }
|
||||
}
|
||||
|
||||
/** Gets a data flow node referring to a MongoDB collection. */
|
||||
private API::Node getACollection() {
|
||||
// A collection resulting from calling `Db.collection(...)`.
|
||||
exists(API::Node collection |
|
||||
collection = getAMongoClientOrDatabase().getMember("collection").getReturn()
|
||||
|
|
||||
result = collection
|
||||
or
|
||||
result = collection.getParameter(1).getParameter(0)
|
||||
)
|
||||
private DataFlow::SourceNode getACollection(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result instanceof Collection
|
||||
or
|
||||
// note that this also covers `mongoose` models since they are subtypes of `mongodb.Collection`
|
||||
result = API::Node::ofType("mongodb", "Collection")
|
||||
exists(DataFlow::TypeTracker t2 | result = getACollection(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/** Gets a data flow node referring to a MongoDB collection. */
|
||||
DataFlow::SourceNode getACollection() { result = getACollection(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** A call to a MongoDB query method. */
|
||||
private class QueryCall extends DatabaseAccess, API::CallNode {
|
||||
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
|
||||
int queryArgIdx;
|
||||
|
||||
QueryCall() {
|
||||
exists(string method |
|
||||
CollectionMethodSignatures::interpretsArgumentAsQuery(method, queryArgIdx) and
|
||||
this = getACollection().getMember(method).getACall()
|
||||
exists(string m | this = getACollection().getAMethodCall(m) |
|
||||
m = "count" and queryArgIdx = 0
|
||||
or
|
||||
m = "distinct" and queryArgIdx = 1
|
||||
or
|
||||
m = "find" and queryArgIdx = 0
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { result = this.getArgument(queryArgIdx) }
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
PromiseFlow::loadStep(this.getALocalUse(), result, Promises::valueProp())
|
||||
}
|
||||
|
||||
DataFlow::Node getACodeOperator() {
|
||||
result = getADollarWhereProperty(this.getParameter(queryArgIdx))
|
||||
}
|
||||
override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is interpreted as a MongoDB query.
|
||||
*/
|
||||
class Query extends NoSql::Query {
|
||||
QueryCall qc;
|
||||
|
||||
Query() { this = qc.getAQueryArgument().asExpr() }
|
||||
|
||||
override DataFlow::Node getACodeOperator() { result = qc.getACodeOperator() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides signatures for the Collection methods.
|
||||
*/
|
||||
module CollectionMethodSignatures {
|
||||
/**
|
||||
* Holds if Collection method `name` interprets parameter `n` as a query.
|
||||
*/
|
||||
predicate interpretsArgumentAsQuery(string name, int n) {
|
||||
// FilterQuery
|
||||
(
|
||||
name = "aggregate" and n = 0
|
||||
or
|
||||
name = "count" and n = 0
|
||||
or
|
||||
name = "countDocuments" and n = 0
|
||||
or
|
||||
name = "deleteMany" and n = 0
|
||||
or
|
||||
name = "deleteOne" and n = 0
|
||||
or
|
||||
name = "distinct" and n = 1
|
||||
or
|
||||
name = "find" and n = 0
|
||||
or
|
||||
name = "findOne" and n = 0
|
||||
or
|
||||
name = "findOneAndDelete" and n = 0
|
||||
or
|
||||
name = "findOneAndRemove" and n = 0
|
||||
or
|
||||
name = "findOneAndReplace" and n = 0
|
||||
or
|
||||
name = "findOneAndUpdate" and n = 0
|
||||
or
|
||||
name = "remove" and n = 0
|
||||
or
|
||||
name = "replaceOne" and n = 0
|
||||
or
|
||||
name = "update" and n = 0
|
||||
or
|
||||
name = "updateMany" and n = 0
|
||||
or
|
||||
name = "updateOne" and n = 0
|
||||
)
|
||||
or
|
||||
// UpdateQuery
|
||||
(
|
||||
name = "findOneAndUpdate" and n = 1
|
||||
or
|
||||
name = "update" and n = 1
|
||||
or
|
||||
name = "updateMany" and n = 1
|
||||
or
|
||||
name = "updateOne" and n = 1
|
||||
)
|
||||
}
|
||||
class Query extends NoSQL::Query {
|
||||
Query() { this = any(QueryCall qc).getAQueryArgument().asExpr() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,342 +132,20 @@ private module Mongoose {
|
||||
/**
|
||||
* Gets an import of Mongoose.
|
||||
*/
|
||||
API::Node getAMongooseInstance() { result = API::moduleImport("mongoose") }
|
||||
DataFlow::ModuleImportNode getAMongooseInstance() { result.getPath() = "mongoose" }
|
||||
|
||||
/**
|
||||
* Gets a reference to `mongoose.createConnection`.
|
||||
* Gets a call to `mongoose.createConnection`.
|
||||
*/
|
||||
API::Node createConnection() { result = getAMongooseInstance().getMember("createConnection") }
|
||||
|
||||
/**
|
||||
* A Mongoose function.
|
||||
*/
|
||||
abstract private class MongooseFunction extends API::Node {
|
||||
/**
|
||||
* Gets the API-graph node for the result from this function (if the function returns a `Query`).
|
||||
*/
|
||||
abstract API::Node getQueryReturn();
|
||||
|
||||
/**
|
||||
* Holds if this function returns a `Query` that evaluates to one or
|
||||
* more Documents (`asArray` is false if it evaluates to a single
|
||||
* Document).
|
||||
*/
|
||||
abstract predicate returnsDocumentQuery(boolean asArray);
|
||||
|
||||
/**
|
||||
* Gets an argument that this function interprets as a query.
|
||||
*/
|
||||
abstract API::Node getQueryArgument();
|
||||
DataFlow::CallNode createConnection() {
|
||||
result = getAMongooseInstance().getAMemberCall("createConnection")
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modeling the Mongoose Model class
|
||||
* A Mongoose collection object.
|
||||
*/
|
||||
module Model {
|
||||
private class ModelFunction extends MongooseFunction {
|
||||
string methodName;
|
||||
|
||||
ModelFunction() { this = getModelObject().getMember(methodName) }
|
||||
|
||||
override API::Node getQueryReturn() {
|
||||
MethodSignatures::returnsQuery(methodName) and result = this.getReturn()
|
||||
}
|
||||
|
||||
override predicate returnsDocumentQuery(boolean asArray) {
|
||||
MethodSignatures::returnsDocumentQuery(methodName, asArray)
|
||||
}
|
||||
|
||||
override API::Node getQueryArgument() {
|
||||
exists(int n |
|
||||
MethodSignatures::interpretsArgumentAsQuery(methodName, n) and
|
||||
result = this.getParameter(n)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a API-graph node referring to a Mongoose Model object.
|
||||
*/
|
||||
private API::Node getModelObject() {
|
||||
result = getAMongooseInstance().getMember("model").getReturn()
|
||||
or
|
||||
exists(API::Node conn | conn = createConnection().getReturn() |
|
||||
result = conn.getMember("model").getReturn() or
|
||||
result = conn.getMember("models").getAMember()
|
||||
)
|
||||
or
|
||||
result = API::Node::ofType("mongoose", "Model")
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides signatures for the Model methods.
|
||||
*/
|
||||
module MethodSignatures {
|
||||
/**
|
||||
* Holds if Model method `name` interprets parameter `n` as a query.
|
||||
*/
|
||||
predicate interpretsArgumentAsQuery(string name, int n) {
|
||||
// implement lots of the MongoDB collection interface
|
||||
MongoDB::CollectionMethodSignatures::interpretsArgumentAsQuery(name, n)
|
||||
or
|
||||
name = "find" + ["ById", "One"] + "AndUpdate" and n = 1
|
||||
or
|
||||
name in ["delete" + ["Many", "One"], "geoSearch", "remove", "replaceOne", "where"] and
|
||||
n = 0
|
||||
or
|
||||
name in [
|
||||
"find" + ["", "ById", "One"],
|
||||
"find" + ["ById", "One"] + "And" + ["Delete", "Remove", "Update"],
|
||||
"update" + ["", "Many", "One"]
|
||||
] and
|
||||
n = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if Model method `name` returns a Query.
|
||||
*/
|
||||
predicate returnsQuery(string name) {
|
||||
name =
|
||||
[
|
||||
"$where", "count", "findOne", "findOneAndDelete", "findOneAndRemove",
|
||||
"findOneAndReplace", "findOneAndUpdate", "geosearch", "remove", "replaceOne", "update",
|
||||
"updateMany", "countDocuments", "updateOne", "where", "deleteMany", "deleteOne", "find",
|
||||
"findById", "findByIdAndDelete", "findByIdAndRemove", "findByIdAndUpdate"
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if Document method `name` returns a query that results in
|
||||
* one or more documents, the documents are wrapped in an array
|
||||
* if `asArray` is true.
|
||||
*/
|
||||
predicate returnsDocumentQuery(string name, boolean asArray) {
|
||||
asArray = false and name = "findOne"
|
||||
or
|
||||
asArray = true and name = "find"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modeling the Mongoose Query class
|
||||
*/
|
||||
module Query {
|
||||
private class QueryFunction extends MongooseFunction {
|
||||
string methodName;
|
||||
|
||||
QueryFunction() { this = getAMongooseQuery().getMember(methodName) }
|
||||
|
||||
override API::Node getQueryReturn() {
|
||||
MethodSignatures::returnsQuery(methodName) and result = this.getReturn()
|
||||
}
|
||||
|
||||
override predicate returnsDocumentQuery(boolean asArray) {
|
||||
MethodSignatures::returnsDocumentQuery(methodName, asArray)
|
||||
}
|
||||
|
||||
override API::Node getQueryArgument() {
|
||||
exists(int n |
|
||||
MethodSignatures::interpretsArgumentAsQuery(methodName, n) and
|
||||
result = this.getParameter(n)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class NewQueryFunction extends MongooseFunction {
|
||||
NewQueryFunction() { this = getAMongooseInstance().getMember("Query") }
|
||||
|
||||
override API::Node getQueryReturn() { result = this.getInstance() }
|
||||
|
||||
override predicate returnsDocumentQuery(boolean asArray) { none() }
|
||||
|
||||
override API::Node getQueryArgument() { result = this.getParameter(2) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a data flow node referring to a Mongoose query object.
|
||||
*/
|
||||
API::Node getAMongooseQuery() {
|
||||
result = any(MongooseFunction f).getQueryReturn()
|
||||
or
|
||||
result = API::Node::ofType("mongoose", "Query")
|
||||
or
|
||||
result =
|
||||
getAMongooseQuery()
|
||||
.getMember(any(string name | MethodSignatures::returnsQuery(name)))
|
||||
.getReturn()
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides signatures for the Query methods.
|
||||
*/
|
||||
module MethodSignatures {
|
||||
/**
|
||||
* Holds if Query method `name` interprets parameter `n` as a query.
|
||||
*/
|
||||
predicate interpretsArgumentAsQuery(string name, int n) {
|
||||
n = 0 and
|
||||
name =
|
||||
[
|
||||
"and", "count", "findOneAndReplace", "findOneAndUpdate", "merge", "nor", "or", "remove",
|
||||
"replaceOne", "setQuery", "setUpdate", "update", "countDocuments", "updateMany",
|
||||
"updateOne", "where", "deleteMany", "deleteOne", "elemMatch", "find", "findOne",
|
||||
"findOneAndDelete", "findOneAndRemove"
|
||||
]
|
||||
or
|
||||
n = 1 and
|
||||
name = ["distinct", "findOneAndUpdate", "update", "updateMany", "updateOne"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if Query method `name` returns a Query.
|
||||
*/
|
||||
predicate returnsQuery(string name) {
|
||||
name =
|
||||
[
|
||||
"$where", "J", "comment", "count", "countDocuments", "distinct", "elemMatch", "equals",
|
||||
"error", "estimatedDocumentCount", "exists", "explain", "all", "find", "findById",
|
||||
"findOne", "findOneAndRemove", "findOneAndUpdate", "geometry", "get", "gt", "gte",
|
||||
"hint", "and", "in", "intersects", "lean", "limit", "lt", "lte", "map", "map",
|
||||
"maxDistance", "maxTimeMS", "batchsize", "maxscan", "mod", "ne", "near", "nearSphere",
|
||||
"nin", "or", "orFail", "polygon", "populate", "box", "read", "readConcern", "regexp",
|
||||
"remove", "select", "session", "set", "setOptions", "setQuery", "setUpdate", "center",
|
||||
"size", "skip", "slaveOk", "slice", "snapshot", "sort", "update", "w", "where",
|
||||
"within", "centerSphere", "wtimeout", "circle", "collation"
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if Query method `name` returns a query that results in
|
||||
* one or more documents, the documents are wrapped in an array
|
||||
* if `asArray` is true.
|
||||
*/
|
||||
predicate returnsDocumentQuery(string name, boolean asArray) {
|
||||
asArray = false and name = "findOne"
|
||||
or
|
||||
asArray = true and name = "find"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modeling the Mongoose Document class
|
||||
*/
|
||||
module Document {
|
||||
private class DocumentFunction extends MongooseFunction {
|
||||
string methodName;
|
||||
|
||||
DocumentFunction() { this = getAMongooseDocument().getMember(methodName) }
|
||||
|
||||
override API::Node getQueryReturn() {
|
||||
MethodSignatures::returnsQuery(methodName) and result = this.getReturn()
|
||||
}
|
||||
|
||||
override predicate returnsDocumentQuery(boolean asArray) {
|
||||
MethodSignatures::returnsDocumentQuery(methodName, asArray)
|
||||
}
|
||||
|
||||
override API::Node getQueryArgument() {
|
||||
exists(int n |
|
||||
MethodSignatures::interpretsArgumentAsQuery(methodName, n) and
|
||||
result = this.getParameter(n)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Mongoose Document that is retrieved from the backing database.
|
||||
*/
|
||||
class RetrievedDocument extends API::Node {
|
||||
RetrievedDocument() {
|
||||
exists(boolean asArray, API::Node param |
|
||||
exists(MongooseFunction func |
|
||||
func.returnsDocumentQuery(asArray) and
|
||||
param = func.getLastParameter().getParameter(1)
|
||||
)
|
||||
or
|
||||
exists(API::Node f |
|
||||
f = Query::getAMongooseQuery().getMember("then") and
|
||||
param = f.getParameter(0).getParameter(0)
|
||||
or
|
||||
f = Query::getAMongooseQuery().getMember("exec") and
|
||||
param = f.getParameter(0).getParameter(1)
|
||||
|
|
||||
exists(DataFlow::MethodCallNode pred |
|
||||
// limitation: look at the previous method call
|
||||
Query::MethodSignatures::returnsDocumentQuery(pred.getMethodName(), asArray) and
|
||||
pred.getAMethodCall() = f.getACall()
|
||||
)
|
||||
)
|
||||
|
|
||||
asArray = false and this = param
|
||||
or
|
||||
asArray = true and
|
||||
// limitation: look for direct accesses
|
||||
this = param.getUnknownMember()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a data flow node referring to a Mongoose Document object.
|
||||
*/
|
||||
private API::Node getAMongooseDocument() {
|
||||
result instanceof RetrievedDocument
|
||||
or
|
||||
result = API::Node::ofType("mongoose", "Document")
|
||||
or
|
||||
result =
|
||||
getAMongooseDocument()
|
||||
.getMember(any(string name | MethodSignatures::returnsDocument(name)))
|
||||
.getReturn()
|
||||
}
|
||||
|
||||
private module MethodSignatures {
|
||||
/**
|
||||
* Holds if Document method `name` returns a Query.
|
||||
*/
|
||||
predicate returnsQuery(string name) {
|
||||
// Documents are subtypes of Models
|
||||
Model::MethodSignatures::returnsQuery(name) or
|
||||
name = "replaceOne" or
|
||||
name = "update" or
|
||||
name = "updateOne"
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if Document method `name` interprets parameter `n` as a query.
|
||||
*/
|
||||
predicate interpretsArgumentAsQuery(string name, int n) {
|
||||
// Documents are subtypes of Models
|
||||
Model::MethodSignatures::interpretsArgumentAsQuery(name, n)
|
||||
or
|
||||
n = 0 and
|
||||
(
|
||||
name = "replaceOne" or
|
||||
name = "update" or
|
||||
name = "updateOne"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if Document method `name` returns a query that results in
|
||||
* one or more documents, the documents are wrapped in an array
|
||||
* if `asArray` is true.
|
||||
*/
|
||||
predicate returnsDocumentQuery(string name, boolean asArray) {
|
||||
// Documents are subtypes of Models
|
||||
Model::MethodSignatures::returnsDocumentQuery(name, asArray)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if Document method `name` returns a Document.
|
||||
*/
|
||||
predicate returnsDocument(string name) {
|
||||
name = ["depopulate", "init", "populate", "overwrite"]
|
||||
}
|
||||
}
|
||||
class Model extends MongoDB::Collection {
|
||||
Model() { this = getAMongooseInstance().getAMemberCall("model") }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -501,9 +155,7 @@ private module Mongoose {
|
||||
string kind;
|
||||
|
||||
Credentials() {
|
||||
exists(string prop |
|
||||
this = createConnection().getParameter(3).getMember(prop).getARhs().asExpr()
|
||||
|
|
||||
exists(string prop | this = createConnection().getOptionArgument(3, prop).asExpr() |
|
||||
prop = "user" and kind = "user name"
|
||||
or
|
||||
prop = "pass" and kind = "password"
|
||||
@@ -512,308 +164,4 @@ private module Mongoose {
|
||||
|
||||
override string getCredentialsKind() { result = kind }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is interpreted as a (part of a) MongoDB query.
|
||||
*/
|
||||
class MongoDBQueryPart extends NoSql::Query {
|
||||
MongooseFunction f;
|
||||
|
||||
MongoDBQueryPart() { this = f.getQueryArgument().getARhs().asExpr() }
|
||||
|
||||
override DataFlow::Node getACodeOperator() {
|
||||
result = getADollarWhereProperty(f.getQueryArgument())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An evaluation of a MongoDB query.
|
||||
*/
|
||||
class ShorthandQueryEvaluation extends DatabaseAccess, DataFlow::InvokeNode {
|
||||
MongooseFunction f;
|
||||
|
||||
ShorthandQueryEvaluation() {
|
||||
this = f.getACall() and
|
||||
// shorthand for execution: provide a callback
|
||||
exists(f.getQueryReturn()) and
|
||||
exists(this.getCallback(this.getNumArgument() - 1))
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
// NB: the complete information is not easily accessible for deeply chained calls
|
||||
f.getQueryArgument().getARhs() = result
|
||||
}
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
result = this.getCallback(this.getNumArgument() - 1).getParameter(1)
|
||||
}
|
||||
}
|
||||
|
||||
class ExplicitQueryEvaluation extends DatabaseAccess, DataFlow::CallNode {
|
||||
string member;
|
||||
|
||||
ExplicitQueryEvaluation() {
|
||||
// explicit execution using a Query method call
|
||||
member = ["exec", "then", "catch"] and
|
||||
Query::getAMongooseQuery().getMember(member).getACall() = this
|
||||
}
|
||||
|
||||
private int resultParamIndex() {
|
||||
member = "then" and result = 0
|
||||
or
|
||||
member = "exec" and result = 1
|
||||
}
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
result = this.getCallback(_).getParameter(this.resultParamIndex())
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
// NB: the complete information is not easily accessible for deeply chained calls
|
||||
none()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modeling the Minimongo library.
|
||||
*/
|
||||
private module Minimongo {
|
||||
/**
|
||||
* Provides signatures for the Collection methods.
|
||||
*/
|
||||
module CollectionMethodSignatures {
|
||||
/**
|
||||
* Holds if Collection method `name` interprets parameter `n` as a query.
|
||||
*/
|
||||
predicate interpretsArgumentAsQuery(string m, int queryArgIdx) {
|
||||
// implements most of the MongoDB interface
|
||||
MongoDB::CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx)
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to a Minimongo query method. */
|
||||
private class QueryCall extends DatabaseAccess, API::CallNode {
|
||||
int queryArgIdx;
|
||||
|
||||
QueryCall() {
|
||||
exists(string m |
|
||||
this =
|
||||
API::moduleImport("minimongo")
|
||||
.getAMember()
|
||||
.getReturn()
|
||||
.getAMember()
|
||||
.getMember(m)
|
||||
.getACall() and
|
||||
CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { result = this.getArgument(queryArgIdx) }
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
PromiseFlow::loadStep(this.getALocalUse(), result, Promises::valueProp())
|
||||
}
|
||||
|
||||
DataFlow::Node getACodeOperator() {
|
||||
result = getADollarWhereProperty(this.getParameter(queryArgIdx))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is interpreted as a Minimongo query.
|
||||
*/
|
||||
class Query extends NoSql::Query {
|
||||
QueryCall qc;
|
||||
|
||||
Query() { this = qc.getAQueryArgument().asExpr() }
|
||||
|
||||
override DataFlow::Node getACodeOperator() { result = qc.getACodeOperator() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modeling the MarsDB library.
|
||||
*/
|
||||
private module MarsDB {
|
||||
private class MarsDBAccess extends DatabaseAccess, DataFlow::CallNode {
|
||||
string method;
|
||||
|
||||
MarsDBAccess() {
|
||||
this =
|
||||
API::moduleImport("marsdb")
|
||||
.getMember("Collection")
|
||||
.getInstance()
|
||||
.getMember(method)
|
||||
.getACall()
|
||||
}
|
||||
|
||||
string getMethod() { result = method }
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
PromiseFlow::loadStep(this.getALocalUse(), result, Promises::valueProp())
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { none() }
|
||||
}
|
||||
|
||||
/** A call to a MarsDB query method. */
|
||||
private class QueryCall extends MarsDBAccess, API::CallNode {
|
||||
int queryArgIdx;
|
||||
|
||||
QueryCall() {
|
||||
exists(string m |
|
||||
this.getMethod() = m and
|
||||
// implements parts of the Minimongo interface
|
||||
Minimongo::CollectionMethodSignatures::interpretsArgumentAsQuery(m, queryArgIdx)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
PromiseFlow::loadStep(this.getALocalUse(), result, Promises::valueProp())
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { result = this.getArgument(queryArgIdx) }
|
||||
|
||||
DataFlow::Node getACodeOperator() {
|
||||
result = getADollarWhereProperty(this.getParameter(queryArgIdx))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is interpreted as a MarsDB query.
|
||||
*/
|
||||
class Query extends NoSql::Query {
|
||||
QueryCall qc;
|
||||
|
||||
Query() { this = qc.getAQueryArgument().asExpr() }
|
||||
|
||||
override DataFlow::Node getACodeOperator() { result = qc.getACodeOperator() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modeling the `Node Redis` library.
|
||||
*
|
||||
* Redis is an in-memory key-value store and not a database,
|
||||
* but `Node Redis` can be exploited similarly to a NoSQL database by giving a method an array as argument instead of a string.
|
||||
* As an example the below two invocations of `client.set` are equivalent:
|
||||
*
|
||||
* ```
|
||||
* const redis = require("redis");
|
||||
* const client = redis.createClient();
|
||||
* client.set("key", "value");
|
||||
* client.set(["key", "value"]);
|
||||
* ```
|
||||
*
|
||||
* ioredis is a very similar library. However, ioredis does not support array arguments in the same way, and is therefore not vulnerable to the same kind of type confusion.
|
||||
*/
|
||||
private module Redis {
|
||||
/**
|
||||
* Gets a `Node Redis` client.
|
||||
*/
|
||||
private API::Node client() {
|
||||
result = API::moduleImport("redis").getMember("createClient").getReturn()
|
||||
or
|
||||
result = API::moduleImport("redis").getMember("RedisClient").getInstance()
|
||||
or
|
||||
result = client().getMember("duplicate").getReturn()
|
||||
or
|
||||
result = client().getMember("duplicate").getLastParameter().getParameter(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a (possibly chained) reference to a batch operation object.
|
||||
* These have the same API as a redis client, except the calls are chained, and the sequence is terminated with a `.exec` call.
|
||||
*/
|
||||
private API::Node multi() {
|
||||
result = client().getMember(["multi", "batch"]).getReturn()
|
||||
or
|
||||
result = multi().getAMember().getReturn()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a `Node Redis` client instance. Either a client created using `createClient()`, or a batch operation object.
|
||||
*/
|
||||
private API::Node redis() { result = [client(), multi()] }
|
||||
|
||||
/**
|
||||
* Provides signatures for the query methods from Node Redis.
|
||||
*/
|
||||
module QuerySignatures {
|
||||
/**
|
||||
* Holds if `method` interprets parameter `argIndex` as a key, and a later parameter determines a value/field.
|
||||
* Thereby the method is vulnerable if parameter `argIndex` is unexpectedly an array instead of a string, as an attacker can control arguments to Redis that the attacker was not supposed to control.
|
||||
*
|
||||
* Only setters and similar methods are included.
|
||||
* For getter-like methods it is not generally possible to gain access "outside" of where you are supposed to have access,
|
||||
* it is at most possible to get a Redis call to return more results than expected (e.g. by adding more members to [`geohash`](https://redis.io/commands/geohash)).
|
||||
*/
|
||||
predicate argumentIsAmbiguousKey(string method, int argIndex) {
|
||||
method =
|
||||
[
|
||||
"set", "publish", "append", "bitfield", "decrby", "getset", "hincrby", "hincrbyfloat",
|
||||
"hset", "hsetnx", "incrby", "incrbyfloat", "linsert", "lpush", "lpushx", "lset", "ltrim",
|
||||
"rename", "renamenx", "rpushx", "setbit", "setex", "smove", "zincrby", "zinterstore",
|
||||
"hdel", "lpush", "pfadd", "rpush", "sadd", "sdiffstore", "srem"
|
||||
] and
|
||||
argIndex = 0
|
||||
or
|
||||
method = ["bitop", "hmset", "mset", "msetnx", "geoadd"] and
|
||||
argIndex in [0 .. any(DataFlow::InvokeNode invk).getNumArgument() - 1]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is interpreted as a key in a Node Redis call.
|
||||
*/
|
||||
class RedisKeyArgument extends NoSql::Query {
|
||||
RedisKeyArgument() {
|
||||
exists(string method, int argIndex |
|
||||
QuerySignatures::argumentIsAmbiguousKey(method, argIndex) and
|
||||
this = redis().getMember(method).getParameter(argIndex).getARhs().asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An access to a database through redis
|
||||
*/
|
||||
class RedisDatabaseAccess extends DatabaseAccess, DataFlow::CallNode {
|
||||
RedisDatabaseAccess() { this = redis().getMember(_).getACall() }
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
PromiseFlow::loadStep(this.getALocalUse(), result, Promises::valueProp())
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modeling the `ioredis` library.
|
||||
*
|
||||
* ```
|
||||
* import Redis from 'ioredis'
|
||||
* let client = new Redis(...)
|
||||
* ```
|
||||
*/
|
||||
private module IoRedis {
|
||||
/**
|
||||
* Gets an `ioredis` client.
|
||||
*/
|
||||
API::Node ioredis() { result = API::moduleImport("ioredis").getInstance() }
|
||||
|
||||
/**
|
||||
* An access to a database through ioredis
|
||||
*/
|
||||
class IoRedisDatabaseAccess extends DatabaseAccess, DataFlow::CallNode {
|
||||
IoRedisDatabaseAccess() { this = ioredis().getMember(_).getACall() }
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
PromiseFlow::loadStep(this.getALocalUse(), result, Promises::valueProp())
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,56 +493,11 @@ module NodeJSLib {
|
||||
*/
|
||||
module FS {
|
||||
/**
|
||||
* Gets a member `member` from module `fs` or its drop-in replacements `graceful-fs`, `fs-extra`, `original-fs`.
|
||||
* A member `member` from module `fs`.
|
||||
*/
|
||||
DataFlow::SourceNode moduleMember(string member) {
|
||||
result = fsModule(DataFlow::TypeTracker::end()).getAPropertyRead(member)
|
||||
}
|
||||
|
||||
private DataFlow::SourceNode fsModule(DataFlow::TypeTracker t) {
|
||||
exists(string moduleName |
|
||||
moduleName = ["mz/fs", "original-fs", "fs-extra", "graceful-fs", "fs"]
|
||||
|
|
||||
result = DataFlow::moduleImport(moduleName)
|
||||
or
|
||||
// extra support for flexible names
|
||||
result.asExpr().(Require).getArgument(0).mayHaveStringValue(moduleName)
|
||||
) and
|
||||
t.start()
|
||||
or
|
||||
t.start() and
|
||||
result = DataFlow::moduleMember("fs", "promises")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2, DataFlow::SourceNode pred | pred = fsModule(t2) |
|
||||
result = pred.track(t2, t)
|
||||
or
|
||||
t.continue() = t2 and
|
||||
exists(Promisify::PromisifyAllCall promisifyAllCall |
|
||||
result = promisifyAllCall and
|
||||
pred.flowsTo(promisifyAllCall.getArgument(0))
|
||||
)
|
||||
or
|
||||
// const fs = require('fs');
|
||||
// let fs_copy = methods.reduce((obj, method) => {
|
||||
// obj[method] = fs[method];
|
||||
// return obj;
|
||||
// }, {});
|
||||
t.continue() = t2 and
|
||||
exists(
|
||||
DataFlow::MethodCallNode call, DataFlow::ParameterNode obj, DataFlow::SourceNode method
|
||||
|
|
||||
call.getMethodName() = "reduce" and
|
||||
result = call and
|
||||
obj = call.getABoundCallbackParameter(0, 0) and
|
||||
obj.flowsTo(any(DataFlow::FunctionNode f).getAReturn()) and
|
||||
exists(DataFlow::PropWrite write, DataFlow::PropRead read |
|
||||
write = obj.getAPropertyWrite() and
|
||||
method.flowsToExpr(write.getPropertyNameExpr()) and
|
||||
method.flowsToExpr(read.getPropertyNameExpr()) and
|
||||
read.getBase().getALocalSource() = fsModule(t2) and
|
||||
write.getRhs() = maybePromisified(read)
|
||||
)
|
||||
)
|
||||
exists(string moduleName | moduleName = ["fs"] |
|
||||
result = DataFlow::moduleMember(moduleName, member)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -553,7 +508,7 @@ module NodeJSLib {
|
||||
private class NodeJSFileSystemAccess extends FileSystemAccess, DataFlow::CallNode {
|
||||
string methodName;
|
||||
|
||||
NodeJSFileSystemAccess() { this = maybePromisified(FS::moduleMember(methodName)).getACall() }
|
||||
NodeJSFileSystemAccess() { this = FS::moduleMember(methodName).getACall() }
|
||||
|
||||
/**
|
||||
* Gets the name of the called method.
|
||||
|
||||
@@ -33,54 +33,38 @@ module SQL {
|
||||
* Provides classes modeling the (API compatible) `mysql` and `mysql2` packages.
|
||||
*/
|
||||
private module MySql {
|
||||
private string moduleName() { result = ["mysql", "mysql2", "mysql2/promise"] }
|
||||
private DataFlow::SourceNode mysql() { result = DataFlow::moduleImport(["mysql", "mysql2"]) }
|
||||
|
||||
/** Gets the package name `mysql` or `mysql2`. */
|
||||
API::Node mysql() { result = API::moduleImport(moduleName()) }
|
||||
private DataFlow::CallNode createPool() { result = mysql().getAMemberCall("createPool") }
|
||||
|
||||
/** Gets a reference to `mysql.createConnection`. */
|
||||
API::Node createConnection() {
|
||||
result = mysql().getMember(["createConnection", "createConnectionPromise"])
|
||||
/** Gets a reference to a MySQL pool. */
|
||||
private DataFlow::SourceNode pool(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = createPool()
|
||||
}
|
||||
|
||||
/** Gets a reference to `mysql.createPool`. */
|
||||
API::Node createPool() { result = mysql().getMember(["createPool", "createPoolCluster"]) }
|
||||
/** Gets a reference to a MySQL pool. */
|
||||
private DataFlow::SourceNode pool() { result = pool(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** Gets a node that contains a MySQL pool created using `mysql.createPool()`. */
|
||||
API::Node pool() {
|
||||
result = createPool().getReturn()
|
||||
or
|
||||
result = pool().getMember("on").getReturn()
|
||||
or
|
||||
result = API::Node::ofType(moduleName(), ["Pool", "PoolCluster"])
|
||||
}
|
||||
/** Gets a call to `mysql.createConnection`. */
|
||||
DataFlow::CallNode createConnection() { result = mysql().getAMemberCall("createConnection") }
|
||||
|
||||
/** Gets a data flow node that contains a freshly created MySQL connection instance. */
|
||||
API::Node connection() {
|
||||
result = createConnection().getReturn()
|
||||
or
|
||||
result = createConnection().getReturn().getPromised()
|
||||
or
|
||||
result = pool().getMember("getConnection").getParameter(0).getParameter(1)
|
||||
or
|
||||
result = pool().getMember("getConnection").getPromised()
|
||||
or
|
||||
exists(API::CallNode call |
|
||||
call = pool().getMember("on").getACall() and
|
||||
call.getArgument(0).getStringValue() = ["connection", "acquire", "release"] and
|
||||
result = call.getParameter(1).getParameter(0)
|
||||
/** Gets a reference to a MySQL connection instance. */
|
||||
private DataFlow::SourceNode connection(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
(
|
||||
result = createConnection()
|
||||
or
|
||||
result = pool().getAMethodCall("getConnection").getABoundCallbackParameter(0, 1)
|
||||
)
|
||||
or
|
||||
result = API::Node::ofType(moduleName(), ["Connection", "PoolConnection"])
|
||||
}
|
||||
|
||||
/** Gets a reference to a MySQL connection instance. */
|
||||
DataFlow::SourceNode connection() { result = connection(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** A call to the MySql `query` method. */
|
||||
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
|
||||
QueryCall() {
|
||||
exists(API::Node recv | recv = pool() or recv = connection() |
|
||||
this = recv.getMember(["query", "execute"]).getACall()
|
||||
)
|
||||
}
|
||||
QueryCall() { this = [pool(), connection()].getAMethodCall("query") }
|
||||
|
||||
override DataFlow::Node getAResult() { result = this.getCallback(_).getParameter(1) }
|
||||
|
||||
@@ -97,7 +81,7 @@ private module MySql {
|
||||
/** A call to the `escape` or `escapeId` method that performs SQL sanitization. */
|
||||
class EscapingSanitizer extends SQL::SqlSanitizer, MethodCallExpr {
|
||||
EscapingSanitizer() {
|
||||
this = [mysql(), pool(), connection()].getMember(["escape", "escapeId"]).getACall().asExpr() and
|
||||
this = [mysql(), pool(), connection()].getAMethodCall(["escape", "escapeId"]).asExpr() and
|
||||
input = this.getArgument(0) and
|
||||
output = this
|
||||
}
|
||||
@@ -108,9 +92,8 @@ private module MySql {
|
||||
string kind;
|
||||
|
||||
Credentials() {
|
||||
exists(API::Node callee, string prop |
|
||||
callee in [createConnection(), createPool()] and
|
||||
this = callee.getParameter(0).getMember(prop).getARhs().asExpr() and
|
||||
exists(string prop |
|
||||
this = [createConnection(), createPool()].getOptionArgument(0, prop).asExpr() and
|
||||
(
|
||||
prop = "user" and kind = "user name"
|
||||
or
|
||||
@@ -127,61 +110,23 @@ private module MySql {
|
||||
* Provides classes modeling the PostgreSQL packages, such as `pg` and `pg-promise`.
|
||||
*/
|
||||
private module Postgres {
|
||||
API::Node pg() {
|
||||
result = API::moduleImport("pg")
|
||||
or
|
||||
result = pgpMain().getMember("pg")
|
||||
}
|
||||
|
||||
/** Gets a reference to the `Client` constructor in the `pg` package, for example `require('pg').Client`. */
|
||||
API::Node newClient() { result = pg().getMember("Client") }
|
||||
|
||||
/** Gets a freshly created Postgres client instance. */
|
||||
API::Node client() {
|
||||
result = newClient().getInstance()
|
||||
or
|
||||
// pool.connect(function(err, client) { ... })
|
||||
result = pool().getMember("connect").getParameter(0).getParameter(1)
|
||||
or
|
||||
// await pool.connect()
|
||||
result = pool().getMember("connect").getReturn().getPromised()
|
||||
or
|
||||
result = pgpConnection().getMember("client")
|
||||
or
|
||||
exists(API::CallNode call |
|
||||
call = pool().getMember("on").getACall() and
|
||||
call.getArgument(0).getStringValue() = ["connect", "acquire"] and
|
||||
result = call.getParameter(1).getParameter(0)
|
||||
)
|
||||
or
|
||||
result = client().getMember("on").getReturn()
|
||||
or
|
||||
result = API::Node::ofType("pg", ["Client", "PoolClient"])
|
||||
}
|
||||
|
||||
/** Gets a constructor that when invoked constructs a new connection pool. */
|
||||
API::Node newPool() {
|
||||
/** Gets an expression that constructs a new connection pool. */
|
||||
DataFlow::InvokeNode newPool() {
|
||||
// new require('pg').Pool()
|
||||
result = pg().getMember("Pool")
|
||||
result = DataFlow::moduleImport("pg").getAConstructorInvocation("Pool")
|
||||
or
|
||||
// new require('pg-pool')
|
||||
result = API::moduleImport("pg-pool")
|
||||
result = DataFlow::moduleImport("pg-pool").getAnInstantiation()
|
||||
}
|
||||
|
||||
/** Gets an API node that refers to a connection pool. */
|
||||
API::Node pool() {
|
||||
result = newPool().getInstance()
|
||||
or
|
||||
result = pgpDatabase().getMember("$pool")
|
||||
or
|
||||
result = pool().getMember("on").getReturn()
|
||||
or
|
||||
result = API::Node::ofType("pg", "Pool")
|
||||
/** Gets a creation of a Postgres client. */
|
||||
DataFlow::InvokeNode newClient() {
|
||||
result = DataFlow::moduleImport("pg").getAConstructorInvocation("Client")
|
||||
}
|
||||
|
||||
/** A call to the Postgres `query` method. */
|
||||
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
|
||||
QueryCall() { this = [client(), pool()].getMember("query").getACall() }
|
||||
QueryCall() { this = [newClient(), newPool()].getAMethodCall("query") }
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
this.getNumArgument() = 2 and
|
||||
@@ -210,11 +155,7 @@ private module Postgres {
|
||||
string kind;
|
||||
|
||||
Credentials() {
|
||||
exists(string prop |
|
||||
this = [newClient(), newPool()].getParameter(0).getMember(prop).getARhs().asExpr()
|
||||
or
|
||||
this = pgPromise().getParameter(0).getMember(prop).getARhs().asExpr()
|
||||
|
|
||||
exists(string prop | this = [newClient(), newPool()].getOptionArgument(0, prop).asExpr() |
|
||||
prop = "user" and kind = "user name"
|
||||
or
|
||||
prop = "password" and kind = prop
|
||||
@@ -359,35 +300,30 @@ private module Postgres {
|
||||
*/
|
||||
private module Sqlite {
|
||||
/** Gets a reference to the `sqlite3` module. */
|
||||
API::Node sqlite() {
|
||||
result = API::moduleImport("sqlite3")
|
||||
DataFlow::SourceNode sqlite() {
|
||||
result = DataFlow::moduleImport("sqlite3")
|
||||
or
|
||||
result = sqlite().getMember("verbose").getReturn()
|
||||
result = sqlite().getAMemberCall("verbose")
|
||||
}
|
||||
|
||||
/** Gets an expression that constructs or returns a Sqlite database instance. */
|
||||
API::Node database() {
|
||||
/** Gets an expression that constructs a Sqlite database instance. */
|
||||
DataFlow::SourceNode newDb() {
|
||||
// new require('sqlite3').Database()
|
||||
result = sqlite().getMember("Database").getInstance()
|
||||
or
|
||||
// chained call
|
||||
result = getAChainingQueryCall()
|
||||
or
|
||||
result = API::Node::ofType("sqlite3", "Database")
|
||||
result = sqlite().getAConstructorInvocation("Database")
|
||||
}
|
||||
|
||||
/** Gets a call to a query method on a Sqlite database instance that returns the same instance. */
|
||||
private API::Node getAChainingQueryCall() {
|
||||
result = database().getMember(["all", "each", "exec", "get", "run"]).getReturn()
|
||||
/** Gets a data flow node referring to a Sqlite database instance. */
|
||||
private DataFlow::SourceNode db(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = newDb()
|
||||
}
|
||||
|
||||
/** Gets a data flow node referring to a Sqlite database instance. */
|
||||
DataFlow::SourceNode db() { result = db(DataFlow::TypeTracker::end()) }
|
||||
|
||||
/** A call to a Sqlite query method. */
|
||||
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
|
||||
QueryCall() {
|
||||
this = getAChainingQueryCall().getAnImmediateUse()
|
||||
or
|
||||
this = database().getMember("prepare").getACall()
|
||||
}
|
||||
QueryCall() { this = db().getAMethodCall(["all", "each", "exec", "get", "prepare", "run"]) }
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
result = this.getCallback(1).getParameter(1) or
|
||||
@@ -402,203 +338,3 @@ private module Sqlite {
|
||||
QueryString() { this = any(QueryCall qc).getAQueryArgument().asExpr() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modeling the `mssql` package.
|
||||
*/
|
||||
private module MsSql {
|
||||
/** Gets a reference to the `mssql` module. */
|
||||
API::Node mssql() { result = API::moduleImport("mssql") }
|
||||
|
||||
/** Gets a node referring to an instance of the given class. */
|
||||
API::Node mssqlClass(string name) {
|
||||
result = mssql().getMember(name).getInstance()
|
||||
or
|
||||
result = API::Node::ofType("mssql", name)
|
||||
}
|
||||
|
||||
/** Gets an API node referring to a Request object. */
|
||||
API::Node request() {
|
||||
result = mssqlClass("Request")
|
||||
or
|
||||
result = request().getMember(["input", "replaceInput", "output", "replaceOutput"]).getReturn()
|
||||
or
|
||||
result = [transaction(), pool()].getMember("request").getReturn()
|
||||
}
|
||||
|
||||
/** Gets an API node referring to a Transaction object. */
|
||||
API::Node transaction() {
|
||||
result = mssqlClass("Transaction")
|
||||
or
|
||||
result = pool().getMember("transaction").getReturn()
|
||||
}
|
||||
|
||||
/** Gets a API node referring to a ConnectionPool object. */
|
||||
API::Node pool() { result = mssqlClass("ConnectionPool") }
|
||||
|
||||
/** A tagged template evaluated as a query. */
|
||||
private class QueryTemplateExpr extends DatabaseAccess, DataFlow::ValueNode, DataFlow::SourceNode {
|
||||
override TaggedTemplateExpr astNode;
|
||||
|
||||
QueryTemplateExpr() {
|
||||
mssql().getMember("query").getAUse() = DataFlow::valueNode(astNode.getTag())
|
||||
}
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
PromiseFlow::loadStep(this.getALocalUse(), result, Promises::valueProp())
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
result = DataFlow::valueNode(astNode.getTemplate().getAnElement())
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to a MsSql query method. */
|
||||
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
|
||||
QueryCall() { this = [mssql(), request()].getMember(["query", "batch"]).getACall() }
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
result = this.getCallback(1).getParameter(1)
|
||||
or
|
||||
PromiseFlow::loadStep(this.getALocalUse(), result, Promises::valueProp())
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/** An expression that is passed to a method that interprets it as SQL. */
|
||||
class QueryString extends SQL::SqlString {
|
||||
QueryString() {
|
||||
exists(DatabaseAccess dba | dba instanceof QueryTemplateExpr or dba instanceof QueryCall |
|
||||
this = dba.getAQueryArgument().asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** An element of a query template, which is automatically sanitized. */
|
||||
class QueryTemplateSanitizer extends SQL::SqlSanitizer {
|
||||
QueryTemplateSanitizer() {
|
||||
this = any(QueryTemplateExpr qte).getAQueryArgument().asExpr() and
|
||||
input = this and
|
||||
output = this
|
||||
}
|
||||
}
|
||||
|
||||
/** An expression that is passed as user name or password when creating a client or a pool. */
|
||||
class Credentials extends CredentialsExpr {
|
||||
string kind;
|
||||
|
||||
Credentials() {
|
||||
exists(API::Node callee, string prop |
|
||||
(
|
||||
callee = mssql().getMember("connect")
|
||||
or
|
||||
callee = mssql().getMember("ConnectionPool")
|
||||
) and
|
||||
this = callee.getParameter(0).getMember(prop).getARhs().asExpr() and
|
||||
(
|
||||
prop = "user" and kind = "user name"
|
||||
or
|
||||
prop = "password" and kind = prop
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override string getCredentialsKind() { result = kind }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modeling the `sequelize` package.
|
||||
*/
|
||||
private module Sequelize {
|
||||
class SequelizeModel extends ModelInput::TypeModelCsv {
|
||||
override predicate row(string row) {
|
||||
// package1;type1;package2;type2;path
|
||||
row =
|
||||
[
|
||||
"sequelize;;sequelize-typescript;;", //
|
||||
"sequelize;Sequelize;sequelize;default;", //
|
||||
"sequelize;Sequelize;sequelize;;Instance",
|
||||
"sequelize;Sequelize;sequelize;;Member[Sequelize].Instance",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
class SequelizeSink extends ModelInput::SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"sequelize;Sequelize;Member[query].Argument[0];sql-injection",
|
||||
"sequelize;Sequelize;Member[query].Argument[0].Member[query];sql-injection",
|
||||
"sequelize;;Member[literal,asIs].Argument[0];sql-injection",
|
||||
"sequelize;;Argument[1];credentials[user name]",
|
||||
"sequelize;;Argument[2];credentials[password]",
|
||||
"sequelize;;Argument[0..].Member[username];credentials[user name]",
|
||||
"sequelize;;Argument[0..].Member[password];credentials[password]"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
class SequelizeSource extends ModelInput::SourceModelCsv {
|
||||
override predicate row(string row) {
|
||||
row = "sequelize;Sequelize;Member[query].ReturnValue.Awaited;database-access-result"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private module SpannerCsv {
|
||||
class SpannerTypes extends ModelInput::TypeModelCsv {
|
||||
override predicate row(string row) {
|
||||
// package1; type1; package2; type2; path
|
||||
row =
|
||||
[
|
||||
"@google-cloud/spanner;;@google-cloud/spanner;;Member[Spanner]",
|
||||
"@google-cloud/spanner;Database;@google-cloud/spanner;;ReturnValue.Member[instance].ReturnValue.Member[database].ReturnValue",
|
||||
"@google-cloud/spanner;v1.SpannerClient;@google-cloud/spanner;;Member[v1].Member[SpannerClient].Instance",
|
||||
"@google-cloud/spanner;Transaction;@google-cloud/spanner;Database;Member[runTransaction,runTransactionAsync,getTransaction].Argument[0..1].Parameter[1]",
|
||||
"@google-cloud/spanner;Transaction;@google-cloud/spanner;Database;Member[getTransaction].ReturnValue.Awaited",
|
||||
"@google-cloud/spanner;Snapshot;@google-cloud/spanner;Database;Member[getSnapshot].Argument[0..1].Parameter[1]",
|
||||
"@google-cloud/spanner;Snapshot;@google-cloud/spanner;Database;Member[getSnapshot].ReturnValue.Awaited",
|
||||
"@google-cloud/spanner;BatchTransaction;@google-cloud/spanner;Database;Member[batchTransaction].ReturnValue",
|
||||
"@google-cloud/spanner;BatchTransaction;@google-cloud/spanner;Database;Member[createBatchTransaction].ReturnValue.Awaited",
|
||||
"@google-cloud/spanner;~SqlExecutorDirect;@google-cloud/spanner;Database;Member[run,runPartitionedUpdate,runStream]",
|
||||
"@google-cloud/spanner;~SqlExecutorDirect;@google-cloud/spanner;Transaction;Member[run,runStream,runUpdate]",
|
||||
"@google-cloud/spanner;~SqlExecutorDirect;@google-cloud/spanner;BatchTransaction;Member[createQueryPartitions]",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
class SpannerSinks extends ModelInput::SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
// package; type; path; kind
|
||||
row =
|
||||
[
|
||||
"@google-cloud/spanner;~SqlExecutorDirect;Argument[0];sql-injection",
|
||||
"@google-cloud/spanner;~SqlExecutorDirect;Argument[0].Member[sql];sql-injection",
|
||||
"@google-cloud/spanner;Transaction;Member[batchUpdate].Argument[0];sql-injection",
|
||||
"@google-cloud/spanner;Transaction;Member[batchUpdate].Argument[0].ArrayElement.Member[sql];sql-injection",
|
||||
"@google-cloud/spanner;v1.SpannerClient;Member[executeSql,executeStreamingSql].Argument[0].Member[sql];sql-injection",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
class SpannerSources extends ModelInput::SourceModelCsv {
|
||||
string spannerClass() { result = ["v1.SpannerClient", "Database", "Transaction", "Snapshot",] }
|
||||
|
||||
string resultPath() {
|
||||
result =
|
||||
[
|
||||
"Member[executeSql].Argument[0..].Parameter[1]",
|
||||
"Member[executeSql].ReturnValue.Awaited.Member[0]", "Member[run].ReturnValue.Awaited",
|
||||
"Member[run].Argument[0..].Parameter[1]",
|
||||
]
|
||||
}
|
||||
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
"@google-cloud/spanner;" + this.spannerClass() + ";" + this.resultPath() +
|
||||
";database-access-result"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user