Merge branch 'master' into ir-this-parameter

Bring in new tests so their output can be fixed
This commit is contained in:
Robert Marsh
2020-05-28 08:32:10 -07:00
275 changed files with 3401 additions and 1063 deletions

View File

@@ -16,6 +16,7 @@ The following changes in version 1.25 affect C/C++ analysis in all applications.
## Changes to libraries
* The library `VCS.qll` and all queries that imported it have been removed.
* The data-flow library has been improved, which affects most security queries by potentially
adding more results. Flow through functions now takes nested field reads/writes into account.
For example, the library is able to track flow from `taint()` to `sink()` via the method
@@ -39,3 +40,5 @@ The following changes in version 1.25 affect C/C++ analysis in all applications.
}
};
```
* The security pack taint tracking library (`semmle.code.cpp.security.TaintTracking`) now considers that equality checks may block the flow of taint. This results in fewer false positive results from queries that use this library.

View File

@@ -3,8 +3,10 @@
## General improvements
* Support for the following frameworks and libraries has been improved:
- [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
- [bluebird](http://bluebirdjs.com/)
- [express](https://www.npmjs.com/package/express)
- [fastify](https://www.npmjs.com/package/fastify)
- [fstream](https://www.npmjs.com/package/fstream)
- [jGrowl](https://github.com/stanlemon/jGrowl)
- [jQuery](https://jquery.com/)
@@ -13,12 +15,11 @@
- [mssql](https://www.npmjs.com/package/mssql)
- [mysql](https://www.npmjs.com/package/mysql)
- [pg](https://www.npmjs.com/package/pg)
- [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
- [sequelize](https://www.npmjs.com/package/sequelize)
- [spanner](https://www.npmjs.com/package/spanner)
- [sqlite](https://www.npmjs.com/package/sqlite)
- [ssh2](https://www.npmjs.com/package/ssh2)
- [ssh2-streams](https://www.npmjs.com/package/ssh2-streams)
- [ssh2](https://www.npmjs.com/package/ssh2)
* TypeScript 3.9 is now supported.
@@ -35,41 +36,43 @@
| **Query** | **Expected impact** | **Change** |
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. |
| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. |
| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. |
| Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | Less results | This query now recognizes additional safe patterns of doing URL redirects. |
| Client-side cross-site scripting (`js/xss`) | Less results | This query now recognizes additional safe strings based on URLs. |
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional url scheme checks. |
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | More results | This query now recognizes additional utility functions as vulnerable to prototype polution. |
| Expression has no effect (`js/useless-expression`) | Less results | This query no longer flags an expression when that expression is the only content of the containing file. |
| Unknown directive (`js/unknown-directive`) | Less results | This query no longer flags directives generated by the Babel compiler. |
| Client-side cross-site scripting (`js/xss`) | Fewer results | This query no longer flags optionally sanitized values. |
| Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | Fewer results | This query now recognizes additional safe patterns of doing URL redirects. |
| Client-side cross-site scripting (`js/xss`) | Fewer results | This query now recognizes additional safe patterns of constructing HTML. |
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving NoSQL code operators are now recognized. |
| Expression has no effect (`js/useless-expression`) | Fewer results | This query no longer flags an expression when that expression is the only content of the containing file. |
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional url scheme checks. |
| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. |
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | More results | This query now recognizes additional utility functions as vulnerable to prototype polution. |
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | More results | This query now recognizes more coding patterns that are vulnerable to prototype pollution. |
| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. |
| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. |
| Unknown directive (`js/unknown-directive`) | Fewer results | This query no longer flags directives generated by the Babel compiler. |
| Unused property (`js/unused-property`) | Fewer results | This query no longer flags properties of objects that are operands of `yield` expressions. |
| Zip Slip (`js/zipslip`) | More results | This query now recognizes additional vulnerabilities. |
| Unused property (`js/unused-property`) | Less results | This query no longer flags properties of objects that are operands of `yield` expressions. |
The following low-precision queries are no longer run by default on LGTM (their results already were not displayed):
- `js/angular/dead-event-listener`
- `js/angular/unused-dependency`
- `js/conflicting-html-attribute`
- `js/useless-assignment-to-global`
- `js/too-many-parameters`
- `js/unused-property`
- `js/bitwise-sign-check`
- `js/comparison-of-identical-expressions`
- `js/misspelled-identifier`
- `js/jsdoc/malformed-param-tag`
- `js/jsdoc/unknown-parameter`
- `js/jsdoc/missing-parameter`
- `js/omitted-array-element`
- `js/conflicting-html-attribute`
- `js/ignored-setter-parameter`
- `js/jsdoc/malformed-param-tag`
- `js/jsdoc/missing-parameter`
- `js/jsdoc/unknown-parameter`
- `js/json-in-javascript-file`
- `js/misspelled-identifier`
- `js/nested-loops-with-same-variable`
- `js/node/cyclic-import`
- `js/node/unused-npm-dependency`
- `js/single-run-loop`
- `js/nested-loops-with-same-variable`
- `js/omitted-array-element`
- `js/return-outside-function`
- `js/single-run-loop`
- `js/too-many-parameters`
- `js/unused-property`
- `js/useless-assignment-to-global`
## Changes to libraries
@@ -79,3 +82,4 @@ The following low-precision queries are no longer run by default on LGTM (their
- `Parameter.flow()` now gets the correct data flow node for a parameter. Previously this had a result, but the node was disconnected from the data flow graph.
- `ParameterNode.asExpr()` and `.getAstNode()` now gets the parameter's AST node, whereas previously it had no result.
- `Expr.flow()` now has a more meaningful result for destructuring patterns. Previously this node was disconnected from the data flow graph. Now it represents the values being destructured by the pattern.
* The global data-flow and taint-tracking libraries now model indirect parameter accesses through the `arguments` object in some cases, which may lead to additional results from some of the security queries, particularly "Prototype pollution in utility function".

View File

@@ -6,29 +6,50 @@
import cpp
// True if function was ()-declared, but not (void)-declared or K&R-defined
/**
* Holds if `fde` has a parameter declaration that's clear on the minimum
* number of parameters. This is essentially true for everything except
* `()`-declarations.
*/
private predicate hasDefiniteNumberOfParameters(FunctionDeclarationEntry fde) {
fde.hasVoidParamList()
or
fde.getNumberOfParameters() > 0
or
fde.isDefinition()
}
/* Holds if function was ()-declared, but not (void)-declared or K&R-defined. */
private predicate hasZeroParamDecl(Function f) {
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
not fde.hasVoidParamList() and fde.getNumberOfParameters() = 0 and not fde.isDefinition()
not hasDefiniteNumberOfParameters(fde)
)
}
// True if this file (or header) was compiled as a C file
/* Holds if this file (or header) was compiled as a C file. */
private predicate isCompiledAsC(File f) {
f.compiledAsC()
or
exists(File src | isCompiledAsC(src) | src.getAnIncludedFile() = f)
}
/** Holds if `fc` is a call to `f` with too few arguments. */
predicate tooFewArguments(FunctionCall fc, Function f) {
f = fc.getTarget() and
not f.isVarargs() and
not f instanceof BuiltInFunction and
// This query should only have results on C (not C++) functions that have a
// `()` parameter list somewhere. If it has results on other functions, then
// it's probably because the extractor only saw a partial compilation.
hasZeroParamDecl(f) and
isCompiledAsC(f.getFile()) and
// There is an explicit declaration of the function whose parameter count is larger
// than the number of call arguments
exists(FunctionDeclarationEntry fde | fde = f.getADeclarationEntry() |
// Produce an alert when all declarations that are authoritative on the
// parameter count specify a parameter count larger than the number of call
// arguments.
forex(FunctionDeclarationEntry fde |
fde = f.getADeclarationEntry() and
hasDefiniteNumberOfParameters(fde)
|
fde.getNumberOfParameters() > fc.getNumberOfArguments()
)
}

View File

@@ -1,27 +0,0 @@
/**
* @name Churned lines per file
* @description Number of churned lines per file, across the revision
* history in the database.
* @kind treemap
* @id cpp/historical-churn
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg sum max
* @tags external-data
* @deprecated
*/
import cpp
import external.VCS
from File f, int n
where
n =
sum(Commit entry, int churn |
churn = entry.getRecentChurnForFile(f) and
not artificialChange(entry)
|
churn
) and
exists(f.getMetrics().getNumberOfLinesOfCode())
select f, n order by n desc

View File

@@ -1,27 +0,0 @@
/**
* @name Added lines per file
* @description Number of added lines per file, across the revision
* history in the database.
* @kind treemap
* @id cpp/historical-lines-added
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg sum max
* @tags external-data
* @deprecated
*/
import cpp
import external.VCS
from File f, int n
where
n =
sum(Commit entry, int churn |
churn = entry.getRecentAdditionsForFile(f) and
not artificialChange(entry)
|
churn
) and
exists(f.getMetrics().getNumberOfLinesOfCode())
select f, n order by n desc

View File

@@ -1,27 +0,0 @@
/**
* @name Deleted lines per file
* @description Number of deleted lines per file, across the revision
* history in the database.
* @kind treemap
* @id cpp/historical-lines-deleted
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg sum max
* @tags external-data
* @deprecated
*/
import cpp
import external.VCS
from File f, int n
where
n =
sum(Commit entry, int churn |
churn = entry.getRecentDeletionsForFile(f) and
not artificialChange(entry)
|
churn
) and
exists(f.getMetrics().getNumberOfLinesOfCode())
select f, n order by n desc

View File

@@ -1,18 +0,0 @@
/**
* @name Number of authors
* @description Number of distinct authors for each file.
* @kind treemap
* @id cpp/historical-number-of-authors
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg min max
* @tags external-data
* @deprecated
*/
import cpp
import external.VCS
from File f
where exists(f.getMetrics().getNumberOfLinesOfCode())
select f, count(Author author | author.getAnEditedFile() = f)

View File

@@ -1,19 +0,0 @@
/**
* @name Number of file-level changes
* @description The number of file-level changes made (by version
* control history).
* @kind treemap
* @id cpp/historical-number-of-changes
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg min max sum
* @tags external-data
* @deprecated
*/
import cpp
import external.VCS
from File f
where exists(f.getMetrics().getNumberOfLinesOfCode())
select f, count(Commit svn | f = svn.getAnAffectedFile() and not artificialChange(svn))

View File

@@ -1,21 +0,0 @@
/**
* @name Number of co-committed files
* @description The average number of other files that are touched
* whenever a file is affected by a commit.
* @kind treemap
* @id cpp/historical-number-of-co-commits
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg min max
* @tags external-data
* @deprecated
*/
import cpp
import external.VCS
int committedFiles(Commit commit) { result = count(commit.getAnAffectedFile()) }
from File f
where exists(f.getMetrics().getNumberOfLinesOfCode())
select f, avg(Commit commit | commit.getAnAffectedFile() = f | committedFiles(commit) - 1)

View File

@@ -1,37 +0,0 @@
/**
* @name Number of re-commits for each file
* @description A re-commit is taken to mean a commit to a file that
* was touched less than five days ago.
* @kind treemap
* @id cpp/historical-number-of-re-commits
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg min max
* @tags external-data
* @deprecated
*/
import cpp
import external.VCS
predicate inRange(Commit first, Commit second) {
first.getAnAffectedFile() = second.getAnAffectedFile() and
first != second and
exists(int n |
n = first.getDate().daysTo(second.getDate()) and
n >= 0 and
n < 5
)
}
int recommitsForFile(File f) {
result =
count(Commit recommit |
f = recommit.getAnAffectedFile() and
exists(Commit prev | inRange(prev, recommit))
)
}
from File f
where exists(f.getMetrics().getNumberOfLinesOfCode())
select f, recommitsForFile(f)

View File

@@ -1,27 +0,0 @@
/**
* @name Number of recent authors
* @description Number of distinct authors that have recently made
* changes.
* @kind treemap
* @id cpp/historical-number-of-recent-authors
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg min max
* @tags external-data
* @deprecated
*/
import cpp
import external.VCS
from File f
where exists(f.getMetrics().getNumberOfLinesOfCode())
select f,
count(Author author |
exists(Commit e |
e = author.getACommit() and
f = e.getAnAffectedFile() and
e.daysToNow() <= 180 and
not artificialChange(e)
)
)

View File

@@ -1,24 +0,0 @@
/**
* @name Recently changed files
* @description Number of files recently edited.
* @kind treemap
* @id cpp/historical-number-of-recent-changed-files
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg min max sum
* @tags external-data
* @deprecated
*/
import cpp
import external.VCS
from File f
where
exists(Commit e |
e.getAnAffectedFile() = f and
e.daysToNow() <= 180 and
not artificialChange(e)
) and
exists(f.getMetrics().getNumberOfLinesOfCode())
select f, 1

View File

@@ -1,25 +0,0 @@
/**
* @name Recent changes
* @description Number of recent commits to this file.
* @kind treemap
* @id cpp/historical-number-of-recent-changes
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg min max sum
* @tags external-data
* @deprecated
*/
import cpp
import external.VCS
from File f, int n
where
n =
count(Commit e |
e.getAnAffectedFile() = f and
e.daysToNow() <= 180 and
not artificialChange(e)
) and
exists(f.getMetrics().getNumberOfLinesOfCode())
select f, n order by n desc

View File

@@ -1 +1,7 @@
/**
* DEPRECATED: use `import cpp` instead of `import default`.
*
* Provides classes and predicates for working with C/C++ code.
*/
import cpp

View File

@@ -1,3 +1,5 @@
/** Provides classes for detecting duplicate or similar code. */
import cpp
private string relativePath(File file) { result = file.getRelativePath().replaceAll("\\", "/") }
@@ -8,9 +10,12 @@ private predicate tokenLocation(string path, int sl, int sc, int ec, int el, Cop
tokens(copy, index, sl, sc, ec, el)
}
/** A token block used for detection of duplicate and similar code. */
class Copy extends @duplication_or_similarity {
/** Gets the index of the last token in this block. */
private int lastToken() { result = max(int i | tokens(this, i, _, _, _, _) | i) }
/** Gets the index of the token in this block starting at the location `loc`, if any. */
int tokenStartingAt(Location loc) {
exists(string filepath, int startline, int startcol |
loc.hasLocationInfo(filepath, startline, startcol, _, _) and
@@ -18,6 +23,7 @@ class Copy extends @duplication_or_similarity {
)
}
/** Gets the index of the token in this block ending at the location `loc`, if any. */
int tokenEndingAt(Location loc) {
exists(string filepath, int endline, int endcol |
loc.hasLocationInfo(filepath, _, _, endline, endcol) and
@@ -25,24 +31,38 @@ class Copy extends @duplication_or_similarity {
)
}
/** Gets the line on which the first token in this block starts. */
int sourceStartLine() { tokens(this, 0, result, _, _, _) }
/** Gets the column on which the first token in this block starts. */
int sourceStartColumn() { tokens(this, 0, _, result, _, _) }
/** Gets the line on which the last token in this block ends. */
int sourceEndLine() { tokens(this, lastToken(), _, _, result, _) }
/** Gets the column on which the last token in this block ends. */
int sourceEndColumn() { tokens(this, lastToken(), _, _, _, result) }
/** Gets the number of lines containing at least (part of) one token in this block. */
int sourceLines() { result = this.sourceEndLine() + 1 - this.sourceStartLine() }
/** Gets an opaque identifier for the equivalence class of this block. */
int getEquivalenceClass() { duplicateCode(this, _, result) or similarCode(this, _, result) }
/** Gets the source file in which this block appears. */
File sourceFile() {
exists(string name | duplicateCode(this, name, _) or similarCode(this, name, _) |
name.replaceAll("\\", "/") = relativePath(result)
)
}
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
@@ -53,25 +73,30 @@ class Copy extends @duplication_or_similarity {
endcolumn = sourceEndColumn()
}
/** Gets a textual representation of this element. */
string toString() { none() }
}
/** A block of duplicated code. */
class DuplicateBlock extends Copy, @duplication {
override string toString() { result = "Duplicate code: " + sourceLines() + " duplicated lines." }
}
/** A block of similar code. */
class SimilarBlock extends Copy, @similarity {
override string toString() {
result = "Similar code: " + sourceLines() + " almost duplicated lines."
}
}
/** Gets a function with a body and a location. */
FunctionDeclarationEntry sourceMethod() {
result.isDefinition() and
exists(result.getLocation()) and
numlines(unresolveElement(result.getFunction()), _, _, _)
}
/** Gets the number of member functions in `c` with a body and a location. */
int numberOfSourceMethods(Class c) {
result =
count(FunctionDeclarationEntry m |
@@ -108,6 +133,10 @@ private predicate duplicateStatement(
)
}
/**
* Holds if `m1` is a function with `total` lines, and `m2` is a function
* that has `duplicate` lines in common with `m1`.
*/
predicate duplicateStatements(
FunctionDeclarationEntry m1, FunctionDeclarationEntry m2, int duplicate, int total
) {
@@ -115,13 +144,16 @@ predicate duplicateStatements(
total = strictcount(statementInMethod(m1))
}
/**
* Find pairs of methods are identical
*/
/** Holds if `m` and other are identical functions. */
predicate duplicateMethod(FunctionDeclarationEntry m, FunctionDeclarationEntry other) {
exists(int total | duplicateStatements(m, other, total, total))
}
/**
* INTERNAL: do not use.
*
* Holds if `line` in `f` is similar to a line somewhere else.
*/
predicate similarLines(File f, int line) {
exists(SimilarBlock b | b.sourceFile() = f and line in [b.sourceStartLine() .. b.sourceEndLine()])
}
@@ -152,6 +184,7 @@ private predicate similarLinesCoveredFiles(File f, File otherFile) {
)
}
/** Holds if `coveredLines` lines of `f` are similar to lines in `otherFile`. */
predicate similarLinesCovered(File f, int coveredLines, File otherFile) {
exists(int numLines | numLines = f.getMetrics().getNumberOfLines() |
similarLinesCoveredFiles(f, otherFile) and
@@ -166,6 +199,11 @@ predicate similarLinesCovered(File f, int coveredLines, File otherFile) {
)
}
/**
* INTERNAL: do not use.
*
* Holds if `line` in `f` is duplicated by a line somewhere else.
*/
predicate duplicateLines(File f, int line) {
exists(DuplicateBlock b |
b.sourceFile() = f and line in [b.sourceStartLine() .. b.sourceEndLine()]
@@ -182,6 +220,7 @@ private predicate duplicateLinesPerEquivalenceClass(int equivClass, int lines, F
)
}
/** Holds if `coveredLines` lines of `f` are duplicates of lines in `otherFile`. */
predicate duplicateLinesCovered(File f, int coveredLines, File otherFile) {
exists(int numLines | numLines = f.getMetrics().getNumberOfLines() |
exists(int coveredApprox |
@@ -206,6 +245,7 @@ predicate duplicateLinesCovered(File f, int coveredLines, File otherFile) {
)
}
/** Holds if most of `f` (`percent`%) is similar to `other`. */
predicate similarFiles(File f, File other, int percent) {
exists(int covered, int total |
similarLinesCovered(f, covered, other) and
@@ -216,6 +256,7 @@ predicate similarFiles(File f, File other, int percent) {
not duplicateFiles(f, other, _)
}
/** Holds if most of `f` (`percent`%) is duplicated by `other`. */
predicate duplicateFiles(File f, File other, int percent) {
exists(int covered, int total |
duplicateLinesCovered(f, covered, other) and
@@ -225,6 +266,10 @@ predicate duplicateFiles(File f, File other, int percent) {
)
}
/**
* Holds if most member functions of `c` (`numDup` out of `total`) are
* duplicates of member functions in `other`.
*/
predicate mostlyDuplicateClassBase(Class c, Class other, int numDup, int total) {
numDup =
strictcount(FunctionDeclarationEntry m1 |
@@ -240,6 +285,11 @@ predicate mostlyDuplicateClassBase(Class c, Class other, int numDup, int total)
(numDup * 100) / total > 80
}
/**
* Holds if most member functions of `c` are duplicates of member functions in
* `other`. Provides the human-readable `message` to describe the amount of
* duplication.
*/
predicate mostlyDuplicateClass(Class c, Class other, string message) {
exists(int numDup, int total |
mostlyDuplicateClassBase(c, other, numDup, total) and
@@ -264,12 +314,21 @@ predicate mostlyDuplicateClass(Class c, Class other, string message) {
)
}
/** Holds if `f` and `other` are similar or duplicates. */
predicate fileLevelDuplication(File f, File other) {
similarFiles(f, other, _) or duplicateFiles(f, other, _)
}
/**
* Holds if most member functions of `c` are duplicates of member functions in
* `other`.
*/
predicate classLevelDuplication(Class c, Class other) { mostlyDuplicateClass(c, other, _) }
/**
* Holds if `line` in `f` should be allowed to be duplicated. This is the case
* for `#include` directives.
*/
predicate whitelistedLineForDuplication(File f, int line) {
exists(Include i | i.getFile() = f and i.getLocation().getStartLine() = line)
}

View File

@@ -1,31 +1,52 @@
/** Provides a class for working with defect query results stored in dashboard databases. */
import cpp
/**
* Holds if `id` in the opaque identifier of a result reported by query `queryPath`,
* such that `message` is the associated message and the location of the result spans
* column `startcolumn` of line `startline` to column `endcolumn` of line `endline`
* in file `filepath`.
*
* For more information, see [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
external predicate defectResults(
int id, string queryPath, string file, int startline, int startcol, int endline, int endcol,
string message
);
/**
* A defect query result stored in a dashboard database.
*/
class DefectResult extends int {
DefectResult() { defectResults(this, _, _, _, _, _, _, _) }
/** Gets the path of the query that reported the result. */
string getQueryPath() { defectResults(this, result, _, _, _, _, _, _) }
/** Gets the file in which this query result was reported. */
File getFile() {
exists(string path |
defectResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path
)
}
/** Gets the line on which the location of this query result starts. */
int getStartLine() { defectResults(this, _, _, result, _, _, _, _) }
/** Gets the column on which the location of this query result starts. */
int getStartColumn() { defectResults(this, _, _, _, result, _, _, _) }
/** Gets the line on which the location of this query result ends. */
int getEndLine() { defectResults(this, _, _, _, _, result, _, _) }
/** Gets the column on which the location of this query result ends. */
int getEndColumn() { defectResults(this, _, _, _, _, _, result, _) }
/** Gets the message associated with this query result. */
string getMessage() { defectResults(this, _, _, _, _, _, _, result) }
/** Gets the URL corresponding to the location of this query result. */
string getURL() {
result =
"file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" +

View File

@@ -1,26 +1,45 @@
/**
* Provides classes for working with external data.
*/
import cpp
/**
* An external data item.
*/
class ExternalData extends @externalDataElement {
/** Gets the path of the file this data was loaded from. */
string getDataPath() { externalData(this, result, _, _) }
/**
* Gets the path of the file this data was loaded from, with its
* extension replaced by `.ql`.
*/
string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") }
/** Gets the number of fields in this data item. */
int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) }
string getField(int index) { externalData(this, _, index, result) }
/** Gets the value of the `i`th field of this data item. */
string getField(int i) { externalData(this, _, i, result) }
int getFieldAsInt(int index) { result = getField(index).toInt() }
/** Gets the integer value of the `i`th field of this data item. */
int getFieldAsInt(int i) { result = getField(i).toInt() }
float getFieldAsFloat(int index) { result = getField(index).toFloat() }
/** Gets the floating-point value of the `i`th field of this data item. */
float getFieldAsFloat(int i) { result = getField(i).toFloat() }
date getFieldAsDate(int index) { result = getField(index).toDate() }
/** Gets the value of the `i`th field of this data item, interpreted as a date. */
date getFieldAsDate(int i) { result = getField(i).toDate() }
/** Gets a textual representation of this data item. */
string toString() { result = getQueryPath() + ": " + buildTupleString(0) }
private string buildTupleString(int start) {
start = getNumFields() - 1 and result = getField(start)
/** Gets a textual representation of this data item, starting with the `n`th field. */
private string buildTupleString(int n) {
n = getNumFields() - 1 and result = getField(n)
or
start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start + 1)
n < getNumFields() - 1 and result = getField(n) + "," + buildTupleString(n + 1)
}
}
@@ -33,7 +52,9 @@ class DefectExternalData extends ExternalData {
this.getNumFields() = 2
}
/** Gets the URL associated with this data item. */
string getURL() { result = getField(0) }
/** Gets the message associated with this data item. */
string getMessage() { result = getField(1) }
}

View File

@@ -1,31 +1,58 @@
/** Provides a class for working with metric query results stored in dashboard databases. */
import cpp
/**
* Holds if `id` in the opaque identifier of a result reported by query `queryPath`,
* such that `value` is the reported metric value and the location of the result spans
* column `startcolumn` of line `startline` to column `endcolumn` of line `endline`
* in file `filepath`.
*
* For more information, see [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
external predicate metricResults(
int id, string queryPath, string file, int startline, int startcol, int endline, int endcol,
float value
);
/**
* A metric query result stored in a dashboard database.
*/
class MetricResult extends int {
MetricResult() { metricResults(this, _, _, _, _, _, _, _) }
/** Gets the path of the query that reported the result. */
string getQueryPath() { metricResults(this, result, _, _, _, _, _, _) }
/** Gets the file in which this query result was reported. */
File getFile() {
exists(string path |
metricResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path
)
}
/** Gets the line on which the location of this query result starts. */
int getStartLine() { metricResults(this, _, _, result, _, _, _, _) }
/** Gets the column on which the location of this query result starts. */
int getStartColumn() { metricResults(this, _, _, _, result, _, _, _) }
/** Gets the line on which the location of this query result ends. */
int getEndLine() { metricResults(this, _, _, _, _, result, _, _) }
/** Gets the column on which the location of this query result ends. */
int getEndColumn() { metricResults(this, _, _, _, _, _, result, _) }
/**
* Holds if there is a `Location` entity whose location is the same as
* the location of this query result.
*/
predicate hasMatchingLocation() { exists(this.getMatchingLocation()) }
/**
* Gets the `Location` entity whose location is the same as the location
* of this query result.
*/
Location getMatchingLocation() {
result.getFile() = this.getFile() and
result.getStartLine() = this.getStartLine() and
@@ -34,8 +61,10 @@ class MetricResult extends int {
result.getEndColumn() = this.getEndColumn()
}
/** Gets the value associated with this query result. */
float getValue() { metricResults(this, _, _, _, _, _, _, result) }
/** Gets the URL corresponding to the location of this query result. */
string getURL() {
result =
"file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" +

View File

@@ -1,92 +0,0 @@
import cpp
class Commit extends @svnentry {
Commit() {
svnaffectedfiles(this, _, _) and
exists(date svnDate, date snapshotDate |
svnentries(this, _, _, svnDate, _) and
snapshotDate(snapshotDate) and
svnDate <= snapshotDate
)
}
string toString() { result = this.getRevisionName() }
string getRevisionName() { svnentries(this, result, _, _, _) }
string getAuthor() { svnentries(this, _, result, _, _) }
date getDate() { svnentries(this, _, _, result, _) }
int getChangeSize() { svnentries(this, _, _, _, result) }
string getMessage() { svnentrymsg(this, result) }
string getAnAffectedFilePath(string action) {
exists(File rawFile | svnaffectedfiles(this, unresolveElement(rawFile), action) |
result = rawFile.getAbsolutePath()
)
}
string getAnAffectedFilePath() { result = getAnAffectedFilePath(_) }
File getAnAffectedFile(string action) {
// Workaround for incorrect keys in SVN data
exists(File svnFile | svnFile.getAbsolutePath() = result.getAbsolutePath() |
svnaffectedfiles(this, unresolveElement(svnFile), action)
) and
exists(result.getMetrics().getNumberOfLinesOfCode())
}
File getAnAffectedFile() { exists(string action | result = this.getAnAffectedFile(action)) }
private predicate churnForFile(File f, int added, int deleted) {
// Workaround for incorrect keys in SVN data
exists(File svnFile | svnFile.getAbsolutePath() = f.getAbsolutePath() |
svnchurn(this, unresolveElement(svnFile), added, deleted)
) and
exists(f.getMetrics().getNumberOfLinesOfCode())
}
int getRecentChurnForFile(File f) {
exists(int added, int deleted | churnForFile(f, added, deleted) and result = added + deleted)
}
int getRecentAdditionsForFile(File f) { churnForFile(f, result, _) }
int getRecentDeletionsForFile(File f) { churnForFile(f, _, result) }
predicate isRecent() { recentCommit(this) }
int daysToNow() {
exists(date now | snapshotDate(now) | result = getDate().daysTo(now) and result >= 0)
}
}
class Author extends string {
Author() { exists(Commit e | this = e.getAuthor()) }
Commit getACommit() { result.getAuthor() = this }
File getAnEditedFile() { result = this.getACommit().getAnAffectedFile() }
}
predicate recentCommit(Commit e) {
exists(date snapshotDate, date commitDate, int days |
snapshotDate(snapshotDate) and
e.getDate() = commitDate and
days = commitDate.daysTo(snapshotDate) and
days >= 0 and
days <= 60
)
}
date firstChange(File f) {
result = min(Commit e, date toMin | f = e.getAnAffectedFile() and toMin = e.getDate() | toMin)
}
predicate firstCommit(Commit e) {
not exists(File f | f = e.getAnAffectedFile() | firstChange(f) < e.getDate())
}
predicate artificialChange(Commit e) { firstCommit(e) or e.getChangeSize() >= 50000 }

View File

@@ -1,20 +0,0 @@
/**
* @name Defect from SVN
* @description A test case for creating a defect from SVN data.
* @kind problem
* @problem.severity warning
* @tags external-data
* @deprecated
*/
import cpp
import external.ExternalArtifact
import external.VCS
predicate numCommits(File f, int i) { i = count(Commit e | e.getAnAffectedFile() = f) }
predicate maxCommits(int i) { i = max(File f, int j | numCommits(f, j) | j) }
from File f, int i
where numCommits(f, i) and maxCommits(i)
select f, "This file has " + i + " commits."

View File

@@ -1,17 +0,0 @@
/**
* @name Metric from SVN
* @description Find number of commits for a file
* @treemap.warnOn lowValues
* @metricType file
* @tags external-data
* @deprecated
*/
import cpp
import external.VCS
predicate numCommits(File f, int i) { i = count(Commit e | e.getAnAffectedFile() = f) }
from File f, int i
where numCommits(f, i)
select f, i

View File

@@ -1,25 +0,0 @@
/**
* @name Filter: exclude results from files that have not recently been
* edited
* @description Use this filter to return results only if they are
* located in files that have been modified in the 60 days
* before the date of the snapshot.
* @kind problem
* @id cpp/recent-defects-filter
* @tags filter
* external-data
* @deprecated
*/
import cpp
import external.DefectFilter
import external.VCS
pragma[noopt]
private predicate recent(File file) {
exists(Commit e | file = e.getAnAffectedFile() | e.isRecent() and not artificialChange(e))
}
from DefectResult res
where recent(res.getFile())
select res, res.getMessage()

View File

@@ -1,25 +0,0 @@
/**
* @name Metric filter: exclude results from files that have not
* recently been edited
* @description Use this filter to return results only if they are
* located in files that have been modified in the 60 days
* before the snapshot.
* @kind treemap
* @id cpp/recent-defects-for-metric-filter
* @tags filter
* external-data
* @deprecated
*/
import cpp
import external.MetricFilter
import external.VCS
pragma[noopt]
private predicate recent(File file) {
exists(Commit e | file = e.getAnAffectedFile() | e.isRecent() and not artificialChange(e))
}
from MetricResult res
where recent(res.getFile())
select res, res.getValue()

View File

@@ -1 +1,7 @@
/**
* DEPRECATED: Objective C is no longer supported.
*
* Import `cpp` instead of `objc`.
*/
import cpp

View File

@@ -98,7 +98,12 @@ class Declaration extends Locatable, @declaration {
this.hasQualifiedName(namespaceQualifier, "", baseName)
}
override string toString() { result = this.getName() }
/**
* Gets a description of this `Declaration` for display purposes.
*/
string getDescription() { result = this.getName() }
final override string toString() { result = this.getDescription() }
/**
* Gets the name of this declaration.

View File

@@ -79,7 +79,10 @@ class Namespace extends NameQualifyingElement, @namespace {
/** Gets the metric namespace. */
MetricNamespace getMetrics() { result = this }
override string toString() { result = this.getQualifiedName() }
/** Gets a version of the `QualifiedName` that is more suitable for display purposes. */
string getFriendlyName() { result = this.getQualifiedName() }
final override string toString() { result = getFriendlyName() }
/** Gets a declaration of (part of) this namespace. */
NamespaceDeclarationEntry getADeclarationEntry() { result.getNamespace() = this }
@@ -104,7 +107,7 @@ class NamespaceDeclarationEntry extends Locatable, @namespace_decl {
namespace_decls(underlyingElement(this), unresolveElement(result), _, _)
}
override string toString() { result = this.getNamespace().toString() }
override string toString() { result = this.getNamespace().getFriendlyName() }
/**
* Gets the location of the token preceding the namespace declaration
@@ -150,7 +153,7 @@ class UsingDeclarationEntry extends UsingEntry {
*/
Declaration getDeclaration() { usings(underlyingElement(this), unresolveElement(result), _) }
override string toString() { result = "using " + this.getDeclaration().toString() }
override string toString() { result = "using " + this.getDeclaration().getDescription() }
}
/**
@@ -169,7 +172,7 @@ class UsingDirectiveEntry extends UsingEntry {
*/
Namespace getNamespace() { usings(underlyingElement(this), unresolveElement(result), _) }
override string toString() { result = "using namespace " + this.getNamespace().toString() }
override string toString() { result = "using namespace " + this.getNamespace().getFriendlyName() }
}
/**
@@ -204,7 +207,7 @@ class GlobalNamespace extends Namespace {
*/
deprecated string getFullName() { result = this.getName() }
override string toString() { result = "(global namespace)" }
override string getFriendlyName() { result = "(global namespace)" }
}
/**

View File

@@ -260,24 +260,33 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
*/
int getIndex() { param_decl_bind(underlyingElement(this), result, _) }
private string getAnonymousParameterDescription() {
not exists(getName()) and
exists(string idx |
idx =
((getIndex() + 1).toString() + "th")
.replaceAll("1th", "1st")
.replaceAll("2th", "2nd")
.replaceAll("3th", "3rd")
.replaceAll("11st", "11th")
.replaceAll("12nd", "12th")
.replaceAll("13rd", "13th") and
if exists(getCanonicalName())
then result = "declaration of " + getCanonicalName() + " as anonymous " + idx + " parameter"
else result = "declaration of " + idx + " parameter"
)
}
override string toString() {
if exists(getName())
then result = super.toString()
else
exists(string idx |
idx =
((getIndex() + 1).toString() + "th")
.replaceAll("1th", "1st")
.replaceAll("2th", "2nd")
.replaceAll("3th", "3rd")
.replaceAll("11st", "11th")
.replaceAll("12nd", "12th")
.replaceAll("13rd", "13th")
|
if exists(getCanonicalName())
then result = "declaration of " + getCanonicalName() + " as anonymous " + idx + " parameter"
else result = "declaration of " + idx + " parameter"
)
isDefinition() and
result = "definition of " + getName()
or
not isDefinition() and
if getName() = getCanonicalName()
then result = "declaration of " + getName()
else result = "declaration of " + getCanonicalName() + " as " + getName()
or
result = getAnonymousParameterDescription()
}
/**

View File

@@ -116,7 +116,7 @@ class XMLFile extends XMLParent, File {
XMLFile() { xmlEncoding(this, _) }
/** Gets a printable representation of this XML file. */
override string toString() { result = XMLParent.super.toString() }
override string toString() { result = getName() }
/** Gets the name of this XML file. */
override string getName() { result = File.super.getAbsolutePath() }
@@ -236,7 +236,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
/** Gets a printable representation of this XML element. */
override string toString() { result = XMLParent.super.toString() }
override string toString() { result = getName() }
}
/**

View File

@@ -1,3 +1,8 @@
/**
* Provides a library for reasoning about control flow at the granularity of basic blocks.
* This is usually much more efficient than reasoning directly at the level of `ControlFlowNode`s.
*/
import cpp
private import internal.PrimitiveBasicBlocks
private import internal.ConstantExprs
@@ -148,22 +153,37 @@ predicate bb_successor = bb_successor_cached/2;
class BasicBlock extends ControlFlowNodeBase {
BasicBlock() { basic_block_entry_node(this) }
/** Holds if this basic block contains `node`. */
predicate contains(ControlFlowNode node) { basic_block_member(node, this, _) }
/** Gets the `ControlFlowNode` at position `pos` in this basic block. */
ControlFlowNode getNode(int pos) { basic_block_member(result, this, pos) }
/** Gets a `ControlFlowNode` in this basic block. */
ControlFlowNode getANode() { basic_block_member(result, this, _) }
/** Gets a `BasicBlock` that is a direct successor of this basic block. */
BasicBlock getASuccessor() { bb_successor(this, result) }
/** Gets a `BasicBlock` that is a direct predecessor of this basic block. */
BasicBlock getAPredecessor() { bb_successor(result, this) }
/**
* Gets a `BasicBlock` such that the control-flow edge `(this, result)` may be taken
* when the outgoing edge of this basic block is an expression that is true.
*/
BasicBlock getATrueSuccessor() { result.getStart() = this.getEnd().getATrueSuccessor() }
/**
* Gets a `BasicBlock` such that the control-flow edge `(this, result)` may be taken
* when the outgoing edge of this basic block is an expression that is false.
*/
BasicBlock getAFalseSuccessor() { result.getStart() = this.getEnd().getAFalseSuccessor() }
/** Gets the final `ControlFlowNode` of this basic block. */
ControlFlowNode getEnd() { basic_block_member(result, this, bb_length(this) - 1) }
/** Gets the first `ControlFlowNode` of this basic block. */
ControlFlowNode getStart() { result = this }
/** Gets the number of `ControlFlowNode`s in this basic block. */
@@ -192,6 +212,7 @@ class BasicBlock extends ControlFlowNodeBase {
this.getEnd().getLocation().hasLocationInfo(endf, _, _, endl, endc)
}
/** Gets the function containing this basic block. */
Function getEnclosingFunction() { result = this.getStart().getControlFlowScope() }
/**

View File

@@ -1,3 +1,8 @@
/**
* Provides a library for reasoning about control flow at the granularity of
* individual nodes in the control-flow graph.
*/
import cpp
import BasicBlocks
private import semmle.code.cpp.controlflow.internal.ConstantExprs
@@ -29,8 +34,10 @@ private import semmle.code.cpp.controlflow.internal.CFG
* `Handler`. There are no edges from function calls to `Handler`s.
*/
class ControlFlowNode extends Locatable, ControlFlowNodeBase {
/** Gets a direct successor of this control-flow node, if any. */
ControlFlowNode getASuccessor() { successors_adapted(this, result) }
/** Gets a direct predecessor of this control-flow node, if any. */
ControlFlowNode getAPredecessor() { this = result.getASuccessor() }
/** Gets the function containing this control-flow node. */
@@ -71,6 +78,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
result = getASuccessor()
}
/** Gets the `BasicBlock` containing this control-flow node. */
BasicBlock getBasicBlock() { result.getANode() = this }
}
@@ -86,10 +94,18 @@ import ControlFlowGraphPublic
*/
class ControlFlowNodeBase extends ElementBase, @cfgnode { }
/**
* Holds when `n2` is a control-flow node such that the control-flow
* edge `(n1, n2)` may be taken when `n1` is an expression that is true.
*/
predicate truecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
qlCFGTrueSuccessor(n1, n2)
}
/**
* Holds when `n2` is a control-flow node such that the control-flow
* edge `(n1, n2)` may be taken when `n1` is an expression that is false.
*/
predicate falsecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
qlCFGFalseSuccessor(n1, n2)
}

View File

@@ -15,14 +15,25 @@ import Dereferenced
abstract class DataflowAnnotation extends string {
DataflowAnnotation() { this = "pointer-null" or this = "pointer-valid" }
/** Holds if this annotation is the default annotation. */
abstract predicate isDefault();
/** Holds if this annotation is generated when analyzing expression `e`. */
abstract predicate generatedOn(Expr e);
/**
* Holds if this annotation is generated for the variable `v` when
* the control-flow edge `(src, dest)` is taken.
*/
abstract predicate generatedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest);
/**
* Holds if this annotation is removed for the variable `v` when
* the control-flow edge `(src, dest)` is taken.
*/
abstract predicate killedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest);
/** Holds if expression `e` is given this annotation. */
predicate marks(Expr e) {
this.generatedOn(e) and reachable(e)
or
@@ -31,6 +42,7 @@ abstract class DataflowAnnotation extends string {
exists(LocalScopeVariable v | this.marks(v, e) and e = v.getAnAccess())
}
/** Holds if the variable `v` accessed in control-flow node `n` is given this annotation. */
predicate marks(LocalScopeVariable v, ControlFlowNode n) {
v.getAnAccess().getEnclosingFunction().getBlock() = n and
this.isDefault()
@@ -57,6 +69,10 @@ abstract class DataflowAnnotation extends string {
)
}
/**
* Holds if the variable `v` preserves this annotation when the control-flow
* edge `(src, dest)` is taken.
*/
predicate preservedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest) {
this.marks(v, src) and
src.getASuccessor() = dest and
@@ -64,6 +80,10 @@ abstract class DataflowAnnotation extends string {
not v.getAnAssignment() = src
}
/**
* Holds if the variable `v` is assigned this annotation when `src` is an assignment
* expression that assigns to `v` and the control-flow edge `(src, dest)` is taken.
*/
predicate assignedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest) {
this.marks(src.(AssignExpr).getRValue()) and
src = v.getAnAssignment() and

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -79,13 +79,6 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintBarrier(node)
}
/** DEPRECATED: override `isSanitizerIn` and `isSanitizerOut` instead. */
deprecated predicate isSanitizerEdge(DataFlow::Node node1, DataFlow::Node node2) { none() }
deprecated final override predicate isBarrierEdge(DataFlow::Node node1, DataFlow::Node node2) {
isSanitizerEdge(node1, node2)
}
/** Holds if data flow into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }

View File

@@ -79,13 +79,6 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintBarrier(node)
}
/** DEPRECATED: override `isSanitizerIn` and `isSanitizerOut` instead. */
deprecated predicate isSanitizerEdge(DataFlow::Node node1, DataFlow::Node node2) { none() }
deprecated final override predicate isBarrierEdge(DataFlow::Node node1, DataFlow::Node node2) {
isSanitizerEdge(node1, node2)
}
/** Holds if data flow into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }

View File

@@ -86,7 +86,7 @@ class Closure extends Class {
result.getName() = "operator()"
}
override string toString() { result = "decltype([...](...){...})" }
override string getDescription() { result = "decltype([...](...){...})" }
}
/**
@@ -99,7 +99,7 @@ class Closure extends Class {
* ```
*/
class LambdaCapture extends Locatable, @lambdacapture {
override string toString() { result = getField().toString() }
override string toString() { result = getField().getName() }
override string getCanonicalQLClass() { result = "LambdaCapture" }

View File

@@ -1,10 +1,12 @@
import cpp
import semmle.code.cpp.security.Security
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.DataFlow2
private import semmle.code.cpp.ir.dataflow.DataFlow3
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch
private import semmle.code.cpp.controlflow.IRGuards
private import semmle.code.cpp.models.interfaces.Taint
private import semmle.code.cpp.models.interfaces.DataFlow
@@ -170,11 +172,34 @@ private predicate hasUpperBoundsCheck(Variable var) {
)
}
private predicate nodeIsBarrierEqualityCandidate(
DataFlow::Node node, Operand access, Variable checkedVar
) {
readsVariable(node.asInstruction(), checkedVar) and
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
}
private predicate nodeIsBarrier(DataFlow::Node node) {
exists(Variable checkedVar |
readsVariable(node.asInstruction(), checkedVar) and
hasUpperBoundsCheck(checkedVar)
)
or
exists(Variable checkedVar, Operand access |
/*
* This node is guarded by a condition that forces the accessed variable
* to equal something else. For example:
* ```
* x = taintsource()
* if (x == 10) {
* taintsink(x); // not considered tainted
* }
* ```
*/
nodeIsBarrierEqualityCandidate(node, access, checkedVar) and
readsVariable(access.getDef(), checkedVar)
)
}
private predicate nodeIsBarrierIn(DataFlow::Node node) {

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -71,9 +71,7 @@ class Node extends TIRDataFlowNode {
* `x.set(taint())` is a partial definition of `x`, and `transfer(&x, taint())` is
* a partial definition of `&x`).
*/
Expr asPartialDefinition() {
result = this.(PartialDefinitionNode).getInstruction().getUnconvertedResultExpression()
}
Expr asPartialDefinition() { result = this.(PartialDefinitionNode).getDefinedExpr() }
/**
* DEPRECATED: See UninitializedNode.
@@ -247,14 +245,17 @@ abstract class PostUpdateNode extends InstructionNode {
* setY(&x); // a partial definition of the object `x`.
* ```
*/
abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { }
abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode {
abstract Expr getDefinedExpr();
}
private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
override ChiInstruction instr;
FieldAddressInstruction field;
ExplicitFieldStoreQualifierNode() {
not instr.isResultConflated() and
exists(StoreInstruction store, FieldInstruction field |
exists(StoreInstruction store |
instr.getPartial() = store and field = store.getDestinationAddress()
)
}
@@ -264,6 +265,10 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
// DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications
// this consistency failure has.
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
override Expr getDefinedExpr() {
result = field.getObjectAddress().getUnconvertedResultExpression()
}
}
/**
@@ -274,15 +279,18 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
*/
private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode {
override StoreInstruction instr;
FieldAddressInstruction field;
ExplicitSingleFieldStoreQualifierNode() {
exists(FieldAddressInstruction field |
field = instr.getDestinationAddress() and
not exists(ChiInstruction chi | chi.getPartial() = instr)
)
field = instr.getDestinationAddress() and
not exists(ChiInstruction chi | chi.getPartial() = instr)
}
override Node getPreUpdateNode() { none() }
override Expr getDefinedExpr() {
result = field.getObjectAddress().getUnconvertedResultExpression()
}
}
/**
@@ -454,9 +462,9 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
// for now.
iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom
or
// The next two rules allow flow from partial definitions in setters to succeeding loads in the caller.
// First, we add flow from write side-effects to non-conflated chi instructions through their
// partial operands. Consider the following example:
// Add flow from write side-effects to non-conflated chi instructions through their
// partial operands. From there, a `readStep` will find subsequent reads of that field.
// Consider the following example:
// ```
// void setX(Point* p, int new_x) {
// p->x = new_x;
@@ -466,14 +474,9 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
// ```
// Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to
// `setX`, which will be melded into `p` through a chi instruction.
iTo.getAnOperand().(ChiPartialOperand).getDef() = iFrom.(WriteSideEffectInstruction) and
not iTo.isResultConflated()
or
// Next, we add flow from non-conflated chi instructions to loads (even when they are not precise).
// This ensures that loads of `p->x` gets data flow from the `WriteSideEffectInstruction` above.
exists(ChiInstruction chi | iFrom = chi |
not chi.isResultConflated() and
iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = chi
exists(ChiInstruction chi | chi = iTo |
chi.getPartialOperand().getDef() = iFrom.(WriteSideEffectInstruction) and
not chi.isResultConflated()
)
or
// Flow from stores to structs with a single field to a load of that field.

View File

@@ -79,13 +79,6 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintBarrier(node)
}
/** DEPRECATED: override `isSanitizerIn` and `isSanitizerOut` instead. */
deprecated predicate isSanitizerEdge(DataFlow::Node node1, DataFlow::Node node2) { none() }
deprecated final override predicate isBarrierEdge(DataFlow::Node node1, DataFlow::Node node2) {
isSanitizerEdge(node1, node2)
}
/** Holds if data flow into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }

View File

@@ -79,13 +79,6 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintBarrier(node)
}
/** DEPRECATED: override `isSanitizerIn` and `isSanitizerOut` instead. */
deprecated predicate isSanitizerEdge(DataFlow::Node node1, DataFlow::Node node2) { none() }
deprecated final override predicate isBarrierEdge(DataFlow::Node node1, DataFlow::Node node2) {
isSanitizerEdge(node1, node2)
}
/** Holds if data flow into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }

View File

@@ -362,7 +362,7 @@ CppType getTypeForPRValueOrUnknown(Type type) {
/**
* Gets the `CppType` that represents a glvalue of type `type`.
*/
CppType getTypeForGLValue(Type type) { result.hasType(type, true) }
CppGLValueAddressType getTypeForGLValue(Type type) { result.hasType(type, true) }
/**
* Gets the `CppType` that represents a prvalue of type `int`.

View File

@@ -1,4 +1,4 @@
import default
import cpp
from Class c, string n
where n = count(Class x | x.getName() = c.getName()) + " distinct class(es) called " + c.getName()

View File

@@ -1,4 +1,4 @@
import default
import cpp
import semmle.code.cpp.models.implementations.Allocation
query predicate newExprs(

View File

@@ -1,4 +1,4 @@
import default
import cpp
string getValueCategoryString(Expr expr) {
if expr.isLValueCategory()

View File

@@ -115,5 +115,5 @@ void test_conflated_fields3() {
XY xy;
xy.x = 0;
taint_y(&xy);
sink(xy.x); // not tainted [FALSE POSITIVE]
sink(xy.x); // not tainted
}

View File

@@ -103,8 +103,6 @@
| defaulttainttracking.cpp:110:17:110:22 | call to getenv | defaulttainttracking.cpp:110:17:110:32 | (int)... |
| defaulttainttracking.cpp:110:17:110:22 | call to getenv | defaulttainttracking.cpp:110:17:110:32 | access to array |
| defaulttainttracking.cpp:110:17:110:22 | call to getenv | defaulttainttracking.cpp:111:12:111:18 | tainted |
| defaulttainttracking.cpp:110:17:110:22 | call to getenv | defaulttainttracking.cpp:118:11:118:11 | x |
| defaulttainttracking.cpp:110:17:110:22 | call to getenv | shared.h:6:15:6:23 | sinkparam |
| dispatch.cpp:28:29:28:34 | call to getenv | dispatch.cpp:28:24:28:27 | call to atoi |
| dispatch.cpp:28:29:28:34 | call to getenv | dispatch.cpp:28:29:28:34 | call to getenv |
| dispatch.cpp:28:29:28:34 | call to getenv | dispatch.cpp:28:29:28:45 | (const char *)... |

View File

@@ -21,8 +21,6 @@
| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:98:10:98:11 | p2 | IR only |
| defaulttainttracking.cpp:97:27:97:32 | call to getenv | shared.h:5:23:5:31 | sinkparam | IR only |
| defaulttainttracking.cpp:110:17:110:22 | call to getenv | defaulttainttracking.cpp:111:8:111:8 | y | AST only |
| defaulttainttracking.cpp:110:17:110:22 | call to getenv | defaulttainttracking.cpp:118:11:118:11 | x | IR only |
| defaulttainttracking.cpp:110:17:110:22 | call to getenv | shared.h:6:15:6:23 | sinkparam | IR only |
| globals.cpp:13:15:13:20 | call to getenv | globals.cpp:13:5:13:11 | global1 | AST only |
| globals.cpp:23:15:23:20 | call to getenv | globals.cpp:23:5:23:11 | global2 | AST only |
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:11:104:20 | (...) | IR only |

View File

@@ -0,0 +1,370 @@
| A.cpp:25:7:25:10 | this | AST only |
| A.cpp:25:13:25:13 | c | AST only |
| A.cpp:27:22:27:25 | this | AST only |
| A.cpp:27:28:27:28 | c | AST only |
| A.cpp:31:20:31:20 | c | AST only |
| A.cpp:40:5:40:6 | cc | AST only |
| A.cpp:41:5:41:6 | ct | AST only |
| A.cpp:42:10:42:12 | & ... | AST only |
| A.cpp:43:10:43:12 | & ... | AST only |
| A.cpp:48:20:48:20 | c | AST only |
| A.cpp:49:10:49:10 | b | AST only |
| A.cpp:49:13:49:13 | c | AST only |
| A.cpp:55:5:55:5 | b | AST only |
| A.cpp:56:10:56:10 | b | AST only |
| A.cpp:56:13:56:15 | call to get | AST only |
| A.cpp:57:28:57:30 | call to get | AST only |
| A.cpp:64:17:64:18 | b1 | AST only |
| A.cpp:65:10:65:11 | b1 | AST only |
| A.cpp:65:14:65:14 | c | AST only |
| A.cpp:66:10:66:11 | b2 | AST only |
| A.cpp:66:14:66:14 | c | AST only |
| A.cpp:73:21:73:22 | b1 | AST only |
| A.cpp:74:10:74:11 | b1 | AST only |
| A.cpp:74:14:74:14 | c | AST only |
| A.cpp:75:10:75:11 | b2 | AST only |
| A.cpp:75:14:75:14 | c | AST only |
| A.cpp:81:17:81:18 | b1 | AST only |
| A.cpp:81:21:81:21 | c | AST only |
| A.cpp:90:7:90:8 | b2 | AST only |
| A.cpp:90:15:90:15 | c | AST only |
| A.cpp:100:9:100:9 | a | AST only |
| A.cpp:101:8:101:9 | c1 | AST only |
| A.cpp:107:12:107:13 | c1 | AST only |
| A.cpp:107:16:107:16 | a | AST only |
| A.cpp:120:12:120:13 | c1 | AST only |
| A.cpp:120:16:120:16 | a | AST only |
| A.cpp:126:5:126:5 | b | AST only |
| A.cpp:131:8:131:8 | b | AST only |
| A.cpp:132:10:132:10 | b | AST only |
| A.cpp:132:13:132:13 | c | AST only |
| A.cpp:142:10:142:10 | c | AST only |
| A.cpp:143:7:143:10 | this | AST only |
| A.cpp:143:13:143:13 | b | AST only |
| A.cpp:151:18:151:18 | b | AST only |
| A.cpp:152:10:152:10 | d | AST only |
| A.cpp:152:13:152:13 | b | AST only |
| A.cpp:153:10:153:10 | d | AST only |
| A.cpp:153:13:153:13 | b | AST only |
| A.cpp:153:16:153:16 | c | AST only |
| A.cpp:154:10:154:10 | b | AST only |
| A.cpp:154:13:154:13 | c | AST only |
| A.cpp:160:29:160:29 | b | AST only |
| A.cpp:161:38:161:39 | l1 | AST only |
| A.cpp:162:38:162:39 | l2 | AST only |
| A.cpp:163:10:163:11 | l3 | AST only |
| A.cpp:163:14:163:17 | head | AST only |
| A.cpp:164:10:164:11 | l3 | AST only |
| A.cpp:164:14:164:17 | next | AST only |
| A.cpp:164:20:164:23 | head | AST only |
| A.cpp:165:10:165:11 | l3 | AST only |
| A.cpp:165:14:165:17 | next | AST only |
| A.cpp:165:20:165:23 | next | AST only |
| A.cpp:165:26:165:29 | head | AST only |
| A.cpp:166:10:166:11 | l3 | AST only |
| A.cpp:166:14:166:17 | next | AST only |
| A.cpp:166:20:166:23 | next | AST only |
| A.cpp:166:26:166:29 | next | AST only |
| A.cpp:166:32:166:35 | head | AST only |
| A.cpp:169:12:169:12 | l | AST only |
| A.cpp:169:15:169:18 | head | AST only |
| A.cpp:183:7:183:10 | head | AST only |
| A.cpp:183:7:183:10 | this | AST only |
| A.cpp:184:7:184:10 | this | AST only |
| A.cpp:184:13:184:16 | next | AST only |
| B.cpp:7:25:7:25 | e | AST only |
| B.cpp:8:25:8:26 | b1 | AST only |
| B.cpp:9:10:9:11 | b2 | AST only |
| B.cpp:9:14:9:17 | box1 | AST only |
| B.cpp:9:20:9:24 | elem1 | AST only |
| B.cpp:10:10:10:11 | b2 | AST only |
| B.cpp:10:14:10:17 | box1 | AST only |
| B.cpp:10:20:10:24 | elem2 | AST only |
| B.cpp:16:37:16:37 | e | AST only |
| B.cpp:17:25:17:26 | b1 | AST only |
| B.cpp:18:10:18:11 | b2 | AST only |
| B.cpp:18:14:18:17 | box1 | AST only |
| B.cpp:18:20:18:24 | elem1 | AST only |
| B.cpp:19:10:19:11 | b2 | AST only |
| B.cpp:19:14:19:17 | box1 | AST only |
| B.cpp:19:20:19:24 | elem2 | AST only |
| B.cpp:35:7:35:10 | this | AST only |
| B.cpp:35:13:35:17 | elem1 | AST only |
| B.cpp:36:7:36:10 | this | AST only |
| B.cpp:36:13:36:17 | elem2 | AST only |
| B.cpp:46:7:46:10 | this | AST only |
| B.cpp:46:13:46:16 | box1 | AST only |
| C.cpp:19:5:19:5 | c | AST only |
| C.cpp:24:5:24:8 | this | AST only |
| C.cpp:24:11:24:12 | s3 | AST only |
| D.cpp:9:21:9:24 | elem | AST only |
| D.cpp:9:21:9:24 | this | AST only |
| D.cpp:11:29:11:32 | elem | AST only |
| D.cpp:11:29:11:32 | this | AST only |
| D.cpp:16:21:16:23 | box | AST only |
| D.cpp:16:21:16:23 | this | AST only |
| D.cpp:18:29:18:31 | box | AST only |
| D.cpp:18:29:18:31 | this | AST only |
| D.cpp:22:10:22:11 | b2 | AST only |
| D.cpp:22:14:22:20 | call to getBox1 | AST only |
| D.cpp:22:25:22:31 | call to getElem | AST only |
| D.cpp:30:5:30:5 | b | AST only |
| D.cpp:30:8:30:10 | box | AST only |
| D.cpp:30:13:30:16 | elem | AST only |
| D.cpp:31:14:31:14 | b | AST only |
| D.cpp:37:5:37:5 | b | AST only |
| D.cpp:37:8:37:10 | box | AST only |
| D.cpp:37:21:37:21 | e | AST only |
| D.cpp:38:14:38:14 | b | AST only |
| D.cpp:44:5:44:5 | b | AST only |
| D.cpp:44:8:44:14 | call to getBox1 | AST only |
| D.cpp:44:19:44:22 | elem | AST only |
| D.cpp:45:14:45:14 | b | AST only |
| D.cpp:51:5:51:5 | b | AST only |
| D.cpp:51:8:51:14 | call to getBox1 | AST only |
| D.cpp:51:27:51:27 | e | AST only |
| D.cpp:52:14:52:14 | b | AST only |
| D.cpp:57:5:57:12 | boxfield | AST only |
| D.cpp:57:5:57:12 | this | AST only |
| D.cpp:58:5:58:12 | boxfield | AST only |
| D.cpp:58:5:58:12 | this | AST only |
| D.cpp:58:15:58:17 | box | AST only |
| D.cpp:58:20:58:23 | elem | AST only |
| D.cpp:64:10:64:17 | boxfield | AST only |
| D.cpp:64:10:64:17 | this | AST only |
| D.cpp:64:20:64:22 | box | AST only |
| D.cpp:64:25:64:28 | elem | AST only |
| E.cpp:21:10:21:10 | p | AST only |
| E.cpp:21:13:21:16 | data | AST only |
| E.cpp:21:18:21:23 | buffer | AST only |
| E.cpp:28:21:28:23 | raw | AST only |
| E.cpp:29:21:29:21 | b | AST only |
| E.cpp:29:24:29:29 | buffer | AST only |
| E.cpp:30:21:30:21 | p | AST only |
| E.cpp:30:23:30:26 | data | AST only |
| E.cpp:30:28:30:33 | buffer | AST only |
| E.cpp:31:10:31:12 | raw | AST only |
| E.cpp:32:10:32:10 | b | AST only |
| E.cpp:32:13:32:18 | buffer | AST only |
| E.cpp:33:18:33:19 | & ... | AST only |
| aliasing.cpp:9:6:9:7 | m1 | AST only |
| aliasing.cpp:13:5:13:6 | m1 | AST only |
| aliasing.cpp:17:5:17:6 | m1 | AST only |
| aliasing.cpp:25:17:25:19 | & ... | AST only |
| aliasing.cpp:26:19:26:20 | s2 | AST only |
| aliasing.cpp:37:8:37:9 | m1 | AST only |
| aliasing.cpp:42:6:42:7 | m1 | AST only |
| aliasing.cpp:49:9:49:10 | m1 | AST only |
| aliasing.cpp:54:6:54:7 | m1 | AST only |
| aliasing.cpp:60:6:60:7 | m1 | AST only |
| aliasing.cpp:72:5:72:6 | m1 | AST only |
| aliasing.cpp:79:6:79:7 | m1 | AST only |
| aliasing.cpp:86:5:86:6 | m1 | AST only |
| aliasing.cpp:92:3:92:3 | w | AST only |
| aliasing.cpp:92:7:92:8 | m1 | AST only |
| by_reference.cpp:12:8:12:8 | a | AST only |
| by_reference.cpp:16:5:16:8 | this | AST only |
| by_reference.cpp:16:11:16:11 | a | AST only |
| by_reference.cpp:20:5:20:8 | this | AST only |
| by_reference.cpp:20:23:20:27 | value | AST only |
| by_reference.cpp:24:19:24:22 | this | AST only |
| by_reference.cpp:24:25:24:29 | value | AST only |
| by_reference.cpp:50:3:50:3 | s | AST only |
| by_reference.cpp:50:17:50:26 | call to user_input | AST only |
| by_reference.cpp:51:10:51:20 | call to getDirectly | AST only |
| by_reference.cpp:56:3:56:3 | s | AST only |
| by_reference.cpp:56:19:56:28 | call to user_input | AST only |
| by_reference.cpp:57:10:57:22 | call to getIndirectly | AST only |
| by_reference.cpp:62:3:62:3 | s | AST only |
| by_reference.cpp:62:25:62:34 | call to user_input | AST only |
| by_reference.cpp:63:10:63:28 | call to getThroughNonMember | AST only |
| by_reference.cpp:68:17:68:18 | & ... | AST only |
| by_reference.cpp:68:21:68:30 | call to user_input | AST only |
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | AST only |
| by_reference.cpp:84:10:84:10 | a | AST only |
| by_reference.cpp:88:9:88:9 | a | AST only |
| by_reference.cpp:102:21:102:39 | & ... | AST only |
| by_reference.cpp:102:22:102:26 | outer | AST only |
| by_reference.cpp:103:21:103:25 | outer | AST only |
| by_reference.cpp:103:27:103:35 | inner_ptr | AST only |
| by_reference.cpp:104:15:104:22 | & ... | AST only |
| by_reference.cpp:104:16:104:20 | outer | AST only |
| by_reference.cpp:106:21:106:41 | & ... | AST only |
| by_reference.cpp:106:22:106:27 | pouter | AST only |
| by_reference.cpp:107:21:107:26 | pouter | AST only |
| by_reference.cpp:107:29:107:37 | inner_ptr | AST only |
| by_reference.cpp:108:15:108:24 | & ... | AST only |
| by_reference.cpp:108:16:108:21 | pouter | AST only |
| by_reference.cpp:110:8:110:12 | outer | AST only |
| by_reference.cpp:110:14:110:25 | inner_nested | AST only |
| by_reference.cpp:110:27:110:27 | a | AST only |
| by_reference.cpp:111:8:111:12 | outer | AST only |
| by_reference.cpp:111:14:111:22 | inner_ptr | AST only |
| by_reference.cpp:111:25:111:25 | a | AST only |
| by_reference.cpp:112:8:112:12 | outer | AST only |
| by_reference.cpp:112:14:112:14 | a | AST only |
| by_reference.cpp:114:8:114:13 | pouter | AST only |
| by_reference.cpp:114:16:114:27 | inner_nested | AST only |
| by_reference.cpp:114:29:114:29 | a | AST only |
| by_reference.cpp:115:8:115:13 | pouter | AST only |
| by_reference.cpp:115:16:115:24 | inner_ptr | AST only |
| by_reference.cpp:115:27:115:27 | a | AST only |
| by_reference.cpp:116:8:116:13 | pouter | AST only |
| by_reference.cpp:116:16:116:16 | a | AST only |
| by_reference.cpp:122:21:122:25 | outer | AST only |
| by_reference.cpp:122:27:122:38 | inner_nested | AST only |
| by_reference.cpp:123:21:123:36 | * ... | AST only |
| by_reference.cpp:123:22:123:26 | outer | AST only |
| by_reference.cpp:124:15:124:19 | outer | AST only |
| by_reference.cpp:124:21:124:21 | a | AST only |
| by_reference.cpp:126:21:126:26 | pouter | AST only |
| by_reference.cpp:126:29:126:40 | inner_nested | AST only |
| by_reference.cpp:127:21:127:38 | * ... | AST only |
| by_reference.cpp:127:22:127:27 | pouter | AST only |
| by_reference.cpp:128:15:128:20 | pouter | AST only |
| by_reference.cpp:128:23:128:23 | a | AST only |
| by_reference.cpp:130:8:130:12 | outer | AST only |
| by_reference.cpp:130:14:130:25 | inner_nested | AST only |
| by_reference.cpp:130:27:130:27 | a | AST only |
| by_reference.cpp:131:8:131:12 | outer | AST only |
| by_reference.cpp:131:14:131:22 | inner_ptr | AST only |
| by_reference.cpp:131:25:131:25 | a | AST only |
| by_reference.cpp:132:8:132:12 | outer | AST only |
| by_reference.cpp:132:14:132:14 | a | AST only |
| by_reference.cpp:134:8:134:13 | pouter | AST only |
| by_reference.cpp:134:16:134:27 | inner_nested | AST only |
| by_reference.cpp:134:29:134:29 | a | AST only |
| by_reference.cpp:135:8:135:13 | pouter | AST only |
| by_reference.cpp:135:16:135:24 | inner_ptr | AST only |
| by_reference.cpp:135:27:135:27 | a | AST only |
| by_reference.cpp:136:8:136:13 | pouter | AST only |
| by_reference.cpp:136:16:136:16 | a | AST only |
| complex.cpp:11:22:11:23 | a_ | AST only |
| complex.cpp:11:22:11:23 | this | AST only |
| complex.cpp:12:22:12:23 | b_ | AST only |
| complex.cpp:12:22:12:23 | this | AST only |
| complex.cpp:51:8:51:8 | b | AST only |
| complex.cpp:51:10:51:14 | inner | AST only |
| complex.cpp:51:16:51:16 | f | AST only |
| complex.cpp:52:8:52:8 | b | AST only |
| complex.cpp:52:10:52:14 | inner | AST only |
| complex.cpp:52:16:52:16 | f | AST only |
| complex.cpp:62:3:62:4 | b1 | AST only |
| complex.cpp:62:6:62:10 | inner | AST only |
| complex.cpp:62:12:62:12 | f | AST only |
| complex.cpp:63:3:63:4 | b2 | AST only |
| complex.cpp:63:6:63:10 | inner | AST only |
| complex.cpp:63:12:63:12 | f | AST only |
| complex.cpp:64:3:64:4 | b3 | AST only |
| complex.cpp:64:6:64:10 | inner | AST only |
| complex.cpp:64:12:64:12 | f | AST only |
| complex.cpp:65:3:65:4 | b3 | AST only |
| complex.cpp:65:6:65:10 | inner | AST only |
| complex.cpp:65:12:65:12 | f | AST only |
| complex.cpp:68:7:68:8 | b1 | AST only |
| complex.cpp:71:7:71:8 | b2 | AST only |
| complex.cpp:74:7:74:8 | b3 | AST only |
| complex.cpp:77:7:77:8 | b4 | AST only |
| constructors.cpp:20:24:20:25 | a_ | AST only |
| constructors.cpp:20:24:20:25 | this | AST only |
| constructors.cpp:21:24:21:25 | b_ | AST only |
| constructors.cpp:21:24:21:25 | this | AST only |
| constructors.cpp:28:10:28:10 | f | AST only |
| constructors.cpp:29:10:29:10 | f | AST only |
| constructors.cpp:40:9:40:9 | f | AST only |
| constructors.cpp:43:9:43:9 | g | AST only |
| constructors.cpp:46:9:46:9 | h | AST only |
| constructors.cpp:49:9:49:9 | i | AST only |
| file://:0:0:0:0 | this | AST only |
| file://:0:0:0:0 | this | AST only |
| file://:0:0:0:0 | this | AST only |
| file://:0:0:0:0 | this | AST only |
| file://:0:0:0:0 | this | AST only |
| file://:0:0:0:0 | this | AST only |
| file://:0:0:0:0 | this | AST only |
| file://:0:0:0:0 | this | AST only |
| file://:0:0:0:0 | this | AST only |
| file://:0:0:0:0 | this | AST only |
| qualifiers.cpp:9:30:9:33 | this | AST only |
| qualifiers.cpp:9:36:9:36 | a | AST only |
| qualifiers.cpp:12:56:12:56 | a | AST only |
| qualifiers.cpp:13:57:13:57 | a | AST only |
| qualifiers.cpp:22:5:22:9 | outer | AST only |
| qualifiers.cpp:22:11:22:18 | call to getInner | AST only |
| qualifiers.cpp:22:23:22:23 | a | AST only |
| qualifiers.cpp:23:10:23:14 | outer | AST only |
| qualifiers.cpp:23:16:23:20 | inner | AST only |
| qualifiers.cpp:23:23:23:23 | a | AST only |
| qualifiers.cpp:27:5:27:9 | outer | AST only |
| qualifiers.cpp:27:11:27:18 | call to getInner | AST only |
| qualifiers.cpp:27:28:27:37 | call to user_input | AST only |
| qualifiers.cpp:28:10:28:14 | outer | AST only |
| qualifiers.cpp:28:16:28:20 | inner | AST only |
| qualifiers.cpp:28:23:28:23 | a | AST only |
| qualifiers.cpp:32:17:32:21 | outer | AST only |
| qualifiers.cpp:32:23:32:30 | call to getInner | AST only |
| qualifiers.cpp:32:35:32:44 | call to user_input | AST only |
| qualifiers.cpp:33:10:33:14 | outer | AST only |
| qualifiers.cpp:33:16:33:20 | inner | AST only |
| qualifiers.cpp:33:23:33:23 | a | AST only |
| qualifiers.cpp:37:19:37:35 | * ... | AST only |
| qualifiers.cpp:37:20:37:24 | outer | AST only |
| qualifiers.cpp:37:38:37:47 | call to user_input | AST only |
| qualifiers.cpp:38:10:38:14 | outer | AST only |
| qualifiers.cpp:38:16:38:20 | inner | AST only |
| qualifiers.cpp:38:23:38:23 | a | AST only |
| qualifiers.cpp:42:6:42:22 | * ... | AST only |
| qualifiers.cpp:42:7:42:11 | outer | AST only |
| qualifiers.cpp:42:25:42:25 | a | AST only |
| qualifiers.cpp:43:10:43:14 | outer | AST only |
| qualifiers.cpp:43:16:43:20 | inner | AST only |
| qualifiers.cpp:43:23:43:23 | a | AST only |
| qualifiers.cpp:47:6:47:11 | & ... | AST only |
| qualifiers.cpp:47:15:47:22 | call to getInner | AST only |
| qualifiers.cpp:47:27:47:27 | a | AST only |
| qualifiers.cpp:48:10:48:14 | outer | AST only |
| qualifiers.cpp:48:16:48:20 | inner | AST only |
| qualifiers.cpp:48:23:48:23 | a | AST only |
| simple.cpp:20:24:20:25 | a_ | AST only |
| simple.cpp:20:24:20:25 | this | AST only |
| simple.cpp:21:24:21:25 | b_ | AST only |
| simple.cpp:21:24:21:25 | this | AST only |
| simple.cpp:28:10:28:10 | f | AST only |
| simple.cpp:29:10:29:10 | f | AST only |
| simple.cpp:39:5:39:5 | f | AST only |
| simple.cpp:40:5:40:5 | g | AST only |
| simple.cpp:41:5:41:5 | h | AST only |
| simple.cpp:42:5:42:5 | h | AST only |
| simple.cpp:45:9:45:9 | f | AST only |
| simple.cpp:48:9:48:9 | g | AST only |
| simple.cpp:51:9:51:9 | h | AST only |
| simple.cpp:54:9:54:9 | i | AST only |
| simple.cpp:65:7:65:7 | i | AST only |
| simple.cpp:83:9:83:10 | f2 | AST only |
| simple.cpp:83:9:83:10 | this | AST only |
| simple.cpp:83:12:83:13 | f1 | AST only |
| struct_init.c:15:8:15:9 | ab | AST only |
| struct_init.c:15:12:15:12 | a | AST only |
| struct_init.c:16:8:16:9 | ab | AST only |
| struct_init.c:16:12:16:12 | b | AST only |
| struct_init.c:22:8:22:9 | ab | AST only |
| struct_init.c:22:11:22:11 | a | AST only |
| struct_init.c:23:8:23:9 | ab | AST only |
| struct_init.c:23:11:23:11 | b | AST only |
| struct_init.c:24:10:24:12 | & ... | AST only |
| struct_init.c:31:8:31:12 | outer | AST only |
| struct_init.c:31:14:31:21 | nestedAB | AST only |
| struct_init.c:31:23:31:23 | a | AST only |
| struct_init.c:32:8:32:12 | outer | AST only |
| struct_init.c:32:14:32:21 | nestedAB | AST only |
| struct_init.c:32:23:32:23 | b | AST only |
| struct_init.c:33:8:33:12 | outer | AST only |
| struct_init.c:33:14:33:22 | pointerAB | AST only |
| struct_init.c:33:25:33:25 | a | AST only |
| struct_init.c:34:8:34:12 | outer | AST only |
| struct_init.c:34:14:34:22 | pointerAB | AST only |
| struct_init.c:34:25:34:25 | b | AST only |
| struct_init.c:36:10:36:24 | & ... | AST only |
| struct_init.c:36:11:36:15 | outer | AST only |
| struct_init.c:46:10:46:14 | outer | AST only |
| struct_init.c:46:16:46:24 | pointerAB | AST only |

View File

@@ -0,0 +1,58 @@
/**
* @kind problem
*/
import cpp
import semmle.code.cpp.ir.dataflow.DataFlow::DataFlow as IR
import semmle.code.cpp.dataflow.DataFlow::DataFlow as AST
newtype TNode =
TASTNode(AST::Node n) or
TIRNode(IR::Node n)
class Node extends TNode {
string toString() { none() }
IR::Node asIR() { none() }
AST::Node asAST() { none() }
Location getLocation() { none() }
}
class ASTNode extends Node, TASTNode {
AST::Node n;
ASTNode() { this = TASTNode(n) }
override string toString() { result = n.asPartialDefinition().toString() }
override AST::Node asAST() { result = n }
override Location getLocation() { result = n.getLocation() }
}
class IRNode extends Node, TIRNode {
IR::Node n;
IRNode() { this = TIRNode(n) }
override string toString() { result = n.asPartialDefinition().toString() }
override IR::Node asIR() { result = n }
override Location getLocation() { result = n.getLocation() }
}
from Node node, AST::Node astNode, IR::Node irNode, string msg
where
node.asIR() = irNode and
exists(irNode.asPartialDefinition()) and
not exists(AST::Node otherNode | otherNode.asPartialDefinition() = irNode.asPartialDefinition()) and
msg = "IR only"
or
node.asAST() = astNode and
exists(astNode.asPartialDefinition()) and
not exists(IR::Node otherNode | otherNode.asPartialDefinition() = astNode.asPartialDefinition()) and
msg = "AST only"
select node, msg

View File

@@ -0,0 +1,20 @@
| A.cpp:100:5:100:6 | c1 |
| A.cpp:142:7:142:7 | b |
| aliasing.cpp:9:3:9:3 | s |
| aliasing.cpp:13:3:13:3 | s |
| aliasing.cpp:17:3:17:3 | s |
| aliasing.cpp:37:3:37:6 | ref1 |
| aliasing.cpp:42:3:42:4 | s2 |
| aliasing.cpp:49:3:49:7 | copy1 |
| aliasing.cpp:54:3:54:4 | s2 |
| aliasing.cpp:60:3:60:4 | s2 |
| aliasing.cpp:72:3:72:3 | s |
| aliasing.cpp:79:3:79:3 | s |
| aliasing.cpp:86:3:86:3 | s |
| aliasing.cpp:92:5:92:5 | s |
| by_reference.cpp:12:5:12:5 | s |
| by_reference.cpp:84:3:84:7 | inner |
| by_reference.cpp:88:3:88:7 | inner |
| qualifiers.cpp:12:49:12:53 | inner |
| qualifiers.cpp:13:51:13:55 | inner |
| simple.cpp:65:5:65:5 | a |

View File

@@ -0,0 +1,8 @@
/**
* @kind problem
*/
import cpp
import semmle.code.cpp.ir.dataflow.DataFlow::DataFlow
select any(Node n).asPartialDefinition()

View File

@@ -0,0 +1,390 @@
| A.cpp:25:7:25:10 | this |
| A.cpp:25:13:25:13 | c |
| A.cpp:27:22:27:25 | this |
| A.cpp:27:28:27:28 | c |
| A.cpp:31:20:31:20 | c |
| A.cpp:40:5:40:6 | cc |
| A.cpp:41:5:41:6 | ct |
| A.cpp:42:10:42:12 | & ... |
| A.cpp:43:10:43:12 | & ... |
| A.cpp:48:20:48:20 | c |
| A.cpp:49:10:49:10 | b |
| A.cpp:49:13:49:13 | c |
| A.cpp:55:5:55:5 | b |
| A.cpp:56:10:56:10 | b |
| A.cpp:56:13:56:15 | call to get |
| A.cpp:57:28:57:30 | call to get |
| A.cpp:64:17:64:18 | b1 |
| A.cpp:65:10:65:11 | b1 |
| A.cpp:65:14:65:14 | c |
| A.cpp:66:10:66:11 | b2 |
| A.cpp:66:14:66:14 | c |
| A.cpp:73:21:73:22 | b1 |
| A.cpp:74:10:74:11 | b1 |
| A.cpp:74:14:74:14 | c |
| A.cpp:75:10:75:11 | b2 |
| A.cpp:75:14:75:14 | c |
| A.cpp:81:17:81:18 | b1 |
| A.cpp:81:21:81:21 | c |
| A.cpp:90:7:90:8 | b2 |
| A.cpp:90:15:90:15 | c |
| A.cpp:100:5:100:6 | c1 |
| A.cpp:100:9:100:9 | a |
| A.cpp:101:8:101:9 | c1 |
| A.cpp:107:12:107:13 | c1 |
| A.cpp:107:16:107:16 | a |
| A.cpp:120:12:120:13 | c1 |
| A.cpp:120:16:120:16 | a |
| A.cpp:126:5:126:5 | b |
| A.cpp:131:8:131:8 | b |
| A.cpp:132:10:132:10 | b |
| A.cpp:132:13:132:13 | c |
| A.cpp:142:7:142:7 | b |
| A.cpp:142:10:142:10 | c |
| A.cpp:143:7:143:10 | this |
| A.cpp:143:13:143:13 | b |
| A.cpp:151:18:151:18 | b |
| A.cpp:152:10:152:10 | d |
| A.cpp:152:13:152:13 | b |
| A.cpp:153:10:153:10 | d |
| A.cpp:153:13:153:13 | b |
| A.cpp:153:16:153:16 | c |
| A.cpp:154:10:154:10 | b |
| A.cpp:154:13:154:13 | c |
| A.cpp:160:29:160:29 | b |
| A.cpp:161:38:161:39 | l1 |
| A.cpp:162:38:162:39 | l2 |
| A.cpp:163:10:163:11 | l3 |
| A.cpp:163:14:163:17 | head |
| A.cpp:164:10:164:11 | l3 |
| A.cpp:164:14:164:17 | next |
| A.cpp:164:20:164:23 | head |
| A.cpp:165:10:165:11 | l3 |
| A.cpp:165:14:165:17 | next |
| A.cpp:165:20:165:23 | next |
| A.cpp:165:26:165:29 | head |
| A.cpp:166:10:166:11 | l3 |
| A.cpp:166:14:166:17 | next |
| A.cpp:166:20:166:23 | next |
| A.cpp:166:26:166:29 | next |
| A.cpp:166:32:166:35 | head |
| A.cpp:169:12:169:12 | l |
| A.cpp:169:15:169:18 | head |
| A.cpp:183:7:183:10 | head |
| A.cpp:184:7:184:10 | this |
| A.cpp:184:13:184:16 | next |
| B.cpp:7:25:7:25 | e |
| B.cpp:8:25:8:26 | b1 |
| B.cpp:9:10:9:11 | b2 |
| B.cpp:9:14:9:17 | box1 |
| B.cpp:9:20:9:24 | elem1 |
| B.cpp:10:10:10:11 | b2 |
| B.cpp:10:14:10:17 | box1 |
| B.cpp:10:20:10:24 | elem2 |
| B.cpp:16:37:16:37 | e |
| B.cpp:17:25:17:26 | b1 |
| B.cpp:18:10:18:11 | b2 |
| B.cpp:18:14:18:17 | box1 |
| B.cpp:18:20:18:24 | elem1 |
| B.cpp:19:10:19:11 | b2 |
| B.cpp:19:14:19:17 | box1 |
| B.cpp:19:20:19:24 | elem2 |
| B.cpp:35:7:35:10 | this |
| B.cpp:35:13:35:17 | elem1 |
| B.cpp:36:7:36:10 | this |
| B.cpp:36:13:36:17 | elem2 |
| B.cpp:46:7:46:10 | this |
| B.cpp:46:13:46:16 | box1 |
| C.cpp:19:5:19:5 | c |
| C.cpp:24:5:24:8 | this |
| C.cpp:24:11:24:12 | s3 |
| D.cpp:9:21:9:24 | elem |
| D.cpp:11:29:11:32 | elem |
| D.cpp:16:21:16:23 | box |
| D.cpp:18:29:18:31 | box |
| D.cpp:22:10:22:11 | b2 |
| D.cpp:22:14:22:20 | call to getBox1 |
| D.cpp:22:25:22:31 | call to getElem |
| D.cpp:30:5:30:5 | b |
| D.cpp:30:8:30:10 | box |
| D.cpp:30:13:30:16 | elem |
| D.cpp:31:14:31:14 | b |
| D.cpp:37:5:37:5 | b |
| D.cpp:37:8:37:10 | box |
| D.cpp:37:21:37:21 | e |
| D.cpp:38:14:38:14 | b |
| D.cpp:44:5:44:5 | b |
| D.cpp:44:8:44:14 | call to getBox1 |
| D.cpp:44:19:44:22 | elem |
| D.cpp:45:14:45:14 | b |
| D.cpp:51:5:51:5 | b |
| D.cpp:51:8:51:14 | call to getBox1 |
| D.cpp:51:27:51:27 | e |
| D.cpp:52:14:52:14 | b |
| D.cpp:57:5:57:12 | boxfield |
| D.cpp:58:5:58:12 | boxfield |
| D.cpp:58:15:58:17 | box |
| D.cpp:58:20:58:23 | elem |
| D.cpp:64:10:64:17 | boxfield |
| D.cpp:64:20:64:22 | box |
| D.cpp:64:25:64:28 | elem |
| E.cpp:21:10:21:10 | p |
| E.cpp:21:13:21:16 | data |
| E.cpp:21:18:21:23 | buffer |
| E.cpp:28:21:28:23 | raw |
| E.cpp:29:21:29:21 | b |
| E.cpp:29:24:29:29 | buffer |
| E.cpp:30:21:30:21 | p |
| E.cpp:30:23:30:26 | data |
| E.cpp:30:28:30:33 | buffer |
| E.cpp:31:10:31:12 | raw |
| E.cpp:32:10:32:10 | b |
| E.cpp:32:13:32:18 | buffer |
| E.cpp:33:18:33:19 | & ... |
| aliasing.cpp:9:3:9:3 | s |
| aliasing.cpp:9:6:9:7 | m1 |
| aliasing.cpp:13:3:13:3 | s |
| aliasing.cpp:13:5:13:6 | m1 |
| aliasing.cpp:17:3:17:3 | s |
| aliasing.cpp:17:5:17:6 | m1 |
| aliasing.cpp:25:17:25:19 | & ... |
| aliasing.cpp:26:19:26:20 | s2 |
| aliasing.cpp:37:3:37:6 | ref1 |
| aliasing.cpp:37:8:37:9 | m1 |
| aliasing.cpp:42:3:42:4 | s2 |
| aliasing.cpp:42:6:42:7 | m1 |
| aliasing.cpp:49:3:49:7 | copy1 |
| aliasing.cpp:49:9:49:10 | m1 |
| aliasing.cpp:54:3:54:4 | s2 |
| aliasing.cpp:54:6:54:7 | m1 |
| aliasing.cpp:60:3:60:4 | s2 |
| aliasing.cpp:60:6:60:7 | m1 |
| aliasing.cpp:72:3:72:3 | s |
| aliasing.cpp:72:5:72:6 | m1 |
| aliasing.cpp:79:3:79:3 | s |
| aliasing.cpp:79:6:79:7 | m1 |
| aliasing.cpp:86:3:86:3 | s |
| aliasing.cpp:86:5:86:6 | m1 |
| aliasing.cpp:92:3:92:3 | w |
| aliasing.cpp:92:5:92:5 | s |
| aliasing.cpp:92:7:92:8 | m1 |
| by_reference.cpp:12:5:12:5 | s |
| by_reference.cpp:12:8:12:8 | a |
| by_reference.cpp:16:5:16:8 | this |
| by_reference.cpp:16:11:16:11 | a |
| by_reference.cpp:20:5:20:8 | this |
| by_reference.cpp:20:23:20:27 | value |
| by_reference.cpp:24:19:24:22 | this |
| by_reference.cpp:24:25:24:29 | value |
| by_reference.cpp:50:3:50:3 | s |
| by_reference.cpp:50:17:50:26 | call to user_input |
| by_reference.cpp:51:10:51:20 | call to getDirectly |
| by_reference.cpp:56:3:56:3 | s |
| by_reference.cpp:56:19:56:28 | call to user_input |
| by_reference.cpp:57:10:57:22 | call to getIndirectly |
| by_reference.cpp:62:3:62:3 | s |
| by_reference.cpp:62:25:62:34 | call to user_input |
| by_reference.cpp:63:10:63:28 | call to getThroughNonMember |
| by_reference.cpp:68:17:68:18 | & ... |
| by_reference.cpp:68:21:68:30 | call to user_input |
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA |
| by_reference.cpp:84:3:84:7 | inner |
| by_reference.cpp:84:10:84:10 | a |
| by_reference.cpp:88:3:88:7 | inner |
| by_reference.cpp:88:9:88:9 | a |
| by_reference.cpp:102:21:102:39 | & ... |
| by_reference.cpp:102:22:102:26 | outer |
| by_reference.cpp:103:21:103:25 | outer |
| by_reference.cpp:103:27:103:35 | inner_ptr |
| by_reference.cpp:104:15:104:22 | & ... |
| by_reference.cpp:104:16:104:20 | outer |
| by_reference.cpp:106:21:106:41 | & ... |
| by_reference.cpp:106:22:106:27 | pouter |
| by_reference.cpp:107:21:107:26 | pouter |
| by_reference.cpp:107:29:107:37 | inner_ptr |
| by_reference.cpp:108:15:108:24 | & ... |
| by_reference.cpp:108:16:108:21 | pouter |
| by_reference.cpp:110:8:110:12 | outer |
| by_reference.cpp:110:14:110:25 | inner_nested |
| by_reference.cpp:110:27:110:27 | a |
| by_reference.cpp:111:8:111:12 | outer |
| by_reference.cpp:111:14:111:22 | inner_ptr |
| by_reference.cpp:111:25:111:25 | a |
| by_reference.cpp:112:8:112:12 | outer |
| by_reference.cpp:112:14:112:14 | a |
| by_reference.cpp:114:8:114:13 | pouter |
| by_reference.cpp:114:16:114:27 | inner_nested |
| by_reference.cpp:114:29:114:29 | a |
| by_reference.cpp:115:8:115:13 | pouter |
| by_reference.cpp:115:16:115:24 | inner_ptr |
| by_reference.cpp:115:27:115:27 | a |
| by_reference.cpp:116:8:116:13 | pouter |
| by_reference.cpp:116:16:116:16 | a |
| by_reference.cpp:122:21:122:25 | outer |
| by_reference.cpp:122:27:122:38 | inner_nested |
| by_reference.cpp:123:21:123:36 | * ... |
| by_reference.cpp:123:22:123:26 | outer |
| by_reference.cpp:124:15:124:19 | outer |
| by_reference.cpp:124:21:124:21 | a |
| by_reference.cpp:126:21:126:26 | pouter |
| by_reference.cpp:126:29:126:40 | inner_nested |
| by_reference.cpp:127:21:127:38 | * ... |
| by_reference.cpp:127:22:127:27 | pouter |
| by_reference.cpp:128:15:128:20 | pouter |
| by_reference.cpp:128:23:128:23 | a |
| by_reference.cpp:130:8:130:12 | outer |
| by_reference.cpp:130:14:130:25 | inner_nested |
| by_reference.cpp:130:27:130:27 | a |
| by_reference.cpp:131:8:131:12 | outer |
| by_reference.cpp:131:14:131:22 | inner_ptr |
| by_reference.cpp:131:25:131:25 | a |
| by_reference.cpp:132:8:132:12 | outer |
| by_reference.cpp:132:14:132:14 | a |
| by_reference.cpp:134:8:134:13 | pouter |
| by_reference.cpp:134:16:134:27 | inner_nested |
| by_reference.cpp:134:29:134:29 | a |
| by_reference.cpp:135:8:135:13 | pouter |
| by_reference.cpp:135:16:135:24 | inner_ptr |
| by_reference.cpp:135:27:135:27 | a |
| by_reference.cpp:136:8:136:13 | pouter |
| by_reference.cpp:136:16:136:16 | a |
| complex.cpp:11:22:11:23 | a_ |
| complex.cpp:12:22:12:23 | b_ |
| complex.cpp:51:8:51:8 | b |
| complex.cpp:51:10:51:14 | inner |
| complex.cpp:51:16:51:16 | f |
| complex.cpp:52:8:52:8 | b |
| complex.cpp:52:10:52:14 | inner |
| complex.cpp:52:16:52:16 | f |
| complex.cpp:62:3:62:4 | b1 |
| complex.cpp:62:6:62:10 | inner |
| complex.cpp:62:12:62:12 | f |
| complex.cpp:63:3:63:4 | b2 |
| complex.cpp:63:6:63:10 | inner |
| complex.cpp:63:12:63:12 | f |
| complex.cpp:64:3:64:4 | b3 |
| complex.cpp:64:6:64:10 | inner |
| complex.cpp:64:12:64:12 | f |
| complex.cpp:65:3:65:4 | b3 |
| complex.cpp:65:6:65:10 | inner |
| complex.cpp:65:12:65:12 | f |
| complex.cpp:68:7:68:8 | b1 |
| complex.cpp:71:7:71:8 | b2 |
| complex.cpp:74:7:74:8 | b3 |
| complex.cpp:77:7:77:8 | b4 |
| constructors.cpp:20:24:20:25 | a_ |
| constructors.cpp:21:24:21:25 | b_ |
| constructors.cpp:28:10:28:10 | f |
| constructors.cpp:29:10:29:10 | f |
| constructors.cpp:40:9:40:9 | f |
| constructors.cpp:43:9:43:9 | g |
| constructors.cpp:46:9:46:9 | h |
| constructors.cpp:49:9:49:9 | i |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| file://:0:0:0:0 | this |
| qualifiers.cpp:9:30:9:33 | this |
| qualifiers.cpp:9:36:9:36 | a |
| qualifiers.cpp:12:49:12:53 | inner |
| qualifiers.cpp:12:56:12:56 | a |
| qualifiers.cpp:13:51:13:55 | inner |
| qualifiers.cpp:13:57:13:57 | a |
| qualifiers.cpp:22:5:22:9 | outer |
| qualifiers.cpp:22:11:22:18 | call to getInner |
| qualifiers.cpp:22:23:22:23 | a |
| qualifiers.cpp:23:10:23:14 | outer |
| qualifiers.cpp:23:16:23:20 | inner |
| qualifiers.cpp:23:23:23:23 | a |
| qualifiers.cpp:27:5:27:9 | outer |
| qualifiers.cpp:27:11:27:18 | call to getInner |
| qualifiers.cpp:27:28:27:37 | call to user_input |
| qualifiers.cpp:28:10:28:14 | outer |
| qualifiers.cpp:28:16:28:20 | inner |
| qualifiers.cpp:28:23:28:23 | a |
| qualifiers.cpp:32:17:32:21 | outer |
| qualifiers.cpp:32:23:32:30 | call to getInner |
| qualifiers.cpp:32:35:32:44 | call to user_input |
| qualifiers.cpp:33:10:33:14 | outer |
| qualifiers.cpp:33:16:33:20 | inner |
| qualifiers.cpp:33:23:33:23 | a |
| qualifiers.cpp:37:19:37:35 | * ... |
| qualifiers.cpp:37:20:37:24 | outer |
| qualifiers.cpp:37:38:37:47 | call to user_input |
| qualifiers.cpp:38:10:38:14 | outer |
| qualifiers.cpp:38:16:38:20 | inner |
| qualifiers.cpp:38:23:38:23 | a |
| qualifiers.cpp:42:6:42:22 | * ... |
| qualifiers.cpp:42:7:42:11 | outer |
| qualifiers.cpp:42:25:42:25 | a |
| qualifiers.cpp:43:10:43:14 | outer |
| qualifiers.cpp:43:16:43:20 | inner |
| qualifiers.cpp:43:23:43:23 | a |
| qualifiers.cpp:47:6:47:11 | & ... |
| qualifiers.cpp:47:15:47:22 | call to getInner |
| qualifiers.cpp:47:27:47:27 | a |
| qualifiers.cpp:48:10:48:14 | outer |
| qualifiers.cpp:48:16:48:20 | inner |
| qualifiers.cpp:48:23:48:23 | a |
| simple.cpp:20:24:20:25 | a_ |
| simple.cpp:21:24:21:25 | b_ |
| simple.cpp:28:10:28:10 | f |
| simple.cpp:29:10:29:10 | f |
| simple.cpp:39:5:39:5 | f |
| simple.cpp:40:5:40:5 | g |
| simple.cpp:41:5:41:5 | h |
| simple.cpp:42:5:42:5 | h |
| simple.cpp:45:9:45:9 | f |
| simple.cpp:48:9:48:9 | g |
| simple.cpp:51:9:51:9 | h |
| simple.cpp:54:9:54:9 | i |
| simple.cpp:65:5:65:5 | a |
| simple.cpp:65:7:65:7 | i |
| simple.cpp:83:9:83:10 | f2 |
| simple.cpp:83:12:83:13 | f1 |
| struct_init.c:15:8:15:9 | ab |
| struct_init.c:15:12:15:12 | a |
| struct_init.c:16:8:16:9 | ab |
| struct_init.c:16:12:16:12 | b |
| struct_init.c:22:8:22:9 | ab |
| struct_init.c:22:11:22:11 | a |
| struct_init.c:23:8:23:9 | ab |
| struct_init.c:23:11:23:11 | b |
| struct_init.c:24:10:24:12 | & ... |
| struct_init.c:31:8:31:12 | outer |
| struct_init.c:31:14:31:21 | nestedAB |
| struct_init.c:31:23:31:23 | a |
| struct_init.c:32:8:32:12 | outer |
| struct_init.c:32:14:32:21 | nestedAB |
| struct_init.c:32:23:32:23 | b |
| struct_init.c:33:8:33:12 | outer |
| struct_init.c:33:14:33:22 | pointerAB |
| struct_init.c:33:25:33:25 | a |
| struct_init.c:34:8:34:12 | outer |
| struct_init.c:34:14:34:22 | pointerAB |
| struct_init.c:34:25:34:25 | b |
| struct_init.c:36:10:36:24 | & ... |
| struct_init.c:36:11:36:15 | outer |
| struct_init.c:46:10:46:14 | outer |
| struct_init.c:46:16:46:24 | pointerAB |

View File

@@ -0,0 +1,8 @@
/**
* @kind problem
*/
import cpp
import semmle.code.cpp.dataflow.DataFlow::DataFlow
select any(Node n).asPartialDefinition()

View File

@@ -15,10 +15,14 @@ int vsnprintf(char *s, size_t n, const char *format, va_list arg);
int mysprintf(char *s, size_t n, const char *format, ...)
{
int result;
va_list args;
va_start(args, format);
vsnprintf(s, n, format, args);
result = vsnprintf(s, n, format, args);
va_end(args);
return result;
}
int sscanf(const char *s, const char *format, ...);

View File

@@ -3,112 +3,114 @@
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
| format.cpp:16:21:16:21 | s | format.cpp:20:13:20:13 | s | |
| format.cpp:16:31:16:31 | n | format.cpp:20:16:20:16 | n | |
| format.cpp:16:46:16:51 | format | format.cpp:20:19:20:24 | format | |
| format.cpp:18:10:18:13 | args | format.cpp:20:27:20:30 | args | |
| format.cpp:46:21:46:24 | {...} | format.cpp:47:17:47:22 | buffer | |
| format.cpp:46:21:46:24 | {...} | format.cpp:48:8:48:13 | buffer | |
| format.cpp:46:23:46:23 | 0 | format.cpp:46:21:46:24 | {...} | TAINT |
| format.cpp:47:17:47:22 | ref arg buffer | format.cpp:48:8:48:13 | buffer | |
| format.cpp:47:30:47:33 | %s | format.cpp:47:17:47:22 | ref arg buffer | TAINT |
| format.cpp:47:36:47:43 | Hello. | format.cpp:47:17:47:22 | ref arg buffer | TAINT |
| format.cpp:51:21:51:24 | {...} | format.cpp:52:17:52:22 | buffer | |
| format.cpp:51:21:51:24 | {...} | format.cpp:53:8:53:13 | buffer | |
| format.cpp:51:23:51:23 | 0 | format.cpp:51:21:51:24 | {...} | TAINT |
| format.cpp:52:17:52:22 | ref arg buffer | format.cpp:53:8:53:13 | buffer | |
| format.cpp:52:30:52:33 | %s | format.cpp:52:17:52:22 | ref arg buffer | TAINT |
| format.cpp:52:36:52:49 | call to source | format.cpp:52:17:52:22 | ref arg buffer | TAINT |
| format.cpp:56:21:56:24 | {...} | format.cpp:57:17:57:22 | buffer | |
| format.cpp:56:21:56:24 | {...} | format.cpp:58:8:58:13 | buffer | |
| format.cpp:56:23:56:23 | 0 | format.cpp:56:21:56:24 | {...} | TAINT |
| format.cpp:57:17:57:22 | ref arg buffer | format.cpp:58:8:58:13 | buffer | |
| format.cpp:57:30:57:43 | call to source | format.cpp:57:17:57:22 | ref arg buffer | TAINT |
| format.cpp:57:48:57:55 | Hello. | format.cpp:57:17:57:22 | ref arg buffer | TAINT |
| format.cpp:61:21:61:24 | {...} | format.cpp:62:17:62:22 | buffer | |
| format.cpp:61:21:61:24 | {...} | format.cpp:63:8:63:13 | buffer | |
| format.cpp:61:23:61:23 | 0 | format.cpp:61:21:61:24 | {...} | TAINT |
| format.cpp:62:17:62:22 | ref arg buffer | format.cpp:63:8:63:13 | buffer | |
| format.cpp:62:30:62:39 | %s %s %s | format.cpp:62:17:62:22 | ref arg buffer | TAINT |
| format.cpp:62:42:62:44 | a | format.cpp:62:17:62:22 | ref arg buffer | TAINT |
| format.cpp:62:47:62:49 | b | format.cpp:62:17:62:22 | ref arg buffer | TAINT |
| format.cpp:62:52:62:65 | call to source | format.cpp:62:17:62:22 | ref arg buffer | TAINT |
| format.cpp:66:21:66:24 | {...} | format.cpp:67:17:67:22 | buffer | |
| format.cpp:66:21:66:24 | {...} | format.cpp:68:8:68:13 | buffer | |
| format.cpp:66:23:66:23 | 0 | format.cpp:66:21:66:24 | {...} | TAINT |
| format.cpp:67:17:67:22 | ref arg buffer | format.cpp:68:8:68:13 | buffer | |
| format.cpp:67:30:67:35 | %.*s | format.cpp:67:17:67:22 | ref arg buffer | TAINT |
| format.cpp:67:38:67:39 | 10 | format.cpp:67:17:67:22 | ref arg buffer | TAINT |
| format.cpp:67:42:67:55 | call to source | format.cpp:67:17:67:22 | ref arg buffer | TAINT |
| format.cpp:72:21:72:24 | {...} | format.cpp:73:17:73:22 | buffer | |
| format.cpp:72:21:72:24 | {...} | format.cpp:74:8:74:13 | buffer | |
| format.cpp:72:23:72:23 | 0 | format.cpp:72:21:72:24 | {...} | TAINT |
| format.cpp:73:17:73:22 | ref arg buffer | format.cpp:74:8:74:13 | buffer | |
| format.cpp:73:30:73:33 | %i | format.cpp:73:17:73:22 | ref arg buffer | TAINT |
| format.cpp:73:36:73:36 | 0 | format.cpp:73:17:73:22 | ref arg buffer | TAINT |
| format.cpp:77:21:77:24 | {...} | format.cpp:78:17:78:22 | buffer | |
| format.cpp:77:21:77:24 | {...} | format.cpp:79:8:79:13 | buffer | |
| format.cpp:77:23:77:23 | 0 | format.cpp:77:21:77:24 | {...} | TAINT |
| format.cpp:78:17:78:22 | ref arg buffer | format.cpp:79:8:79:13 | buffer | |
| format.cpp:78:30:78:33 | %i | format.cpp:78:17:78:22 | ref arg buffer | TAINT |
| format.cpp:78:36:78:41 | call to source | format.cpp:78:17:78:22 | ref arg buffer | TAINT |
| format.cpp:82:21:82:24 | {...} | format.cpp:83:17:83:22 | buffer | |
| format.cpp:82:21:82:24 | {...} | format.cpp:84:8:84:13 | buffer | |
| format.cpp:82:23:82:23 | 0 | format.cpp:82:21:82:24 | {...} | TAINT |
| format.cpp:83:17:83:22 | ref arg buffer | format.cpp:84:8:84:13 | buffer | |
| format.cpp:83:30:83:35 | %.*s | format.cpp:83:17:83:22 | ref arg buffer | TAINT |
| format.cpp:83:38:83:43 | call to source | format.cpp:83:17:83:22 | ref arg buffer | TAINT |
| format.cpp:83:48:83:55 | Hello. | format.cpp:83:17:83:22 | ref arg buffer | TAINT |
| format.cpp:88:21:88:24 | {...} | format.cpp:89:17:89:22 | buffer | |
| format.cpp:88:21:88:24 | {...} | format.cpp:90:8:90:13 | buffer | |
| format.cpp:88:23:88:23 | 0 | format.cpp:88:21:88:24 | {...} | TAINT |
| format.cpp:89:17:89:22 | ref arg buffer | format.cpp:90:8:90:13 | buffer | |
| format.cpp:89:30:89:33 | %p | format.cpp:89:17:89:22 | ref arg buffer | TAINT |
| format.cpp:89:36:89:49 | call to source | format.cpp:89:17:89:22 | ref arg buffer | TAINT |
| format.cpp:94:21:94:24 | {...} | format.cpp:95:16:95:21 | buffer | |
| format.cpp:94:21:94:24 | {...} | format.cpp:96:8:96:13 | buffer | |
| format.cpp:94:23:94:23 | 0 | format.cpp:94:21:94:24 | {...} | TAINT |
| format.cpp:95:16:95:21 | ref arg buffer | format.cpp:96:8:96:13 | buffer | |
| format.cpp:95:24:95:27 | %s | format.cpp:95:16:95:21 | ref arg buffer | TAINT |
| format.cpp:95:30:95:43 | call to source | format.cpp:95:16:95:21 | ref arg buffer | TAINT |
| format.cpp:99:21:99:24 | {...} | format.cpp:100:16:100:21 | buffer | |
| format.cpp:99:21:99:24 | {...} | format.cpp:101:8:101:13 | buffer | |
| format.cpp:99:23:99:23 | 0 | format.cpp:99:21:99:24 | {...} | TAINT |
| format.cpp:100:16:100:21 | ref arg buffer | format.cpp:101:8:101:13 | buffer | |
| format.cpp:100:24:100:28 | %ls | format.cpp:100:16:100:21 | ref arg buffer | TAINT |
| format.cpp:100:31:100:45 | call to source | format.cpp:100:16:100:21 | ref arg buffer | TAINT |
| format.cpp:104:25:104:28 | {...} | format.cpp:105:17:105:23 | wbuffer | |
| format.cpp:104:25:104:28 | {...} | format.cpp:106:8:106:14 | wbuffer | |
| format.cpp:104:27:104:27 | 0 | format.cpp:104:25:104:28 | {...} | TAINT |
| format.cpp:105:17:105:23 | ref arg wbuffer | format.cpp:106:8:106:14 | wbuffer | |
| format.cpp:105:31:105:35 | %s | format.cpp:105:17:105:23 | ref arg wbuffer | TAINT |
| format.cpp:105:38:105:52 | call to source | format.cpp:105:17:105:23 | ref arg wbuffer | TAINT |
| format.cpp:109:21:109:24 | {...} | format.cpp:110:18:110:23 | buffer | |
| format.cpp:109:21:109:24 | {...} | format.cpp:111:8:111:13 | buffer | |
| format.cpp:109:23:109:23 | 0 | format.cpp:109:21:109:24 | {...} | TAINT |
| format.cpp:110:18:110:23 | ref arg buffer | format.cpp:111:8:111:13 | buffer | |
| format.cpp:115:10:115:11 | 0 | format.cpp:116:29:116:29 | i | |
| format.cpp:115:10:115:11 | 0 | format.cpp:117:8:117:8 | i | |
| format.cpp:116:28:116:29 | ref arg & ... | format.cpp:116:29:116:29 | i [inner post update] | |
| format.cpp:116:28:116:29 | ref arg & ... | format.cpp:117:8:117:8 | i | |
| format.cpp:116:29:116:29 | i | format.cpp:116:28:116:29 | & ... | |
| format.cpp:120:10:120:11 | 0 | format.cpp:121:40:121:40 | i | |
| format.cpp:120:10:120:11 | 0 | format.cpp:122:8:122:8 | i | |
| format.cpp:121:39:121:40 | ref arg & ... | format.cpp:121:40:121:40 | i [inner post update] | |
| format.cpp:121:39:121:40 | ref arg & ... | format.cpp:122:8:122:8 | i | |
| format.cpp:121:40:121:40 | i | format.cpp:121:39:121:40 | & ... | |
| format.cpp:125:21:125:24 | {...} | format.cpp:126:32:126:37 | buffer | |
| format.cpp:125:21:125:24 | {...} | format.cpp:127:8:127:13 | buffer | |
| format.cpp:125:23:125:23 | 0 | format.cpp:125:21:125:24 | {...} | TAINT |
| format.cpp:126:31:126:37 | ref arg & ... | format.cpp:126:32:126:37 | buffer [inner post update] | |
| format.cpp:126:31:126:37 | ref arg & ... | format.cpp:127:8:127:13 | buffer | |
| format.cpp:126:32:126:37 | buffer | format.cpp:126:31:126:37 | & ... | |
| format.cpp:130:21:130:24 | {...} | format.cpp:131:40:131:45 | buffer | |
| format.cpp:130:21:130:24 | {...} | format.cpp:132:8:132:13 | buffer | |
| format.cpp:130:23:130:23 | 0 | format.cpp:130:21:130:24 | {...} | TAINT |
| format.cpp:131:39:131:45 | ref arg & ... | format.cpp:131:40:131:45 | buffer [inner post update] | |
| format.cpp:131:39:131:45 | ref arg & ... | format.cpp:132:8:132:13 | buffer | |
| format.cpp:131:40:131:45 | buffer | format.cpp:131:39:131:45 | & ... | |
| 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 | |
| format.cpp:16:46:16:51 | format | format.cpp:22:28:22:33 | format | |
| format.cpp:20:10:20:13 | args | format.cpp:22:36:22:39 | args | |
| format.cpp:22:12:22:20 | call to vsnprintf | format.cpp:22:3:22:40 | ... = ... | |
| format.cpp:22:12:22:20 | call to vsnprintf | format.cpp:25:9:25:14 | result | |
| format.cpp:50:21:50:24 | {...} | format.cpp:51:17:51:22 | buffer | |
| format.cpp:50:21:50:24 | {...} | format.cpp:52:8:52:13 | buffer | |
| format.cpp:50:23:50:23 | 0 | format.cpp:50:21:50:24 | {...} | TAINT |
| format.cpp:51:17:51:22 | ref arg buffer | format.cpp:52:8:52:13 | buffer | |
| format.cpp:51:30:51:33 | %s | format.cpp:51:17:51:22 | ref arg buffer | TAINT |
| format.cpp:51:36:51:43 | Hello. | format.cpp:51:17:51:22 | ref arg buffer | TAINT |
| format.cpp:55:21:55:24 | {...} | format.cpp:56:17:56:22 | buffer | |
| format.cpp:55:21:55:24 | {...} | format.cpp:57:8:57:13 | buffer | |
| format.cpp:55:23:55:23 | 0 | format.cpp:55:21:55:24 | {...} | TAINT |
| format.cpp:56:17:56:22 | ref arg buffer | format.cpp:57:8:57:13 | buffer | |
| format.cpp:56:30:56:33 | %s | format.cpp:56:17:56:22 | ref arg buffer | TAINT |
| format.cpp:56:36:56:49 | call to source | format.cpp:56:17:56:22 | ref arg buffer | TAINT |
| format.cpp:60:21:60:24 | {...} | format.cpp:61:17:61:22 | buffer | |
| format.cpp:60:21:60:24 | {...} | format.cpp:62:8:62:13 | buffer | |
| format.cpp:60:23:60:23 | 0 | format.cpp:60:21:60:24 | {...} | TAINT |
| format.cpp:61:17:61:22 | ref arg buffer | format.cpp:62:8:62:13 | buffer | |
| format.cpp:61:30:61:43 | call to source | format.cpp:61:17:61:22 | ref arg buffer | TAINT |
| format.cpp:61:48:61:55 | Hello. | format.cpp:61:17:61:22 | ref arg buffer | TAINT |
| format.cpp:65:21:65:24 | {...} | format.cpp:66:17:66:22 | buffer | |
| format.cpp:65:21:65:24 | {...} | format.cpp:67:8:67:13 | buffer | |
| format.cpp:65:23:65:23 | 0 | format.cpp:65:21:65:24 | {...} | TAINT |
| format.cpp:66:17:66:22 | ref arg buffer | format.cpp:67:8:67:13 | buffer | |
| format.cpp:66:30:66:39 | %s %s %s | format.cpp:66:17:66:22 | ref arg buffer | TAINT |
| format.cpp:66:42:66:44 | a | format.cpp:66:17:66:22 | ref arg buffer | TAINT |
| format.cpp:66:47:66:49 | b | format.cpp:66:17:66:22 | ref arg buffer | TAINT |
| format.cpp:66:52:66:65 | call to source | format.cpp:66:17:66:22 | ref arg buffer | TAINT |
| format.cpp:70:21:70:24 | {...} | format.cpp:71:17:71:22 | buffer | |
| format.cpp:70:21:70:24 | {...} | format.cpp:72:8:72:13 | buffer | |
| format.cpp:70:23:70:23 | 0 | format.cpp:70:21:70:24 | {...} | TAINT |
| format.cpp:71:17:71:22 | ref arg buffer | format.cpp:72:8:72:13 | buffer | |
| format.cpp:71:30:71:35 | %.*s | format.cpp:71:17:71:22 | ref arg buffer | TAINT |
| format.cpp:71:38:71:39 | 10 | format.cpp:71:17:71:22 | ref arg buffer | TAINT |
| format.cpp:71:42:71:55 | call to source | format.cpp:71:17:71:22 | ref arg buffer | TAINT |
| format.cpp:76:21:76:24 | {...} | format.cpp:77:17:77:22 | buffer | |
| format.cpp:76:21:76:24 | {...} | format.cpp:78:8:78:13 | buffer | |
| format.cpp:76:23:76:23 | 0 | format.cpp:76:21:76:24 | {...} | TAINT |
| format.cpp:77:17:77:22 | ref arg buffer | format.cpp:78:8:78:13 | buffer | |
| format.cpp:77:30:77:33 | %i | format.cpp:77:17:77:22 | ref arg buffer | TAINT |
| format.cpp:77:36:77:36 | 0 | format.cpp:77:17:77:22 | ref arg buffer | TAINT |
| format.cpp:81:21:81:24 | {...} | format.cpp:82:17:82:22 | buffer | |
| format.cpp:81:21:81:24 | {...} | format.cpp:83:8:83:13 | buffer | |
| format.cpp:81:23:81:23 | 0 | format.cpp:81:21:81:24 | {...} | TAINT |
| format.cpp:82:17:82:22 | ref arg buffer | format.cpp:83:8:83:13 | buffer | |
| format.cpp:82:30:82:33 | %i | format.cpp:82:17:82:22 | ref arg buffer | TAINT |
| format.cpp:82:36:82:41 | call to source | format.cpp:82:17:82:22 | ref arg buffer | TAINT |
| format.cpp:86:21:86:24 | {...} | format.cpp:87:17:87:22 | buffer | |
| format.cpp:86:21:86:24 | {...} | format.cpp:88:8:88:13 | buffer | |
| format.cpp:86:23:86:23 | 0 | format.cpp:86:21:86:24 | {...} | TAINT |
| format.cpp:87:17:87:22 | ref arg buffer | format.cpp:88:8:88:13 | buffer | |
| format.cpp:87:30:87:35 | %.*s | format.cpp:87:17:87:22 | ref arg buffer | TAINT |
| format.cpp:87:38:87:43 | call to source | format.cpp:87:17:87:22 | ref arg buffer | TAINT |
| format.cpp:87:48:87:55 | Hello. | format.cpp:87:17:87:22 | ref arg buffer | TAINT |
| format.cpp:92:21:92:24 | {...} | format.cpp:93:17:93:22 | buffer | |
| format.cpp:92:21:92:24 | {...} | format.cpp:94:8:94:13 | buffer | |
| format.cpp:92:23:92:23 | 0 | format.cpp:92:21:92:24 | {...} | TAINT |
| format.cpp:93:17:93:22 | ref arg buffer | format.cpp:94:8:94:13 | buffer | |
| format.cpp:93:30:93:33 | %p | format.cpp:93:17:93:22 | ref arg buffer | TAINT |
| format.cpp:93:36:93:49 | call to source | format.cpp:93:17:93:22 | ref arg buffer | TAINT |
| format.cpp:98:21:98:24 | {...} | format.cpp:99:16:99:21 | buffer | |
| format.cpp:98:21:98:24 | {...} | format.cpp:100:8:100:13 | buffer | |
| format.cpp:98:23:98:23 | 0 | format.cpp:98:21:98:24 | {...} | TAINT |
| format.cpp:99:16:99:21 | ref arg buffer | format.cpp:100:8:100:13 | buffer | |
| format.cpp:99:24:99:27 | %s | format.cpp:99:16:99:21 | ref arg buffer | TAINT |
| format.cpp:99:30:99:43 | call to source | format.cpp:99:16:99:21 | ref arg buffer | TAINT |
| format.cpp:103:21:103:24 | {...} | format.cpp:104:16:104:21 | buffer | |
| format.cpp:103:21:103:24 | {...} | format.cpp:105:8:105:13 | buffer | |
| format.cpp:103:23:103:23 | 0 | format.cpp:103:21:103:24 | {...} | TAINT |
| format.cpp:104:16:104:21 | ref arg buffer | format.cpp:105:8:105:13 | buffer | |
| format.cpp:104:24:104:28 | %ls | format.cpp:104:16:104:21 | ref arg buffer | TAINT |
| format.cpp:104:31:104:45 | call to source | format.cpp:104:16:104:21 | ref arg buffer | TAINT |
| format.cpp:108:25:108:28 | {...} | format.cpp:109:17:109:23 | wbuffer | |
| format.cpp:108:25:108:28 | {...} | format.cpp:110:8:110:14 | wbuffer | |
| format.cpp:108:27:108:27 | 0 | format.cpp:108:25:108:28 | {...} | TAINT |
| format.cpp:109:17:109:23 | ref arg wbuffer | format.cpp:110:8:110:14 | wbuffer | |
| format.cpp:109:31:109:35 | %s | format.cpp:109:17:109:23 | ref arg wbuffer | TAINT |
| format.cpp:109:38:109:52 | call to source | format.cpp:109:17:109:23 | ref arg wbuffer | TAINT |
| format.cpp:113:21:113:24 | {...} | format.cpp:114:18:114:23 | buffer | |
| format.cpp:113:21:113:24 | {...} | format.cpp:115:8:115:13 | buffer | |
| format.cpp:113:23:113:23 | 0 | format.cpp:113:21:113:24 | {...} | TAINT |
| format.cpp:114:18:114:23 | ref arg buffer | format.cpp:115:8:115:13 | buffer | |
| format.cpp:119:10:119:11 | 0 | format.cpp:120:29:120:29 | i | |
| format.cpp:119:10:119:11 | 0 | format.cpp:121:8:121:8 | i | |
| format.cpp:120:28:120:29 | ref arg & ... | format.cpp:120:29:120:29 | i [inner post update] | |
| format.cpp:120:28:120:29 | ref arg & ... | format.cpp:121:8:121:8 | i | |
| format.cpp:120:29:120:29 | i | format.cpp:120:28:120:29 | & ... | |
| format.cpp:124:10:124:11 | 0 | format.cpp:125:40:125:40 | i | |
| format.cpp:124:10:124:11 | 0 | format.cpp:126:8:126:8 | i | |
| format.cpp:125:39:125:40 | ref arg & ... | format.cpp:125:40:125:40 | i [inner post update] | |
| format.cpp:125:39:125:40 | ref arg & ... | format.cpp:126:8:126:8 | i | |
| format.cpp:125:40:125:40 | i | format.cpp:125:39:125:40 | & ... | |
| format.cpp:129:21:129:24 | {...} | format.cpp:130:32:130:37 | buffer | |
| format.cpp:129:21:129:24 | {...} | format.cpp:131:8:131:13 | buffer | |
| format.cpp:129:23:129:23 | 0 | format.cpp:129:21:129:24 | {...} | TAINT |
| format.cpp:130:31:130:37 | ref arg & ... | format.cpp:130:32:130:37 | buffer [inner post update] | |
| format.cpp:130:31:130:37 | ref arg & ... | format.cpp:131:8:131:13 | buffer | |
| format.cpp:130:32:130:37 | buffer | format.cpp:130:31:130:37 | & ... | |
| format.cpp:134:21:134:24 | {...} | format.cpp:135:40:135:45 | buffer | |
| format.cpp:134:21:134:24 | {...} | format.cpp:136:8:136:13 | buffer | |
| format.cpp:134:23:134:23 | 0 | format.cpp:134:21:134:24 | {...} | TAINT |
| format.cpp:135:39:135:45 | ref arg & ... | format.cpp:135:40:135:45 | buffer [inner post update] | |
| format.cpp:135:39:135:45 | ref arg & ... | format.cpp:136:8:136:13 | buffer | |
| format.cpp:135:40:135:45 | buffer | format.cpp:135:39:135:45 | & ... | |
| stl.cpp:67:12:67:17 | call to source | stl.cpp:71:7:71:7 | a | |
| stl.cpp:68:16:68:20 | 123 | stl.cpp:68:16:68:21 | call to basic_string | TAINT |
| stl.cpp:68:16:68:21 | call to basic_string | stl.cpp:72:7:72:7 | b | |

View File

@@ -1,13 +1,13 @@
| format.cpp:53:8:53:13 | buffer | format.cpp:52:36:52:49 | call to source |
| format.cpp:58:8:58:13 | buffer | format.cpp:57:30:57:43 | call to source |
| format.cpp:63:8:63:13 | buffer | format.cpp:62:52:62:65 | call to source |
| format.cpp:68:8:68:13 | buffer | format.cpp:67:42:67:55 | call to source |
| format.cpp:79:8:79:13 | buffer | format.cpp:78:36:78:41 | call to source |
| format.cpp:84:8:84:13 | buffer | format.cpp:83:38:83:43 | call to source |
| format.cpp:90:8:90:13 | buffer | format.cpp:89:36:89:49 | call to source |
| format.cpp:96:8:96:13 | buffer | format.cpp:95:30:95:43 | call to source |
| format.cpp:101:8:101:13 | buffer | format.cpp:100:31:100:45 | call to source |
| format.cpp:106:8:106:14 | wbuffer | format.cpp:105:38:105:52 | call to source |
| format.cpp:57:8:57:13 | buffer | format.cpp:56:36:56:49 | call to source |
| format.cpp:62:8:62:13 | buffer | format.cpp:61:30:61:43 | call to source |
| format.cpp:67:8:67:13 | buffer | format.cpp:66:52:66:65 | call to source |
| format.cpp:72:8:72:13 | buffer | format.cpp:71:42:71:55 | call to source |
| format.cpp:83:8:83:13 | buffer | format.cpp:82:36:82:41 | call to source |
| format.cpp:88:8:88:13 | buffer | format.cpp:87:38:87:43 | call to source |
| format.cpp:94:8:94:13 | buffer | format.cpp:93:36:93:49 | call to source |
| format.cpp:100:8:100:13 | buffer | format.cpp:99:30:99:43 | call to source |
| format.cpp:105:8:105:13 | buffer | format.cpp:104:31:104:45 | call to source |
| format.cpp:110:8:110:14 | wbuffer | format.cpp:109:38:109:52 | call to source |
| stl.cpp:71:7:71:7 | a | stl.cpp:67:12:67:17 | call to source |
| stl.cpp:73:7:73:7 | c | stl.cpp:69:16:69:21 | call to source |
| stl.cpp:75:9:75:13 | call to c_str | stl.cpp:69:16:69:21 | call to source |

View File

@@ -1,13 +1,13 @@
| format.cpp:53:8:53:13 | format.cpp:52:36:52:49 | AST only |
| format.cpp:58:8:58:13 | format.cpp:57:30:57:43 | AST only |
| format.cpp:63:8:63:13 | format.cpp:62:52:62:65 | AST only |
| format.cpp:68:8:68:13 | format.cpp:67:42:67:55 | AST only |
| format.cpp:79:8:79:13 | format.cpp:78:36:78:41 | AST only |
| format.cpp:84:8:84:13 | format.cpp:83:38:83:43 | AST only |
| format.cpp:90:8:90:13 | format.cpp:89:36:89:49 | AST only |
| format.cpp:96:8:96:13 | format.cpp:95:30:95:43 | AST only |
| format.cpp:101:8:101:13 | format.cpp:100:31:100:45 | AST only |
| format.cpp:106:8:106:14 | format.cpp:105:38:105:52 | AST only |
| format.cpp:57:8:57:13 | format.cpp:56:36:56:49 | AST only |
| format.cpp:62:8:62:13 | format.cpp:61:30:61:43 | AST only |
| format.cpp:67:8:67:13 | format.cpp:66:52:66:65 | AST only |
| format.cpp:72:8:72:13 | format.cpp:71:42:71:55 | AST only |
| format.cpp:83:8:83:13 | format.cpp:82:36:82:41 | AST only |
| format.cpp:88:8:88:13 | format.cpp:87:38:87:43 | AST only |
| format.cpp:94:8:94:13 | format.cpp:93:36:93:49 | AST only |
| format.cpp:100:8:100:13 | format.cpp:99:30:99:43 | AST only |
| format.cpp:105:8:105:13 | format.cpp:104:31:104:45 | AST only |
| format.cpp:110:8:110:14 | format.cpp:109:38:109:52 | AST only |
| stl.cpp:73:7:73:7 | stl.cpp:69:16:69:21 | AST only |
| stl.cpp:75:9:75:13 | stl.cpp:69:16:69:21 | AST only |
| stl.cpp:125:13:125:17 | stl.cpp:117:10:117:15 | AST only |

View File

@@ -1,4 +1,4 @@
import default
import cpp
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.implementation.aliased_ssa.constant.ConstantAnalysis
import semmle.code.cpp.ir.internal.IntegerConstant

View File

@@ -1,4 +1,4 @@
import default
import cpp
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.AliasAnalysis
import semmle.code.cpp.ir.implementation.raw.IR
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -1,4 +1,4 @@
import default
import cpp
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.AliasAnalysis
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.AliasConfiguration
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR

View File

@@ -1,4 +1,4 @@
import default
import cpp
query predicate classUuids(Class cls, string uuid) {
if exists(cls.getUuid()) then uuid = cls.getUuid() else uuid = ""

View File

@@ -2,7 +2,7 @@ import cpp
class FunctionMonkeyPatch extends Function {
language[monotonicAggregates]
override string toString() {
override string getDescription() {
exists(string name, string templateArgs, string args |
result = name + templateArgs + args and
name = this.getQualifiedName() and
@@ -30,7 +30,9 @@ class FunctionMonkeyPatch extends Function {
}
class ParameterMonkeyPatch extends Parameter {
override string toString() { result = super.getType().getName() + " " + super.toString() }
override string getDescription() {
result = super.getType().getName() + " " + super.getDescription()
}
}
from Element e, Element ti

View File

@@ -1,7 +1,7 @@
| templates.cpp:9:5:9:14 | using c |
| usings.cpp:8:1:8:11 | using nf |
| usings.cpp:9:1:9:17 | using namespace N |
| usings.cpp:18:3:18:13 | using bf |
| usings.cpp:21:5:21:14 | using gf |
| usings.cpp:34:3:34:20 | using tbf |
| usings.cpp:42:5:42:22 | using foo |
| templates.cpp:9:5:9:14 | using c | UsingDeclarationEntry, enclosingElement:std |
| usings.cpp:8:1:8:11 | using nf | UsingDeclarationEntry, enclosingElement:(global namespace) |
| usings.cpp:9:1:9:17 | using namespace N | UsingDirectiveEntry, enclosingElement:(global namespace) |
| usings.cpp:18:3:18:13 | using bf | UsingDeclarationEntry, enclosingElement:D |
| usings.cpp:21:5:21:14 | using gf | UsingDeclarationEntry, enclosingElement:{ ... } |
| usings.cpp:34:3:34:20 | using tbf | UsingDeclarationEntry, enclosingElement:TD |
| usings.cpp:42:5:42:22 | using foo | UsingDeclarationEntry, enclosingElement:nsbar |

View File

@@ -1,4 +1,14 @@
import cpp
string describe(UsingEntry ue) {
ue instanceof UsingDeclarationEntry and
result = "UsingDeclarationEntry"
or
ue instanceof UsingDirectiveEntry and
result = "UsingDirectiveEntry"
or
result = "enclosingElement:" + ue.getEnclosingElement().toString()
}
from UsingEntry ue
select ue
select ue, concat(describe(ue), ", ")

View File

@@ -1,7 +0,0 @@
| templates.cpp:9:5:9:14 | using c | file://:0:0:0:0 | std |
| usings.cpp:8:1:8:11 | using nf | file://:0:0:0:0 | (global namespace) |
| usings.cpp:9:1:9:17 | using namespace N | file://:0:0:0:0 | (global namespace) |
| usings.cpp:18:3:18:13 | using bf | usings.cpp:16:8:16:8 | D |
| usings.cpp:21:5:21:14 | using gf | usings.cpp:20:13:23:3 | { ... } |
| usings.cpp:34:3:34:20 | using tbf | usings.cpp:32:8:32:9 | TD |
| usings.cpp:42:5:42:22 | using foo | usings.cpp:41:11:41:15 | nsbar |

View File

@@ -1,5 +0,0 @@
import cpp
from UsingEntry ue, Element e
where e = ue.getEnclosingElement()
select ue, e

View File

@@ -1,13 +1,4 @@
edges
| field_conflation.c:12:22:12:27 | call to getenv | field_conflation.c:13:3:13:18 | Chi |
| field_conflation.c:12:22:12:34 | (const char *)... | field_conflation.c:13:3:13:18 | Chi |
| field_conflation.c:13:3:13:18 | Chi | field_conflation.c:19:15:19:17 | taint_array output argument |
| field_conflation.c:19:15:19:17 | taint_array output argument | field_conflation.c:20:10:20:13 | (unsigned long)... |
| field_conflation.c:19:15:19:17 | taint_array output argument | field_conflation.c:20:13:20:13 | x |
| field_conflation.c:19:15:19:17 | taint_array output argument | field_conflation.c:20:13:20:13 | x |
| field_conflation.c:19:15:19:17 | taint_array output argument | field_conflation.c:20:13:20:13 | x |
| field_conflation.c:20:13:20:13 | x | field_conflation.c:20:10:20:13 | (unsigned long)... |
| field_conflation.c:20:13:20:13 | x | field_conflation.c:20:13:20:13 | x |
| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | (size_t)... |
| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | (size_t)... |
| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted |
@@ -68,16 +59,27 @@ edges
| test.cpp:227:24:227:37 | (const char *)... | test.cpp:237:10:237:19 | (size_t)... |
| test.cpp:235:11:235:20 | (size_t)... | test.cpp:214:23:214:23 | s |
| test.cpp:237:10:237:19 | (size_t)... | test.cpp:220:21:220:21 | s |
| test.cpp:241:2:241:32 | Chi | test.cpp:279:17:279:20 | get_size output argument |
| test.cpp:241:2:241:32 | Chi | test.cpp:295:18:295:21 | get_size output argument |
| test.cpp:241:18:241:23 | call to getenv | test.cpp:241:2:241:32 | Chi |
| test.cpp:241:18:241:31 | (const char *)... | test.cpp:241:2:241:32 | Chi |
| test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... |
| test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... |
| test.cpp:249:20:249:33 | (const char *)... | test.cpp:253:11:253:29 | ... * ... |
| test.cpp:249:20:249:33 | (const char *)... | test.cpp:253:11:253:29 | ... * ... |
| test.cpp:279:17:279:20 | get_size output argument | test.cpp:281:11:281:28 | ... * ... |
| test.cpp:279:17:279:20 | get_size output argument | test.cpp:281:11:281:28 | ... * ... |
| test.cpp:295:18:295:21 | get_size output argument | test.cpp:298:10:298:27 | ... * ... |
| test.cpp:295:18:295:21 | get_size output argument | test.cpp:298:10:298:27 | ... * ... |
| test.cpp:301:19:301:24 | call to getenv | test.cpp:305:11:305:28 | ... * ... |
| test.cpp:301:19:301:24 | call to getenv | test.cpp:305:11:305:28 | ... * ... |
| test.cpp:301:19:301:32 | (const char *)... | test.cpp:305:11:305:28 | ... * ... |
| test.cpp:301:19:301:32 | (const char *)... | test.cpp:305:11:305:28 | ... * ... |
| test.cpp:309:19:309:24 | call to getenv | test.cpp:314:10:314:27 | ... * ... |
| test.cpp:309:19:309:24 | call to getenv | test.cpp:314:10:314:27 | ... * ... |
| test.cpp:309:19:309:32 | (const char *)... | test.cpp:314:10:314:27 | ... * ... |
| test.cpp:309:19:309:32 | (const char *)... | test.cpp:314:10:314:27 | ... * ... |
nodes
| field_conflation.c:12:22:12:27 | call to getenv | semmle.label | call to getenv |
| field_conflation.c:12:22:12:34 | (const char *)... | semmle.label | (const char *)... |
| field_conflation.c:13:3:13:18 | Chi | semmle.label | Chi |
| field_conflation.c:19:15:19:17 | taint_array output argument | semmle.label | taint_array output argument |
| field_conflation.c:20:10:20:13 | (unsigned long)... | semmle.label | (unsigned long)... |
| field_conflation.c:20:10:20:13 | (unsigned long)... | semmle.label | (unsigned long)... |
| field_conflation.c:20:13:20:13 | x | semmle.label | x |
| field_conflation.c:20:13:20:13 | x | semmle.label | x |
| field_conflation.c:20:13:20:13 | x | semmle.label | x |
| test.cpp:39:21:39:24 | argv | semmle.label | argv |
| test.cpp:39:21:39:24 | argv | semmle.label | argv |
| test.cpp:42:38:42:44 | (size_t)... | semmle.label | (size_t)... |
@@ -140,8 +142,33 @@ nodes
| test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size |
| test.cpp:235:11:235:20 | (size_t)... | semmle.label | (size_t)... |
| test.cpp:237:10:237:19 | (size_t)... | semmle.label | (size_t)... |
| test.cpp:241:2:241:32 | Chi | semmle.label | Chi |
| test.cpp:241:18:241:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:241:18:241:31 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:249:20:249:25 | call to getenv | semmle.label | call to getenv |
| test.cpp:249:20:249:33 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... |
| test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... |
| test.cpp:253:11:253:29 | ... * ... | semmle.label | ... * ... |
| test.cpp:279:17:279:20 | get_size output argument | semmle.label | get_size output argument |
| test.cpp:281:11:281:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:281:11:281:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:281:11:281:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:295:18:295:21 | get_size output argument | semmle.label | get_size output argument |
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:298:10:298:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:301:19:301:24 | call to getenv | semmle.label | call to getenv |
| test.cpp:301:19:301:32 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:305:11:305:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:305:11:305:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:305:11:305:28 | ... * ... | semmle.label | ... * ... |
| test.cpp:309:19:309:24 | call to getenv | semmle.label | call to getenv |
| test.cpp:309:19:309:32 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:314:10:314:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:314:10:314:27 | ... * ... | semmle.label | ... * ... |
| test.cpp:314:10:314:27 | ... * ... | semmle.label | ... * ... |
#select
| field_conflation.c:20:3:20:8 | call to malloc | field_conflation.c:12:22:12:27 | call to getenv | field_conflation.c:20:13:20:13 | x | This allocation size is derived from $@ and might overflow | field_conflation.c:12:22:12:27 | call to getenv | user input (getenv) |
| test.cpp:42:31:42:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:45:31:45:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
@@ -155,3 +182,8 @@ nodes
| test.cpp:221:14:221:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:221:21:221:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) |
| test.cpp:229:2:229:7 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) |
| test.cpp:231:2:231:7 | call to malloc | test.cpp:201:14:201:19 | call to getenv | test.cpp:231:9:231:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow | test.cpp:201:14:201:19 | call to getenv | user input (getenv) |
| test.cpp:253:4:253:9 | call to malloc | test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:249:20:249:25 | call to getenv | user input (getenv) |
| test.cpp:281:4:281:9 | call to malloc | test.cpp:241:18:241:23 | call to getenv | test.cpp:281:11:281:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:241:18:241:23 | call to getenv | user input (getenv) |
| test.cpp:298:3:298:8 | call to malloc | test.cpp:241:18:241:23 | call to getenv | test.cpp:298:10:298:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:241:18:241:23 | call to getenv | user input (getenv) |
| test.cpp:305:4:305:9 | call to malloc | test.cpp:301:19:301:24 | call to getenv | test.cpp:305:11:305:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:301:19:301:24 | call to getenv | user input (getenv) |
| test.cpp:314:3:314:8 | call to malloc | test.cpp:309:19:309:24 | call to getenv | test.cpp:314:10:314:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:309:19:309:24 | call to getenv | user input (getenv) |

View File

@@ -17,5 +17,5 @@ void test_conflated_fields3(void) {
struct XY xy;
xy.x = 4;
taint_array(&xy);
malloc(xy.x); // not tainted [FALSE POSITIVE]
malloc(xy.x); // not tainted
}

View File

@@ -236,3 +236,81 @@ void more_cases() {
my_func(100); // GOOD
my_func(local_size); // GOOD
}
bool get_size(int &out_size) {
out_size = atoi(getenv("USER"));
return true;
}
void equality_cases() {
{
int size1 = atoi(getenv("USER"));
int size2 = atoi(getenv("USER"));
if (size1 == 100)
{
malloc(size2 * sizeof(int)); // BAD
}
if (size2 == 100)
{
malloc(size2 * sizeof(int)); // GOOD
}
}
{
int size = atoi(getenv("USER"));
if (size != 100)
return;
malloc(size * sizeof(int)); // GOOD
}
{
int size;
if ((get_size(size)) && (size == 100))
{
malloc(size * sizeof(int)); // GOOD
}
}
{
int size;
if ((get_size(size)) && (size != 100))
{
malloc(size * sizeof(int)); // BAD
}
}
{
int size;
if ((!get_size(size)) || (size != 100))
return;
malloc(size * sizeof(int)); // GOOD
}
{
int size;
if ((!get_size(size)) || (size == 100))
return;
malloc(size * sizeof(int)); // BAD
}
{
int size = atoi(getenv("USER"));
if ((size == 50) || (size == 100))
{
malloc(size * sizeof(int)); // GOOD [FALSE POSITIVE]
}
}
{
int size = atoi(getenv("USER"));
if (size != 50 && size != 100)
return;
malloc(size * sizeof(int)); // GOOD [FALSE POSITIVE]
}
}

View File

@@ -5,5 +5,4 @@
| test.c:63:3:63:5 | sc8 | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:62:9:62:16 | - ... | Extreme value |
| test.c:75:3:75:5 | sc1 | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:74:9:74:16 | 127 | Extreme value |
| test.c:76:3:76:5 | sc1 | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:74:9:74:16 | 127 | Extreme value |
| test.c:114:9:114:9 | x | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:108:17:108:23 | 2147483647 | Extreme value |
| test.c:124:9:124:9 | x | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:118:17:118:23 | 2147483647 | Extreme value |

View File

@@ -111,7 +111,7 @@ void test_guards3(int cond) {
if (x != 0) return;
return x + 1; // GOOD [FALSE POSITIVE]
return x + 1; // GOOD
}
void test_guards4(int cond) {

View File

@@ -1160,26 +1160,6 @@ class UsingStmt extends Stmt, @using_stmt {
* ```
*/
Expr getAnExpr() { none() }
/**
* DEPRECATED: Use UsingBlockStmt.getExpr() instead.
* Gets the expression directly used by this `using` statement, if any. For
* example, `f` on line 2 in
*
* ```
* var f = File.Open("settings.xml");
* using (f) {
* ...
* }
* ```
*/
deprecated Expr getExpr() { none() }
/**
* DEPRECATED: Use UsingBlockStmt.getBody() instead.
* Gets the body of this `using` statement.
*/
deprecated Stmt getBody() { none() }
}
/**
@@ -1212,7 +1192,7 @@ class UsingBlockStmt extends UsingStmt, @using_block_stmt {
* }
* ```
*/
override Expr getExpr() { result = this.getChild(0) }
Expr getExpr() { result = this.getChild(0) }
override Expr getAnExpr() {
result = this.getAVariableDeclExpr().getInitializer()
@@ -1221,7 +1201,7 @@ class UsingBlockStmt extends UsingStmt, @using_block_stmt {
}
/** Gets the body of this `using` statement. */
override Stmt getBody() { result.getParent() = this }
Stmt getBody() { result.getParent() = this }
override string toString() { result = "using (...) {...}" }
}

View File

@@ -474,7 +474,8 @@ module Gvn {
sourceDecl = any(GenericType t).getSourceDeclaration() and
not sourceDecl instanceof PointerType and
not sourceDecl instanceof NullableType and
not sourceDecl instanceof ArrayType
not sourceDecl instanceof ArrayType and
not sourceDecl instanceof TupleType
}
cached

View File

@@ -116,7 +116,7 @@ class XMLFile extends XMLParent, File {
XMLFile() { xmlEncoding(this, _) }
/** Gets a printable representation of this XML file. */
override string toString() { result = XMLParent.super.toString() }
override string toString() { result = getName() }
/** Gets the name of this XML file. */
override string getName() { result = File.super.getAbsolutePath() }
@@ -236,7 +236,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
/** Gets a printable representation of this XML element. */
override string toString() { result = XMLParent.super.toString() }
override string toString() { result = getName() }
}
/**

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -79,13 +79,6 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintBarrier(node)
}
/** DEPRECATED: override `isSanitizerIn` and `isSanitizerOut` instead. */
deprecated predicate isSanitizerEdge(DataFlow::Node node1, DataFlow::Node node2) { none() }
deprecated final override predicate isBarrierEdge(DataFlow::Node node1, DataFlow::Node node2) {
isSanitizerEdge(node1, node2)
}
/** Holds if data flow into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }

View File

@@ -79,13 +79,6 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintBarrier(node)
}
/** DEPRECATED: override `isSanitizerIn` and `isSanitizerOut` instead. */
deprecated predicate isSanitizerEdge(DataFlow::Node node1, DataFlow::Node node2) { none() }
deprecated final override predicate isBarrierEdge(DataFlow::Node node1, DataFlow::Node node2) {
isSanitizerEdge(node1, node2)
}
/** Holds if data flow into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }

View File

@@ -79,13 +79,6 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintBarrier(node)
}
/** DEPRECATED: override `isSanitizerIn` and `isSanitizerOut` instead. */
deprecated predicate isSanitizerEdge(DataFlow::Node node1, DataFlow::Node node2) { none() }
deprecated final override predicate isBarrierEdge(DataFlow::Node node1, DataFlow::Node node2) {
isSanitizerEdge(node1, node2)
}
/** Holds if data flow into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }

View File

@@ -79,13 +79,6 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintBarrier(node)
}
/** DEPRECATED: override `isSanitizerIn` and `isSanitizerOut` instead. */
deprecated predicate isSanitizerEdge(DataFlow::Node node1, DataFlow::Node node2) { none() }
deprecated final override predicate isBarrierEdge(DataFlow::Node node1, DataFlow::Node node2) {
isSanitizerEdge(node1, node2)
}
/** Holds if data flow into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }

View File

@@ -79,13 +79,6 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintBarrier(node)
}
/** DEPRECATED: override `isSanitizerIn` and `isSanitizerOut` instead. */
deprecated predicate isSanitizerEdge(DataFlow::Node node1, DataFlow::Node node2) { none() }
deprecated final override predicate isBarrierEdge(DataFlow::Node node1, DataFlow::Node node2) {
isSanitizerEdge(node1, node2)
}
/** Holds if data flow into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }

View File

@@ -0,0 +1,17 @@
public boolean shouldOverrideUrlLoading(WebView view, String url) {
{
Uri uri = Uri.parse(url);
// BAD: partial domain match, which allows an attacker to register a domain like myexample.com to circumvent the verification
if (uri.getHost() != null && uri.getHost().endsWith("example.com")) {
return false;
}
}
{
Uri uri = Uri.parse(url);
// GOOD: full domain match
if (uri.getHost() != null && uri.getHost().endsWith(".example.com")) {
return false;
}
}
}

View File

@@ -0,0 +1,28 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Apps that rely on URL Parsing to verify that a given URL is pointing to a trust server may be susceptible to many different ways to get URL parsing and verification wrong, which allows an attacker to register a fake site to break the access control.</p>
</overview>
<recommendation>
<p>Verify the whole host and domain (FQDN) or check endsWith dot+domain.</p>
</recommendation>
<example>
<p>The following example shows two ways of verifying host domain. In the 'BAD' case,
verification is implemented as partial domain match. In the 'GOOD' case, full domain is verified.</p>
<sample src="IncorrectURLVerification.java" />
</example>
<references>
<li>
<a href="https://drive.google.com/file/d/0BwMN49Gzo3x6T1N5WGQ4TTNlMHBOb1ZRQTVEWnVBZjFUaE5N/view">Common Android app vulnerabilities from Sebastian Porst of Google</a>
</li>
<li>
<a href="https://www.bugcrowd.com/resources/webinars/overview-of-common-android-app-vulnerabilities/">Common Android app vulnerabilities from bugcrowd</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,97 @@
/**
* @id java/incorrect-url-verification
* @name Incorrect URL verification
* @description Apps that rely on URL parsing to verify that a given URL is pointing to a trusted server are susceptible to wrong ways of URL parsing and verification.
* @kind problem
* @tags security
* external/cwe-939
*/
import java
/**
* The Java class `android.R.string` specific to Android applications, which contains references to application specific resources defined in /res/values/strings.xml.
* For example, <resources>...<string name="host">example.com</string>...</resources> in the application com.example.android.web can be referred as R.string.host with the type com.example.android.web.R$string
*/
class AndroidRString extends RefType {
AndroidRString() { this.hasQualifiedName(_, "R$string") }
}
/**
* The Java class `android.net.Uri` and `java.net.URL`.
*/
class Uri extends RefType {
Uri() {
hasQualifiedName("android.net", "Uri") or
hasQualifiedName("java.net", "URL")
}
}
/**
* The method `getHost()` declared in `android.net.Uri` and `java.net.URL`.
*/
class UriGetHostMethod extends Method {
UriGetHostMethod() {
getDeclaringType() instanceof Uri and
hasName("getHost") and
getNumberOfParameters() = 0
}
}
/**
* The method access with incorrect string comparision
*/
class HostVerificationMethodAccess extends MethodAccess {
HostVerificationMethodAccess() {
(
this.getMethod().hasName("endsWith") or
this.getMethod().hasName("contains") or
this.getMethod().hasName("indexOf")
) and
this.getMethod().getNumberOfParameters() = 1 and
(
this.getArgument(0).(StringLiteral).getRepresentedString().charAt(0) != "." //string constant comparison e.g. uri.getHost().endsWith("example.com")
or
this
.getArgument(0)
.(AddExpr)
.getLeftOperand()
.(VarAccess)
.getVariable()
.getAnAssignedValue()
.(StringLiteral)
.getRepresentedString()
.charAt(0) != "." //var1+var2, check var1 starts with "." e.g. String domainName = "example"; Uri.parse(url).getHost().endsWith(domainName+".com")
or
this
.getArgument(0)
.(AddExpr)
.getLeftOperand()
.(StringLiteral)
.getRepresentedString()
.charAt(0) != "." //"."+var2, check string constant "." e.g. String domainName = "example.com"; Uri.parse(url).getHost().endsWith("www."+domainName)
or
exists(MethodAccess ma, Method m, Field f |
this.getArgument(0) = ma and
ma.getMethod() = m and
m.hasName("getString") and
m.getDeclaringType().getQualifiedName() = "android.content.res.Resources" and
ma.getArgument(0).(FieldRead).getField() = f and
f.getDeclaringType() instanceof AndroidRString
) //Check resource properties in /res/values/strings.xml in Android mobile applications using res.getString(R.string.key)
or
this
.getArgument(0)
.(VarAccess)
.getVariable()
.getAnAssignedValue()
.(StringLiteral)
.getRepresentedString()
.charAt(0) != "." //check variable starts with "." e.g. String domainName = "example.com"; Uri.parse(url).getHost().endsWith(domainName)
)
}
}
from UriGetHostMethod um, MethodAccess uma, HostVerificationMethodAccess hma
where hma.getQualifier() = uma and uma.getMethod() = um
select hma, "Method has potentially $@ ", hma.getArgument(0), "improper URL verification"

View File

@@ -22,8 +22,7 @@ class TypeAuthorizedUrl extends Class {
}
/**
* The class
* `org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry`.
* The class `org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry`.
*/
class TypeAbstractRequestMatcherRegistry extends Class {
TypeAbstractRequestMatcherRegistry() {
@@ -34,38 +33,44 @@ class TypeAbstractRequestMatcherRegistry extends Class {
}
/**
* The class
* `org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest.EndpointRequestMatcher`.
* The class `org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest`.
*/
class TypeEndpointRequestMatcher extends Class {
TypeEndpointRequestMatcher() {
class TypeEndpointRequest extends Class {
TypeEndpointRequest() {
this
.hasQualifiedName("org.springframework.boot.actuate.autoconfigure.security.servlet",
"EndpointRequest$EndpointRequestMatcher")
"EndpointRequest")
}
}
/** A call to `EndpointRequest.toAnyEndpoint` method. */
class ToAnyEndpointCall extends MethodAccess {
ToAnyEndpointCall() {
getMethod().hasName("toAnyEndpoint") and
getMethod().getDeclaringType() instanceof TypeEndpointRequest
}
}
/**
* A call to `HttpSecurity.requestMatcher` method with argument of type
* `EndpointRequestMatcher`.
* A call to `HttpSecurity.requestMatcher` method with argument `RequestMatcher.toAnyEndpoint()`.
*/
class RequestMatcherCall extends MethodAccess {
RequestMatcherCall() {
getMethod().hasName("requestMatcher") and
getMethod().getDeclaringType() instanceof TypeHttpSecurity and
getArgument(0).getType() instanceof TypeEndpointRequestMatcher
getArgument(0) instanceof ToAnyEndpointCall
}
}
/**
* A call to `HttpSecurity.requestMatchers` method with lambda argument resolving to
* `EndpointRequestMatcher` type.
* A call to `HttpSecurity.requestMatchers` method with lambda argument
* `RequestMatcher.toAnyEndpoint()`.
*/
class RequestMatchersCall extends MethodAccess {
RequestMatchersCall() {
getMethod().hasName("requestMatchers") and
getMethod().getDeclaringType() instanceof TypeHttpSecurity and
getArgument(0).(LambdaExpr).getExprBody().getType() instanceof TypeEndpointRequestMatcher
getArgument(0).(LambdaExpr).getExprBody() instanceof ToAnyEndpointCall
}
}
@@ -92,9 +97,6 @@ class PermitAllCall extends MethodAccess {
or
// .requestMatchers(matcher -> EndpointRequest).authorizeRequests([...]).[...]
authorizeRequestsCall.getQualifier() instanceof RequestMatchersCall
or
// http.authorizeRequests([...]).[...]
authorizeRequestsCall.getQualifier() instanceof VarAccess
|
// [...].authorizeRequests(r -> r.anyRequest().permitAll()) or
// [...].authorizeRequests(r -> r.requestMatchers(EndpointRequest).permitAll())
@@ -117,6 +119,22 @@ class PermitAllCall extends MethodAccess {
this.getQualifier() = anyRequestCall
)
)
or
exists(AuthorizeRequestsCall authorizeRequestsCall |
// http.authorizeRequests([...]).[...]
authorizeRequestsCall.getQualifier() instanceof VarAccess
|
// [...].authorizeRequests(r -> r.requestMatchers(EndpointRequest).permitAll())
authorizeRequestsCall.getArgument(0).(LambdaExpr).getExprBody() = this and
this.getQualifier() instanceof RegistryRequestMatchersCall
or
// [...].authorizeRequests().requestMatchers(EndpointRequest).permitAll() or
authorizeRequestsCall.getNumArgument() = 0 and
exists(RegistryRequestMatchersCall registryRequestMatchersCall |
registryRequestMatchersCall.getQualifier() = authorizeRequestsCall and
this.getQualifier() = registryRequestMatchersCall
)
)
}
}
@@ -129,13 +147,13 @@ class AnyRequestCall extends MethodAccess {
}
/**
* A call to `AbstractRequestMatcherRegistry.requestMatchers` method with an argument of type
* `EndpointRequestMatcher`.
* A call to `AbstractRequestMatcherRegistry.requestMatchers` method with an argument
* `RequestMatcher.toAnyEndpoint()`.
*/
class RegistryRequestMatchersCall extends MethodAccess {
RegistryRequestMatchersCall() {
getMethod().hasName("requestMatchers") and
getMethod().getDeclaringType() instanceof TypeAbstractRequestMatcherRegistry and
getAnArgument().getType() instanceof TypeEndpointRequestMatcher
getAnArgument() instanceof ToAnyEndpointCall
}
}

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

View File

@@ -66,9 +66,6 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
/** DEPRECATED: override `isBarrierIn` and `isBarrierOut` instead. */
deprecated predicate isBarrierEdge(Node node1, Node node2) { none() }
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }

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