Merge branch 'master' into connect-ir-dataflow-models

This commit is contained in:
Robert Marsh
2020-01-30 08:49:42 -08:00
518 changed files with 9580 additions and 2591 deletions

View File

@@ -0,0 +1,285 @@
/**
* Provides a library for writing QL tests whose success or failure is based on expected results
* embedded in the test source code as comments, rather than a `.expected` file.
*
* To create a new inline expectations test:
* - Declare a class that extends `InlineExpectationsTest`. In the characteristic predicate of the
* new class, bind `this` to a unique string (usually the name of the test).
* - Override the `hasActualResult()` predicate to produce the actual results of the query. For each
* result, specify a `Location`, a text description of the element for which the result was
* reported, a short string to serve as the tag to identify expected results for this test, and the
* expected value of the result.
* - Override `getARelevantTag()` to return the set of tags that can be produced by
* `hasActualResult()`. Often this is just a single tag.
*
* Example:
* ```
* class ConstantValueTest extends InlineExpectationsTest {
* ConstantValueTest() { this = "ConstantValueTest" }
*
* override string getARelevantTag() {
* // We only use one tag for this test.
* result = "const"
* }
*
* override predicate hasActualResult(
* Location location, string element, string tag, string valuesasas
* ) {
* exists(Expr e |
* tag = "const" and // The tag for this test.
* valuesasas = e.getValue() and // The expected value. Will only hold for constant expressions.
* location = e.getLocation() and // The location of the result to be reported.
* element = e.toString() // The display text for the result.
* )
* }
* }
* ```
*
* There is no need to write a `select` clause or query predicate. All of the differences between
* expected results and actual results will be reported in the `failures()` query predicate.
*
* To annotate the test source code with an expected result, place a C++-style (`//`) comment on the
* same line as the expected result, with text of the following format as the body of the comment:
*
* `// $tag=expected-value`
*
* Where `tag` is the value of the `tag` parameter from `hasActualResult()`, and `expected-value` is
* the value of the `value` parameter from `hasActualResult()`. The `=expected-value` portion may be
* omitted, in which case `expected-value` is treated as the empty string. Multiple expectations may
* be placed in the same comment, as long as each is prefixed by a `$`. Any actual result that
* appears on a line that does not contain a matching expected result comment will be reported with
* a message of the form "Unexpected result: tag=value". Any expected result comment for which there
* is no matching actual result will be reported with a message of the form
* "Missing result: tag=expected-value".
*
* Example:
* ```
* int i = x + 5; // $const=5
* int j = y + (7 - 3) // $const=7 $const=3 $const=4 // The result of the subtraction is a constant.
* ```
*
* For tests that contain known false positives and false negatives, it is possible to further
* annotate that a particular expected result is known to be a false positive, or that a particular
* missing result is known to be a false negative:
*
* `// $f+:tag=expected-value` // False positive
* `// $f-:tag=expected-value` // False negative
*
* A false positive expectation is treated as any other expected result, except that if there is no
* matching actual result, the message will be of the form "Fixed false positive: tag=value". A
* false negative expectation is treated as if there were no expected result, except that if a
* matching expected result is found, the message will be of the form
* "Fixed false negative: tag=value".
*
* If the same result value is expected for two or more tags on the same line, there is a shorthand
* notation available:
*
* `// $tag1,tag2=expected-value`
*
* is equivalent to:
*
* `// $tag1=expected-value $tag2=expected-value`
*/
import cpp
/**
* Base class for tests with inline expectations. The test extends this class to provide the actual
* results of the query, which are then compared with the expected results in comments to produce a
* list of failure messages that point out where the actual results differ from the expected
* results.
*/
abstract class InlineExpectationsTest extends string {
bindingset[this]
InlineExpectationsTest() { any() }
/**
* Returns all tags that can be generated by this test. Most tests will only ever produce a single
* tag. Any expected result comments for a tag that is not returned by the `getARelevantTag()`
* predicate for an active test will be ignored. This makes it possible to write multiple tests in
* different `.ql` files that all query the same source code.
*/
abstract string getARelevantTag();
/**
* Returns the actual results of the query that is being tested. Each result consist of the
* following values:
* - `location` - The source code location of the result. Any expected result comment must appear
* on the start line of this location.
* - `element` - Display text for the element on which the result is reported.
* - `tag` - The tag that marks this result as coming from this test. This must be one of the tags
* returned by `getARelevantTag()`.
* - `value` - The value of the result, which will be matched against the value associated with
* `tag` in any expected result comment on that line.
*/
abstract predicate hasActualResult(Location location, string element, string tag, string value);
final predicate hasFailureMessage(FailureLocatable element, string message) {
exists(ActualResult actualResult |
actualResult.getTest() = this and
element = actualResult and
(
exists(FalseNegativeExpectation falseNegative |
falseNegative.matchesActualResult(actualResult) and
message = "Fixed false negative:" + falseNegative.getExpectationText()
)
or
not exists(ValidExpectation expectation | expectation.matchesActualResult(actualResult)) and
message = "Unexpected result: " + actualResult.getExpectationText()
)
)
or
exists(ValidExpectation expectation |
not exists(ActualResult actualResult | expectation.matchesActualResult(actualResult)) and
expectation.getTag() = getARelevantTag() and
element = expectation and
(
expectation instanceof GoodExpectation and
message = "Missing result:" + expectation.getExpectationText()
or
expectation instanceof FalsePositiveExpectation and
message = "Fixed false positive:" + expectation.getExpectationText()
)
)
or
exists(InvalidExpectation expectation |
element = expectation and
message = "Invalid expectation syntax: " + expectation.getExpectation()
)
}
}
/**
* RegEx pattern to match a comment containing one or more expected results. The comment must be a
* C++-style (`//`) comment with `$` as its first non-whitespace character. Any subsequent character
* is treated as part of the expected results, except that the comment may contain a `//` sequence
* to treat the remainder of the line as a regular (non-interpreted) comment.
*/
private string expectationCommentPattern() { result = "//\\s*(\\$(?:[^/]|/[^/])*)(?://.*)?" }
/**
* RegEx pattern to match a single expected result, not including the leading `$`. It starts with an
* optional `f+:` or `f-:`, followed by one or more comma-separated tags containing only letters,
* `-`, and `_`, optionally followed by `=` and the expected value.
*/
private string expectationPattern() {
result = "(?:(f(?:\\+|-)):)?((?:[A-Za-z-_]+)(?:\\s*,\\s*[A-Za-z-_]+)*)(?:=(.*))?"
}
private string getAnExpectation(CppStyleComment comment) {
result = comment.getContents().regexpCapture(expectationCommentPattern(), 1).splitAt("$").trim() and
result != ""
}
private newtype TFailureLocatable =
TActualResult(
InlineExpectationsTest test, Location location, string element, string tag, string value
) {
test.hasActualResult(location, element, tag, value)
} or
TValidExpectation(CppStyleComment comment, string tag, string value, string knownFailure) {
exists(string expectation |
expectation = getAnExpectation(comment) and
expectation.regexpMatch(expectationPattern()) and
tag = expectation.regexpCapture(expectationPattern(), 2).splitAt(",").trim() and
(
if exists(expectation.regexpCapture(expectationPattern(), 3))
then value = expectation.regexpCapture(expectationPattern(), 3)
else value = ""
) and
(
if exists(expectation.regexpCapture(expectationPattern(), 1))
then knownFailure = expectation.regexpCapture(expectationPattern(), 1)
else knownFailure = ""
)
)
} or
TInvalidExpectation(CppStyleComment comment, string expectation) {
expectation = getAnExpectation(comment) and
not expectation.regexpMatch(expectationPattern())
}
class FailureLocatable extends TFailureLocatable {
string toString() { none() }
Location getLocation() { none() }
final string getExpectationText() { result = getTag() + "=" + getValue() }
string getTag() { none() }
string getValue() { none() }
}
class ActualResult extends FailureLocatable, TActualResult {
InlineExpectationsTest test;
Location location;
string element;
string tag;
string value;
ActualResult() { this = TActualResult(test, location, element, tag, value) }
override string toString() { result = element }
override Location getLocation() { result = location }
InlineExpectationsTest getTest() { result = test }
override string getTag() { result = tag }
override string getValue() { result = value }
}
abstract private class Expectation extends FailureLocatable {
CppStyleComment comment;
override string toString() { result = comment.toString() }
override Location getLocation() { result = comment.getLocation() }
}
private class ValidExpectation extends Expectation, TValidExpectation {
string tag;
string value;
string knownFailure;
ValidExpectation() { this = TValidExpectation(comment, tag, value, knownFailure) }
override string getTag() { result = tag }
override string getValue() { result = value }
string getKnownFailure() { result = knownFailure }
predicate matchesActualResult(ActualResult actualResult) {
getLocation().getStartLine() = actualResult.getLocation().getStartLine() and
getLocation().getFile() = actualResult.getLocation().getFile() and
getTag() = actualResult.getTag() and
getValue() = actualResult.getValue()
}
}
class GoodExpectation extends ValidExpectation {
GoodExpectation() { getKnownFailure() = "" }
}
class FalsePositiveExpectation extends ValidExpectation {
FalsePositiveExpectation() { getKnownFailure() = "f+" }
}
class FalseNegativeExpectation extends ValidExpectation {
FalseNegativeExpectation() { getKnownFailure() = "f-" }
}
class InvalidExpectation extends Expectation, TInvalidExpectation {
string expectation;
InvalidExpectation() { this = TInvalidExpectation(comment, expectation) }
string getExpectation() { result = expectation }
}
query predicate failures(FailureLocatable element, string message) {
exists(InlineExpectationsTest test | test.hasFailureMessage(element, message))
}

View File

@@ -3,12 +3,14 @@ import cpp
string describe(Element e) {
result = "function " + e.(Function).getFullSignature()
or
result = "function declaration entry for " +
result =
"function declaration entry for " +
e.(FunctionDeclarationEntry).getFunction().getFullSignature()
or
result = "parameter for " + e.(Parameter).getFunction().getFullSignature()
or
result = "parameter declaration entry for " +
result =
"parameter declaration entry for " +
e.(ParameterDeclarationEntry).getFunctionDeclarationEntry().getFunction().getFullSignature()
}

View File

@@ -4,7 +4,8 @@ from Compilation c, int i, string s
// Skip the extractor name; it'll vary depending on platform
where
i > 0 and
s = c
s =
c
.getArgument(i)
.replaceAll("\\", "/")
.regexpReplaceAll(".*(/qltest/predefined_macros)", "<tools>$1")

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -64,7 +64,8 @@ query predicate irGuardsCompare(int startLine, string msg) {
guard.comparesEq(left, right, k, false, sense) and op = " != "
) and
startLine = guard.getLocation().getStartLine() and
msg = left.getAnyDef().getUnconvertedResultExpression() + op +
msg =
left.getAnyDef().getUnconvertedResultExpression() + op +
right.getAnyDef().getUnconvertedResultExpression() + "+" + k + " when " + guard + " is " +
which
)

View File

@@ -21,8 +21,8 @@ int main(int argc, char *argv[]) {
char buf[100] = "VAR = ";
sink(strcat(buf, getenv("VAR")));
sink(buf); // BUG: no taint
sink(untainted_buf); // the two buffers would be conflated if we added flow through partial chi inputs
sink(buf);
sink(untainted_buf); // the two buffers would be conflated if we added flow through all partial chi inputs
return 0;
}
@@ -39,3 +39,42 @@ void test_indirect_arg_to_model() {
inet_addr_retval a = inet_addr((const char *)&env_pointer);
sink(a);
}
class B {
public:
virtual void f(const char*) = 0;
};
class D1 : public B {};
class D2 : public D1 {
public:
void f(const char* p) override {}
};
class D3 : public D2 {
public:
void f(const char* p) override {
sink(p);
}
};
void test_dynamic_cast() {
B* b = new D3();
b->f(getenv("VAR")); // tainted
((D2*)b)->f(getenv("VAR")); // tainted
static_cast<D2*>(b)->f(getenv("VAR")); // tainted
dynamic_cast<D2*>(b)->f(getenv("VAR")); // tainted
reinterpret_cast<D2*>(b)->f(getenv("VAR")); // tainted
B* b2 = new D2();
b2->f(getenv("VAR"));
((D2*)b2)->f(getenv("VAR"));
static_cast<D2*>(b2)->f(getenv("VAR"));
dynamic_cast<D2*>(b2)->f(getenv("VAR"));
reinterpret_cast<D2*>(b2)->f(getenv("VAR"));
dynamic_cast<D3*>(b2)->f(getenv("VAR")); // tainted [FALSE POSITIVE]
}

View File

@@ -4,12 +4,14 @@
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:8:16:29 | (const char *)... |
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:16:16:21 | call to getenv |
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:16:16:28 | (const char *)... |
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:5:14:5:23 | p#0 |
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:17:8:17:13 | call to strdup |
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:17:8:17:28 | (const char *)... |
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:17:15:17:20 | call to getenv |
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | defaulttainttracking.cpp:17:15:17:27 | (const char *)... |
| defaulttainttracking.cpp:17:15:17:20 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
| defaulttainttracking.cpp:18:27:18:32 | call to getenv | defaulttainttracking.cpp:7:26:7:35 | p#0 |
| defaulttainttracking.cpp:18:27:18:32 | call to getenv | defaulttainttracking.cpp:18:27:18:32 | call to getenv |
| defaulttainttracking.cpp:18:27:18:32 | call to getenv | defaulttainttracking.cpp:18:27:18:39 | (const char *)... |
@@ -19,6 +21,8 @@
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:8:22:33 | (const char *)... |
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:20:22:25 | call to getenv |
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:20:22:32 | (const char *)... |
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:24:8:24:10 | buf |
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:32:11:32:26 | p#0 |
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:38:11:38:21 | env_pointer |
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:38:25:38:30 | call to getenv |
@@ -27,3 +31,162 @@
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:26:39:34 | call to inet_addr |
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:50:39:61 | & ... |
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:40:10:40:10 | a |
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:45:20:45:29 | p#0 |
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:57:24:57:24 | p |
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:58:14:58:14 | p |
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:64:10:64:15 | call to getenv |
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:64:10:64:22 | (const char *)... |
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | defaulttainttracking.cpp:57:24:57:24 | p |
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | defaulttainttracking.cpp:58:14:58:14 | p |
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | defaulttainttracking.cpp:66:17:66:22 | call to getenv |
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | defaulttainttracking.cpp:66:17:66:29 | (const char *)... |
| defaulttainttracking.cpp:66:17:66:22 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | defaulttainttracking.cpp:57:24:57:24 | p |
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | defaulttainttracking.cpp:58:14:58:14 | p |
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | defaulttainttracking.cpp:67:28:67:33 | call to getenv |
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | defaulttainttracking.cpp:67:28:67:40 | (const char *)... |
| defaulttainttracking.cpp:67:28:67:33 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | defaulttainttracking.cpp:57:24:57:24 | p |
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | defaulttainttracking.cpp:58:14:58:14 | p |
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | defaulttainttracking.cpp:68:29:68:34 | call to getenv |
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | defaulttainttracking.cpp:68:29:68:41 | (const char *)... |
| defaulttainttracking.cpp:68:29:68:34 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | defaulttainttracking.cpp:57:24:57:24 | p |
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | defaulttainttracking.cpp:58:14:58:14 | p |
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | defaulttainttracking.cpp:69:33:69:38 | call to getenv |
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | defaulttainttracking.cpp:69:33:69:45 | (const char *)... |
| defaulttainttracking.cpp:69:33:69:38 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
| defaulttainttracking.cpp:72:11:72:16 | call to getenv | defaulttainttracking.cpp:45:20:45:29 | p#0 |
| defaulttainttracking.cpp:72:11:72:16 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
| defaulttainttracking.cpp:72:11:72:16 | call to getenv | defaulttainttracking.cpp:72:11:72:16 | call to getenv |
| defaulttainttracking.cpp:72:11:72:16 | call to getenv | defaulttainttracking.cpp:72:11:72:23 | (const char *)... |
| defaulttainttracking.cpp:74:18:74:23 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
| defaulttainttracking.cpp:74:18:74:23 | call to getenv | defaulttainttracking.cpp:74:18:74:23 | call to getenv |
| defaulttainttracking.cpp:74:18:74:23 | call to getenv | defaulttainttracking.cpp:74:18:74:30 | (const char *)... |
| defaulttainttracking.cpp:75:29:75:34 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
| defaulttainttracking.cpp:75:29:75:34 | call to getenv | defaulttainttracking.cpp:75:29:75:34 | call to getenv |
| defaulttainttracking.cpp:75:29:75:34 | call to getenv | defaulttainttracking.cpp:75:29:75:41 | (const char *)... |
| defaulttainttracking.cpp:76:30:76:35 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
| defaulttainttracking.cpp:76:30:76:35 | call to getenv | defaulttainttracking.cpp:76:30:76:35 | call to getenv |
| defaulttainttracking.cpp:76:30:76:35 | call to getenv | defaulttainttracking.cpp:76:30:76:42 | (const char *)... |
| defaulttainttracking.cpp:77:34:77:39 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p |
| defaulttainttracking.cpp:77:34:77:39 | call to getenv | defaulttainttracking.cpp:77:34:77:39 | call to getenv |
| defaulttainttracking.cpp:77:34:77:39 | call to getenv | defaulttainttracking.cpp:77:34:77:46 | (const char *)... |
| defaulttainttracking.cpp:79:30:79:35 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| defaulttainttracking.cpp:79:30:79:35 | call to getenv | defaulttainttracking.cpp:57:24:57:24 | p |
| defaulttainttracking.cpp:79:30:79:35 | call to getenv | defaulttainttracking.cpp:58:14:58:14 | p |
| defaulttainttracking.cpp:79:30:79:35 | call to getenv | defaulttainttracking.cpp:79:30:79:35 | call to getenv |
| defaulttainttracking.cpp:79:30:79:35 | call to getenv | defaulttainttracking.cpp:79:30:79:42 | (const char *)... |
| defaulttainttracking.cpp:79:30:79:35 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 |
| test_diff.cpp:92:10:92:13 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:1:11:1:20 | p#0 |
| test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:92:10:92:13 | argv |
| test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:92:10:92:16 | (const char *)... |
| test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:92:10:92:16 | access to array |
| test_diff.cpp:94:32:94:35 | argv | defaulttainttracking.cpp:10:11:10:13 | p#0 |
| test_diff.cpp:94:32:94:35 | argv | test_diff.cpp:2:11:2:13 | p#0 |
| test_diff.cpp:94:32:94:35 | argv | test_diff.cpp:94:10:94:36 | reinterpret_cast<int>... |
| test_diff.cpp:94:32:94:35 | argv | test_diff.cpp:94:32:94:35 | argv |
| test_diff.cpp:96:26:96:29 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| test_diff.cpp:96:26:96:29 | argv | test_diff.cpp:1:11:1:20 | p#0 |
| test_diff.cpp:96:26:96:29 | argv | test_diff.cpp:16:39:16:39 | a |
| test_diff.cpp:96:26:96:29 | argv | test_diff.cpp:17:10:17:10 | a |
| test_diff.cpp:96:26:96:29 | argv | test_diff.cpp:96:26:96:29 | argv |
| test_diff.cpp:96:26:96:29 | argv | test_diff.cpp:96:26:96:32 | (const char *)... |
| test_diff.cpp:96:26:96:29 | argv | test_diff.cpp:96:26:96:32 | access to array |
| test_diff.cpp:98:18:98:21 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:1:11:1:20 | p#0 |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:16:39:16:39 | a |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:17:10:17:10 | a |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:98:13:98:13 | p |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:98:17:98:21 | & ... |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:98:18:98:21 | argv |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:100:10:100:14 | (const char *)... |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:100:10:100:14 | * ... |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:100:11:100:11 | p |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:100:11:100:14 | access to array |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:102:26:102:30 | (const char *)... |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:102:26:102:30 | * ... |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:102:27:102:27 | p |
| test_diff.cpp:98:18:98:21 | argv | test_diff.cpp:102:27:102:30 | access to array |
| test_diff.cpp:104:12:104:15 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:1:11:1:20 | p#0 |
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:10:104:20 | (const char *)... |
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:10:104:20 | * ... |
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:11:104:20 | (...) |
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:12:104:15 | argv |
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:12:104:19 | ... + ... |
| test_diff.cpp:108:10:108:13 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:1:11:1:20 | p#0 |
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:24:20:24:29 | p#0 |
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:29:24:29:24 | p |
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:30:14:30:14 | p |
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:108:10:108:13 | argv |
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:108:10:108:16 | (const char *)... |
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:108:10:108:16 | access to array |
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:24:20:24:29 | p#0 |
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:36:24:36:24 | p |
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:111:10:111:13 | argv |
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:111:10:111:16 | (const char *)... |
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:111:10:111:16 | access to array |
| test_diff.cpp:115:11:115:14 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:1:11:1:20 | p#0 |
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:24:20:24:29 | p#0 |
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:41:24:41:24 | p |
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:42:14:42:14 | p |
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:52:24:52:24 | p |
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:53:37:53:37 | p |
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:115:11:115:14 | argv |
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:115:11:115:17 | (const char *)... |
| test_diff.cpp:115:11:115:14 | argv | test_diff.cpp:115:11:115:17 | access to array |
| test_diff.cpp:118:26:118:29 | argv | test_diff.cpp:60:24:60:24 | p |
| test_diff.cpp:118:26:118:29 | argv | test_diff.cpp:61:34:61:34 | p |
| test_diff.cpp:118:26:118:29 | argv | test_diff.cpp:88:24:88:24 | p |
| test_diff.cpp:118:26:118:29 | argv | test_diff.cpp:118:26:118:29 | argv |
| test_diff.cpp:118:26:118:29 | argv | test_diff.cpp:118:26:118:32 | (const char *)... |
| test_diff.cpp:118:26:118:29 | argv | test_diff.cpp:118:26:118:32 | access to array |
| test_diff.cpp:121:23:121:26 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:1:11:1:20 | p#0 |
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:60:24:60:24 | p |
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:61:34:61:34 | p |
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:67:24:67:24 | p |
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:68:14:68:14 | p |
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:121:23:121:26 | argv |
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:121:23:121:29 | (const char *)... |
| test_diff.cpp:121:23:121:26 | argv | test_diff.cpp:121:23:121:29 | access to array |
| test_diff.cpp:124:19:124:22 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:1:11:1:20 | p#0 |
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:24:20:24:29 | p#0 |
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:76:24:76:24 | p |
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:81:24:81:24 | p |
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:82:14:82:14 | p |
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:124:19:124:22 | argv |
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:124:19:124:25 | (const char *)... |
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:124:19:124:25 | access to array |
| test_diff.cpp:126:43:126:46 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:1:11:1:20 | p#0 |
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:76:24:76:24 | p |
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:81:24:81:24 | p |
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:82:14:82:14 | p |
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:126:43:126:46 | argv |
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:126:43:126:49 | (const char *)... |
| test_diff.cpp:126:43:126:46 | argv | test_diff.cpp:126:43:126:49 | access to array |
| test_diff.cpp:128:44:128:47 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 |
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:1:11:1:20 | p#0 |
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:76:24:76:24 | p |
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:81:24:81:24 | p |
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:82:14:82:14 | p |
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:128:44:128:47 | argv |
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:128:44:128:50 | (const char *)... |
| test_diff.cpp:128:44:128:47 | argv | test_diff.cpp:128:44:128:50 | access to array |

View File

@@ -0,0 +1,129 @@
void sink(const char *);
void sink(int);
struct S {
void(*f)(const char*);
void apply(char* p) {
f(p);
}
void (*get())(const char*) {
return f;
}
};
void calls_sink_with_argv(const char* a) {
sink(a);
}
extern int i;
class BaseWithPureVirtual {
public:
virtual void f(const char*) = 0;
};
class DerivedCallsSink : public BaseWithPureVirtual {
public:
void f(const char* p) override {
sink(p);
}
};
class DerivedDoesNotCallSink : public BaseWithPureVirtual {
public:
void f(const char* p) override {}
};
class DerivedCallsSinkDiamond1 : virtual public BaseWithPureVirtual {
public:
void f(const char* p) override {
sink(p);
}
};
class DerivedDoesNotCallSinkDiamond2 : virtual public BaseWithPureVirtual {
public:
void f(const char* p) override {}
};
class DerivesMultiple : public DerivedCallsSinkDiamond1, public DerivedDoesNotCallSinkDiamond2 {
void f(const char* p) override {
DerivedCallsSinkDiamond1::f(p);
}
};
template<typename T>
class CRTP {
public:
void f(const char* p) {
static_cast<T*>(this)->g(p);
}
};
class CRTPCallsSink : public CRTP<CRTPCallsSink> {
public:
void g(const char* p) {
sink(p);
}
};
class Derived1 : public BaseWithPureVirtual {};
class Derived2 : public Derived1 {
public:
void f(const char* p) override {}
};
class Derived3 : public Derived2 {
public:
void f(const char* p) override {
sink(p);
}
};
class CRTPDoesNotCallSink : public CRTP<CRTPDoesNotCallSink> {
public:
void g(const char* p) {}
};
int main(int argc, char *argv[]) {
sink(argv[0]);
sink(reinterpret_cast<int>(argv));
calls_sink_with_argv(argv[1]);
char*** p = &argv;
sink(*p[0]);
calls_sink_with_argv(*p[i]);
sink(*(argv + 1));
BaseWithPureVirtual* b = new DerivedCallsSink;
b->f(argv[1]);
b = new DerivedDoesNotCallSink;
b->f(argv[0]); // no flow [FALSE POSITIVE by AST]
BaseWithPureVirtual* b2 = new DerivesMultiple;
b2->f(argv[i]);
CRTP<CRTPDoesNotCallSink> crtp_not_call_sink;
crtp_not_call_sink.f(argv[0]);
CRTP<CRTPCallsSink> crtp_calls_sink;
crtp_calls_sink.f(argv[0]);
Derived1* calls_sink = new Derived3;
calls_sink->f(argv[1]);
static_cast<Derived2*>(calls_sink)->f(argv[1]);
dynamic_cast<Derived2*>(calls_sink)->f(argv[1]); // flow [NOT DETECTED by IR]
}

View File

@@ -0,0 +1,18 @@
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 | IR only |
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:8:16:14 | call to _strdup | IR only |
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | defaulttainttracking.cpp:16:8:16:29 | (const char *)... | IR only |
| defaulttainttracking.cpp:16:16:16:21 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 | IR only |
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:3:21:3:22 | s1 | AST only |
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:21:8:21:10 | buf | AST only |
| defaulttainttracking.cpp:22:20:22:25 | call to getenv | defaulttainttracking.cpp:22:15:22:17 | buf | AST only |
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:31:40:31:53 | dotted_address | AST only |
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:36:39:61 | (const char *)... | AST only |
| defaulttainttracking.cpp:38:25:38:30 | call to getenv | defaulttainttracking.cpp:39:51:39:61 | env_pointer | AST only |
| defaulttainttracking.cpp:64:10:64:15 | call to getenv | defaulttainttracking.cpp:52:24:52:24 | p | IR only |
| test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:11:104:20 | (...) | IR only |
| test_diff.cpp:108:10:108:13 | argv | test_diff.cpp:36:24:36:24 | p | AST only |
| test_diff.cpp:111:10:111:13 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 | AST only |
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:1:11:1:20 | p#0 | AST only |
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:29:24:29:24 | p | AST only |
| test_diff.cpp:111:10:111:13 | argv | test_diff.cpp:30:14:30:14 | p | AST only |
| test_diff.cpp:124:19:124:22 | argv | test_diff.cpp:76:24:76:24 | p | IR only |

View File

@@ -0,0 +1,19 @@
import cpp
import semmle.code.cpp.security.Security
import semmle.code.cpp.security.TaintTrackingImpl as ASTTaintTracking
import semmle.code.cpp.ir.dataflow.DefaultTaintTracking as IRDefaultTaintTracking
predicate astFlow(Expr source, Element sink) { ASTTaintTracking::tainted(source, sink) }
predicate irFlow(Expr source, Element sink) { IRDefaultTaintTracking::tainted(source, sink) }
from Expr source, Element sink, string note
where
astFlow(source, sink) and
not irFlow(source, sink) and
note = "AST only"
or
irFlow(source, sink) and
not astFlow(source, sink) and
note = "IR only"
select source, sink, note

View File

@@ -61,8 +61,8 @@ void bg_structptr(XY *p1, XY *p2) {
if (guarded(p1->x)) {
sink(p1->x); // no flow [FALSE POSITIVE in AST]
} else if (guarded(p1->y)) {
sink(p1->x); // flow [NOT DETECTED in IR]
sink(p1->x); // flow
} else if (guarded(p2->x)) {
sink(p1->x); // flow [NOT DETECTED in IR]
sink(p1->x); // flow
}
}

View File

@@ -1,9 +1,5 @@
| BarrierGuard.cpp:60:11:60:16 | BarrierGuard.cpp:62:14:62:14 | AST only |
| BarrierGuard.cpp:60:11:60:16 | BarrierGuard.cpp:64:14:64:14 | AST only |
| BarrierGuard.cpp:60:11:60:16 | BarrierGuard.cpp:66:14:66:14 | AST only |
| clang.cpp:12:9:12:20 | clang.cpp:18:8:18:19 | AST only |
| clang.cpp:12:9:12:20 | clang.cpp:22:8:22:20 | AST only |
| clang.cpp:28:27:28:32 | clang.cpp:29:27:29:28 | AST only |
| clang.cpp:28:27:28:32 | clang.cpp:30:27:30:34 | AST only |
| clang.cpp:39:42:39:47 | clang.cpp:41:18:41:19 | IR only |
| dispatch.cpp:16:37:16:42 | dispatch.cpp:32:16:32:24 | IR only |
@@ -24,7 +20,6 @@
| lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only |
| lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only |
| lambdas.cpp:8:10:8:15 | lambdas.cpp:29:3:29:6 | AST only |
| lambdas.cpp:8:10:8:15 | lambdas.cpp:35:8:35:8 | AST only |
| lambdas.cpp:8:10:8:15 | lambdas.cpp:41:8:41:8 | AST only |
| lambdas.cpp:43:7:43:12 | lambdas.cpp:46:7:46:7 | AST only |
| ref.cpp:29:11:29:16 | ref.cpp:62:10:62:11 | AST only |

View File

@@ -5,8 +5,13 @@
| BarrierGuard.cpp:33:10:33:15 | source | BarrierGuard.cpp:29:16:29:21 | source |
| BarrierGuard.cpp:53:13:53:13 | x | BarrierGuard.cpp:49:10:49:15 | call to source |
| BarrierGuard.cpp:55:13:55:13 | x | BarrierGuard.cpp:49:10:49:15 | call to source |
| BarrierGuard.cpp:64:14:64:14 | x | BarrierGuard.cpp:60:11:60:16 | call to source |
| BarrierGuard.cpp:66:14:66:14 | x | BarrierGuard.cpp:60:11:60:16 | call to source |
| acrossLinkTargets.cpp:12:8:12:8 | (int)... | acrossLinkTargets.cpp:19:27:19:32 | call to source |
| acrossLinkTargets.cpp:12:8:12:8 | x | acrossLinkTargets.cpp:19:27:19:32 | call to source |
| clang.cpp:18:8:18:19 | (const int *)... | clang.cpp:12:9:12:20 | sourceArray1 |
| clang.cpp:18:8:18:19 | sourceArray1 | clang.cpp:12:9:12:20 | sourceArray1 |
| clang.cpp:29:27:29:28 | m1 | clang.cpp:28:27:28:32 | call to source |
| clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source |
| clang.cpp:41:18:41:19 | m2 | clang.cpp:39:42:39:47 | call to source |
| clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source |
@@ -30,6 +35,7 @@
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:107:17:107:22 | call to source |
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:140:8:140:13 | call to source |
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:144:8:144:13 | call to source |
| lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source |
| test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source |
| test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source |
| test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source |

View File

@@ -29,9 +29,9 @@ class Conf extends Configuration {
}
override predicate isAdditionalFlowStep(Node a, Node b) {
b.asPartialDefinition() = any(Call c |
c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr()
).getQualifier()
b.asPartialDefinition() =
any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr())
.getQualifier()
or
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
}

View File

@@ -0,0 +1,134 @@
typedef unsigned long size_t;
typedef struct {} FILE;
int snprintf(char *s, size_t n, const char *format, ...);
int sprintf(char *s, const char *format, ...);
int swprintf(wchar_t *s, size_t n, const wchar_t *format, ...);
typedef void *va_list;
#define va_start(ap, parmN)
#define va_end(ap)
#define va_arg(ap, type) ((type)0)
int vsnprintf(char *s, size_t n, const char *format, va_list arg);
int mysprintf(char *s, size_t n, const char *format, ...)
{
va_list args;
va_start(args, format);
vsnprintf(s, n, format, args);
va_end(args);
}
int sscanf(const char *s, const char *format, ...);
// ----------
int source();
void sink(...) {};
namespace string
{
char *source();
};
namespace wstring
{
wchar_t *source();
};
// ----------
void test1()
{
{
char buffer[256] = {0};
sink(snprintf(buffer, 256, "%s", "Hello."));
sink(buffer);
}
{
char buffer[256] = {0};
sink(snprintf(buffer, 256, "%s", string::source()));
sink(buffer); // tainted
}
{
char buffer[256] = {0};
sink(snprintf(buffer, 256, string::source(), "Hello."));
sink(buffer); // tainted
}
{
char buffer[256] = {0};
sink(snprintf(buffer, 256, "%s %s %s", "a", "b", string::source()));
sink(buffer); // tainted
}
{
char buffer[256] = {0};
sink(snprintf(buffer, 256, "%.*s", 10, string::source()));
sink(buffer); // tainted
}
{
char buffer[256] = {0};
sink(snprintf(buffer, 256, "%i", 0));
sink(buffer);
}
{
char buffer[256] = {0};
sink(snprintf(buffer, 256, "%i", source()));
sink(buffer); // tainted
}
{
char buffer[256] = {0};
sink(snprintf(buffer, 256, "%.*s", source(), "Hello."));
sink(buffer); // tainted
}
{
char buffer[256] = {0};
sink(snprintf(buffer, 256, "%p", string::source()));
sink(buffer); // tainted (debatable)
}
{
char buffer[256] = {0};
sink(sprintf(buffer, "%s", string::source()));
sink(buffer); // tainted
}
{
char buffer[256] = {0};
sink(sprintf(buffer, "%ls", wstring::source()));
sink(buffer); // tainted
}
{
wchar_t wbuffer[256] = {0};
sink(swprintf(wbuffer, 256, L"%s", wstring::source()));
sink(wbuffer); // tainted
}
{
char buffer[256] = {0};
sink(mysprintf(buffer, 256, "%s", string::source()));
sink(buffer); // tainted [NOT DETECTED - implement UserDefinedFormattingFunction.getOutputParameterIndex()]
}
{
int i = 0;
sink(sscanf("123", "%i", &i));
sink(i);
}
{
int i = 0;
sink(sscanf(string::source(), "%i", &i));
sink(i); // tainted [NOT DETECTED]
}
{
char buffer[256] = {0};
sink(sscanf("Hello.", "%s", &buffer));
sink(buffer);
}
{
char buffer[256] = {0};
sink(sscanf(string::source(), "%s", &buffer));
sink(buffer); // tainted [NOT DETECTED]
}
}

View File

@@ -3,6 +3,108 @@
| 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: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: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: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:132:8:132:13 | buffer | |
| format.cpp:131:40:131:45 | buffer | format.cpp:131:39:131:45 | & ... | |
| taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | |
| taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | |
| taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | |

View File

@@ -1,3 +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 |
| taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 |
| taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source |
| taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source |

View File

@@ -1,3 +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 |
| taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only |
| taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only |
| taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only |
@@ -13,13 +23,11 @@
| taint.cpp:181:8:181:9 | taint.cpp:185:11:185:16 | AST only |
| taint.cpp:195:7:195:7 | taint.cpp:192:23:192:28 | AST only |
| taint.cpp:195:7:195:7 | taint.cpp:193:6:193:6 | AST only |
| taint.cpp:215:7:215:7 | taint.cpp:207:6:207:11 | AST only |
| taint.cpp:216:7:216:7 | taint.cpp:207:6:207:11 | AST only |
| taint.cpp:229:3:229:6 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:233:8:233:8 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:236:3:236:6 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:244:3:244:6 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:250:8:250:8 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:256:8:256:8 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:261:7:261:7 | taint.cpp:258:7:258:12 | AST only |
| taint.cpp:351:7:351:7 | taint.cpp:330:6:330:11 | AST only |
@@ -27,7 +35,6 @@
| taint.cpp:423:7:423:7 | taint.cpp:422:14:422:19 | AST only |
| taint.cpp:424:9:424:17 | taint.cpp:422:14:422:19 | AST only |
| taint.cpp:429:7:429:7 | taint.cpp:428:13:428:18 | IR only |
| taint.cpp:430:9:430:14 | taint.cpp:428:13:428:18 | AST only |
| taint.cpp:438:7:438:7 | taint.cpp:437:15:437:20 | AST only |
| taint.cpp:439:10:439:18 | taint.cpp:437:15:437:20 | AST only |
| taint.cpp:446:7:446:7 | taint.cpp:445:14:445:28 | AST only |

View File

@@ -9,6 +9,8 @@
| taint.cpp:167:8:167:13 | call to source | taint.cpp:167:8:167:13 | call to source |
| taint.cpp:168:8:168:14 | tainted | taint.cpp:164:19:164:24 | call to source |
| taint.cpp:210:7:210:7 | x | taint.cpp:207:6:207:11 | call to source |
| taint.cpp:215:7:215:7 | x | taint.cpp:207:6:207:11 | call to source |
| taint.cpp:250:8:250:8 | a | taint.cpp:223:10:223:15 | call to source |
| taint.cpp:280:7:280:7 | t | taint.cpp:275:6:275:11 | call to source |
| taint.cpp:289:7:289:7 | t | taint.cpp:275:6:275:11 | call to source |
| taint.cpp:290:7:290:7 | x | taint.cpp:275:6:275:11 | call to source |
@@ -20,3 +22,4 @@
| taint.cpp:382:7:382:7 | a | taint.cpp:377:23:377:28 | source |
| taint.cpp:391:7:391:7 | a | taint.cpp:385:27:385:32 | source |
| taint.cpp:429:7:429:7 | b | taint.cpp:428:13:428:18 | call to source |
| taint.cpp:430:9:430:14 | member | taint.cpp:428:13:428:18 | call to source |

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -5,7 +5,8 @@ import semmle.code.cpp.ir.internal.IntegerConstant
from IRFunction irFunc, int value
where
value = getValue(getConstantValue(irFunc
value =
getValue(getConstantValue(irFunc
.getReturnInstruction()
.(ReturnValueInstruction)
.getReturnValue()))

View File

@@ -1,6 +1,7 @@
import default
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
predicate shouldEscape(IRAutomaticUserVariable var) {
exists(string name |
@@ -15,9 +16,9 @@ where
exists(IRFunction irFunc |
irFunc = var.getEnclosingIRFunction() and
(
shouldEscape(var) and variableAddressEscapes(var)
shouldEscape(var) and allocationEscapes(var)
or
not shouldEscape(var) and not variableAddressEscapes(var)
not shouldEscape(var) and not allocationEscapes(var)
)
)
select var

View File

@@ -1,86 +0,0 @@
| escape.cpp:111:18:111:21 | CopyValue | no_+0 | no_+0 |
| escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0 | no_+0 |
| escape.cpp:115:20:115:23 | CopyValue | no_+0 | no_+0 |
| escape.cpp:116:19:116:28 | PointerSub[4] | no_+0 | no_+0 |
| escape.cpp:116:20:116:23 | CopyValue | no_+0 | no_+0 |
| escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0 | no_+0 |
| escape.cpp:117:23:117:26 | CopyValue | no_+0 | no_+0 |
| escape.cpp:118:9:118:12 | CopyValue | no_+0 | no_+0 |
| escape.cpp:120:12:120:15 | CopyValue | no_+0 | no_+0 |
| escape.cpp:123:14:123:17 | CopyValue | no_+0 | no_+0 |
| escape.cpp:124:15:124:18 | CopyValue | no_+0 | no_+0 |
| escape.cpp:127:9:127:12 | CopyValue | no_+0 | no_+0 |
| escape.cpp:129:12:129:15 | CopyValue | no_+0 | no_+0 |
| escape.cpp:134:5:134:18 | Convert | no_Array+0 | no_Array+0 |
| escape.cpp:134:11:134:18 | Convert | no_Array+0 | no_Array+0 |
| escape.cpp:135:5:135:12 | Convert | no_Array+0 | no_Array+0 |
| escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20 | no_Array+20 |
| escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20 | no_Array+20 |
| escape.cpp:136:7:136:14 | Convert | no_Array+0 | no_Array+0 |
| escape.cpp:137:17:137:24 | Convert | no_Array+0 | no_Array+0 |
| escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20 | no_Array+20 |
| escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20 | no_Array+20 |
| escape.cpp:138:19:138:26 | Convert | no_Array+0 | no_Array+0 |
| escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0 | no_Point+0 |
| escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4 | no_Point+4 |
| escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8 | no_Point+8 |
| escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0 | no_Point+0 |
| escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4 | no_Point+4 |
| escape.cpp:143:19:143:27 | CopyValue | no_Point+0 | no_Point+0 |
| escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4 | no_Point+4 |
| escape.cpp:144:6:144:14 | CopyValue | no_Point+0 | no_Point+0 |
| escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4 | no_Point+4 |
| escape.cpp:145:20:145:30 | CopyValue | no_Point+8 | no_Point+8 |
| escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8 | no_Point+8 |
| escape.cpp:146:5:146:18 | CopyValue | no_Point+8 | no_Point+8 |
| escape.cpp:146:7:146:17 | CopyValue | no_Point+8 | no_Point+8 |
| escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8 | no_Point+8 |
| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0 | no_Derived+0 |
| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0 | no_Derived+0 |
| escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0 | no_Derived+0 |
| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0 | no_Derived+0 |
| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0 | no_Derived+0 |
| escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0 | no_Derived+0 |
| escape.cpp:151:5:151:14 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12 | no_Derived+12 |
| escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16 | no_Derived+16 |
| escape.cpp:152:19:152:28 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12 | no_Derived+12 |
| escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16 | no_Derived+16 |
| escape.cpp:155:17:155:30 | CopyValue | no_ssa_addrOf+0 | no_ssa_addrOf+0 |
| escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0 | no_ssa_addrOf+0 |
| escape.cpp:158:17:158:28 | CopyValue | no_ssa_refTo+0 | no_ssa_refTo+0 |
| escape.cpp:158:17:158:28 | Store | no_ssa_refTo+0 | no_ssa_refTo+0 |
| escape.cpp:161:19:161:42 | Convert | no_ssa_refToArrayElement+0 | no_ssa_refToArrayElement+0 |
| escape.cpp:161:19:161:45 | CopyValue | no_ssa_refToArrayElement+20 | no_ssa_refToArrayElement+20 |
| escape.cpp:161:19:161:45 | PointerAdd[4] | no_ssa_refToArrayElement+20 | no_ssa_refToArrayElement+20 |
| escape.cpp:161:19:161:45 | Store | no_ssa_refToArrayElement+20 | no_ssa_refToArrayElement+20 |
| escape.cpp:164:24:164:40 | CopyValue | no_ssa_refToArray+0 | no_ssa_refToArray+0 |
| escape.cpp:164:24:164:40 | Store | no_ssa_refToArray+0 | no_ssa_refToArray+0 |
| escape.cpp:167:19:167:28 | CopyValue | passByPtr+0 | passByPtr+0 |
| escape.cpp:170:21:170:29 | CopyValue | passByRef+0 | passByRef+0 |
| escape.cpp:173:22:173:38 | CopyValue | no_ssa_passByPtr+0 | no_ssa_passByPtr+0 |
| escape.cpp:176:24:176:39 | CopyValue | no_ssa_passByRef+0 | no_ssa_passByRef+0 |
| escape.cpp:179:22:179:42 | CopyValue | no_ssa_passByPtr_ret+0 | no_ssa_passByPtr_ret+0 |
| escape.cpp:182:24:182:43 | CopyValue | no_ssa_passByRef_ret+0 | no_ssa_passByRef_ret+0 |
| escape.cpp:185:30:185:40 | CopyValue | passByPtr2+0 | passByPtr2+0 |
| escape.cpp:188:32:188:41 | CopyValue | passByRef2+0 | passByRef2+0 |
| escape.cpp:191:30:191:42 | Call | none | passByPtr3+0 |
| escape.cpp:191:44:191:54 | CopyValue | passByPtr3+0 | passByPtr3+0 |
| escape.cpp:194:32:194:46 | Call | none | passByRef3+0 |
| escape.cpp:194:32:194:59 | CopyValue | none | passByRef3+0 |
| escape.cpp:194:48:194:57 | CopyValue | passByRef3+0 | passByRef3+0 |
| escape.cpp:199:17:199:34 | CopyValue | no_ssa_passByPtr4+0 | no_ssa_passByPtr4+0 |
| escape.cpp:199:37:199:54 | CopyValue | no_ssa_passByPtr5+0 | no_ssa_passByPtr5+0 |
| escape.cpp:202:5:202:19 | Call | none | passByRef6+0 |
| escape.cpp:202:5:202:32 | CopyValue | none | passByRef6+0 |
| escape.cpp:202:21:202:30 | CopyValue | passByRef6+0 | passByRef6+0 |
| escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+0 |
| escape.cpp:205:5:205:39 | CopyValue | none | no_ssa_passByRef7+0 |
| escape.cpp:205:21:205:37 | CopyValue | no_ssa_passByRef7+0 | no_ssa_passByRef7+0 |
| escape.cpp:209:14:209:25 | Call | none | no_ssa_c+0 |
| escape.cpp:217:14:217:16 | CopyValue | c2+0 | c2+0 |
| escape.cpp:221:8:221:19 | Call | none | c3+0 |
| escape.cpp:225:17:225:28 | Call | none | c4+0 |
| escape.cpp:247:2:247:27 | Store | condEscape1+0 | condEscape1+0 |
| escape.cpp:247:16:247:27 | CopyValue | condEscape1+0 | condEscape1+0 |
| escape.cpp:249:9:249:34 | Store | condEscape2+0 | condEscape2+0 |
| escape.cpp:249:23:249:34 | CopyValue | condEscape2+0 | condEscape2+0 |

View File

@@ -1,35 +0,0 @@
import default
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.AliasAnalysis as RawAA
import semmle.code.cpp.ir.implementation.raw.IR as Raw
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.AliasAnalysis as UnAA
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as Un
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction
import semmle.code.cpp.ir.internal.IntegerConstant
from Raw::Instruction rawInstr, Un::Instruction unInstr, string rawPointsTo, string unPointsTo
where
rawInstr = getOldInstruction(unInstr) and
not rawInstr instanceof Raw::VariableAddressInstruction and
(
exists(Variable var, int rawBitOffset, int unBitOffset |
RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), rawBitOffset) and
rawPointsTo = var.toString() + getBitOffsetString(rawBitOffset) and
UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), unBitOffset) and
unPointsTo = var.toString() + getBitOffsetString(unBitOffset)
)
or
exists(Variable var, int unBitOffset |
not RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), _) and
rawPointsTo = "none" and
UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), unBitOffset) and
unPointsTo = var.toString() + getBitOffsetString(unBitOffset)
)
or
exists(Variable var, int rawBitOffset |
RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), rawBitOffset) and
rawPointsTo = var.toString() + getBitOffsetString(rawBitOffset) and
not UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), _) and
unPointsTo = "none"
)
)
select rawInstr.getLocation().toString(), rawInstr.getOperationString(), rawPointsTo, unPointsTo

View File

@@ -1,22 +1,25 @@
import default
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
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis
predicate shouldEscape(IRAutomaticUserVariable var) {
exists(string name |
name = var.getVariable().getName() and
name.matches("no_%")
)
class InterestingAllocation extends VariableAllocation {
IRUserVariable userVar;
InterestingAllocation() { userVar = this.getIRVariable() }
final predicate shouldEscape() { userVar.getVariable().getName().matches("no_%") }
}
from IRAutomaticUserVariable var
from InterestingAllocation var
where
exists(IRFunction irFunc |
irFunc = var.getEnclosingIRFunction() and
(
shouldEscape(var) and variableAddressEscapes(var)
var.shouldEscape() and allocationEscapes(var)
or
not shouldEscape(var) and not variableAddressEscapes(var)
not var.shouldEscape() and not allocationEscapes(var)
)
)
select var

View File

@@ -8056,6 +8056,20 @@ ir.cpp:
# 1166| 0: [VariableAccess] y
# 1166| Type = [IntType] int
# 1166| ValueCategory = prvalue(load)
# 1169| [TopLevelFunction] String ReturnObjectImpl()
# 1169| params:
# 1169| body: [Block] { ... }
# 1170| 0: [ReturnStmt] return ...
# 1170| 0: [ConstructorCall] call to String
# 1170| Type = [Struct] String
# 1170| ValueCategory = prvalue
# 1170| 0: [ArrayToPointerConversion] array to pointer conversion
# 1170| Type = [PointerType] const char *
# 1170| ValueCategory = prvalue
# 1170| expr: foo
# 1170| Type = [ArrayType] const char[4]
# 1170| Value = [StringLiteral] "foo"
# 1170| ValueCategory = lvalue
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| params:

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IRSanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,26 @@
missingOperand
| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
unexpectedOperand
duplicateOperand
missingPhiOperand
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
ambiguousSuccessors
unexplainedLoop
unnecessaryPhiInstruction
operandAcrossFunctions
instructionWithoutUniqueBlock
containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSASanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,2 @@
multipleOperandMemoryLocations
missingVirtualVariableForMemoryLocation

View File

@@ -1166,4 +1166,8 @@ int ModeledCallTarget(int x) {
return y;
}
String ReturnObjectImpl() {
return String("foo");
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -3371,15 +3371,16 @@ ir.cpp:
# 731| Block 7
# 731| r731_11(glval<String>) = VariableAddress[#throw731:19] :
# 731| r731_12(glval<unknown>) = FunctionAddress[String] :
# 731| r731_13(glval<char[14]>) = StringConstant["String object"] :
# 731| r731_14(char *) = Convert : r731_13
# 731| v731_15(void) = Call : func:r731_12, this:r731_11, 0:r731_14
# 731| mu731_16(unknown) = ^CallSideEffect : ~mu724_3
# 731| mu731_17(String) = ^IndirectMayWriteSideEffect[-1] : &:r731_11
# 731| v731_18(void) = ^BufferReadSideEffect[0] : &:r731_14, ~mu724_3
# 731| mu731_19(unknown) = ^BufferMayWriteSideEffect[0] : &:r731_14
# 731| v731_20(void) = ThrowValue : &:r731_11, ~mu724_3
# 731| mu731_12(String) = Uninitialized[#throw731:19] : &:r731_11
# 731| r731_13(glval<unknown>) = FunctionAddress[String] :
# 731| r731_14(glval<char[14]>) = StringConstant["String object"] :
# 731| r731_15(char *) = Convert : r731_14
# 731| v731_16(void) = Call : func:r731_13, this:r731_11, 0:r731_15
# 731| mu731_17(unknown) = ^CallSideEffect : ~mu724_3
# 731| mu731_18(String) = ^IndirectMayWriteSideEffect[-1] : &:r731_11
# 731| v731_19(void) = ^BufferReadSideEffect[0] : &:r731_15, ~mu724_3
# 731| mu731_20(unknown) = ^BufferMayWriteSideEffect[0] : &:r731_15
# 731| v731_21(void) = ThrowValue : &:r731_11, ~mu724_3
#-----| Exception -> Block 9
# 733| Block 8
@@ -3399,15 +3400,16 @@ ir.cpp:
# 735| r735_4(char *) = Load : &:r735_2, ~mu735_3
# 735| mu735_5(unknown) = InitializeIndirection[s] : &:r735_4
# 736| r736_1(glval<String>) = VariableAddress[#throw736:5] :
# 736| r736_2(glval<unknown>) = FunctionAddress[String] :
# 736| r736_3(glval<char *>) = VariableAddress[s] :
# 736| r736_4(char *) = Load : &:r736_3, ~mu724_3
# 736| v736_5(void) = Call : func:r736_2, this:r736_1, 0:r736_4
# 736| mu736_6(unknown) = ^CallSideEffect : ~mu724_3
# 736| mu736_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r736_1
# 736| v736_8(void) = ^BufferReadSideEffect[0] : &:r736_4, ~mu724_3
# 736| mu736_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r736_4
# 736| v736_10(void) = ThrowValue : &:r736_1, ~mu724_3
# 736| mu736_2(String) = Uninitialized[#throw736:5] : &:r736_1
# 736| r736_3(glval<unknown>) = FunctionAddress[String] :
# 736| r736_4(glval<char *>) = VariableAddress[s] :
# 736| r736_5(char *) = Load : &:r736_4, ~mu724_3
# 736| v736_6(void) = Call : func:r736_3, this:r736_1, 0:r736_5
# 736| mu736_7(unknown) = ^CallSideEffect : ~mu724_3
# 736| mu736_8(String) = ^IndirectMayWriteSideEffect[-1] : &:r736_1
# 736| v736_9(void) = ^BufferReadSideEffect[0] : &:r736_5, ~mu724_3
# 736| mu736_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r736_5
# 736| v736_11(void) = ThrowValue : &:r736_1, ~mu724_3
#-----| Exception -> Block 2
# 738| Block 11
@@ -5728,15 +5730,16 @@ ir.cpp:
# 1140| Block 7
# 1140| r1140_11(glval<String>) = VariableAddress[#throw1140:19] :
# 1140| r1140_12(glval<unknown>) = FunctionAddress[String] :
# 1140| r1140_13(glval<char[14]>) = StringConstant["String object"] :
# 1140| r1140_14(char *) = Convert : r1140_13
# 1140| v1140_15(void) = Call : func:r1140_12, this:r1140_11, 0:r1140_14
# 1140| mu1140_16(unknown) = ^CallSideEffect : ~mu1133_3
# 1140| mu1140_17(String) = ^IndirectMayWriteSideEffect[-1] : &:r1140_11
# 1140| v1140_18(void) = ^BufferReadSideEffect[0] : &:r1140_14, ~mu1133_3
# 1140| mu1140_19(unknown) = ^BufferMayWriteSideEffect[0] : &:r1140_14
# 1140| v1140_20(void) = ThrowValue : &:r1140_11, ~mu1133_3
# 1140| mu1140_12(String) = Uninitialized[#throw1140:19] : &:r1140_11
# 1140| r1140_13(glval<unknown>) = FunctionAddress[String] :
# 1140| r1140_14(glval<char[14]>) = StringConstant["String object"] :
# 1140| r1140_15(char *) = Convert : r1140_14
# 1140| v1140_16(void) = Call : func:r1140_13, this:r1140_11, 0:r1140_15
# 1140| mu1140_17(unknown) = ^CallSideEffect : ~mu1133_3
# 1140| mu1140_18(String) = ^IndirectMayWriteSideEffect[-1] : &:r1140_11
# 1140| v1140_19(void) = ^BufferReadSideEffect[0] : &:r1140_15, ~mu1133_3
# 1140| mu1140_20(unknown) = ^BufferMayWriteSideEffect[0] : &:r1140_15
# 1140| v1140_21(void) = ThrowValue : &:r1140_11, ~mu1133_3
#-----| Exception -> Block 9
# 1142| Block 8
@@ -5756,15 +5759,16 @@ ir.cpp:
# 1144| r1144_4(char *) = Load : &:r1144_2, ~mu1144_3
# 1144| mu1144_5(unknown) = InitializeIndirection[s] : &:r1144_4
# 1145| r1145_1(glval<String>) = VariableAddress[#throw1145:5] :
# 1145| r1145_2(glval<unknown>) = FunctionAddress[String] :
# 1145| r1145_3(glval<char *>) = VariableAddress[s] :
# 1145| r1145_4(char *) = Load : &:r1145_3, ~mu1133_3
# 1145| v1145_5(void) = Call : func:r1145_2, this:r1145_1, 0:r1145_4
# 1145| mu1145_6(unknown) = ^CallSideEffect : ~mu1133_3
# 1145| mu1145_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r1145_1
# 1145| v1145_8(void) = ^BufferReadSideEffect[0] : &:r1145_4, ~mu1133_3
# 1145| mu1145_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r1145_4
# 1145| v1145_10(void) = ThrowValue : &:r1145_1, ~mu1133_3
# 1145| mu1145_2(String) = Uninitialized[#throw1145:5] : &:r1145_1
# 1145| r1145_3(glval<unknown>) = FunctionAddress[String] :
# 1145| r1145_4(glval<char *>) = VariableAddress[s] :
# 1145| r1145_5(char *) = Load : &:r1145_4, ~mu1133_3
# 1145| v1145_6(void) = Call : func:r1145_3, this:r1145_1, 0:r1145_5
# 1145| mu1145_7(unknown) = ^CallSideEffect : ~mu1133_3
# 1145| mu1145_8(String) = ^IndirectMayWriteSideEffect[-1] : &:r1145_1
# 1145| v1145_9(void) = ^BufferReadSideEffect[0] : &:r1145_5, ~mu1133_3
# 1145| mu1145_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r1145_5
# 1145| v1145_11(void) = ThrowValue : &:r1145_1, ~mu1133_3
#-----| Exception -> Block 2
# 1147| Block 11
@@ -5878,6 +5882,27 @@ ir.cpp:
# 1163| v1163_9(void) = AliasedUse : ~mu1163_3
# 1163| v1163_10(void) = ExitFunction :
# 1169| String ReturnObjectImpl()
# 1169| Block 0
# 1169| v1169_1(void) = EnterFunction :
# 1169| mu1169_2(unknown) = AliasedDefinition :
# 1169| mu1169_3(unknown) = UnmodeledDefinition :
# 1170| r1170_1(glval<String>) = VariableAddress[#return] :
# 1170| mu1170_2(String) = Uninitialized[#return] : &:r1170_1
# 1170| r1170_3(glval<unknown>) = FunctionAddress[String] :
# 1170| r1170_4(glval<char[4]>) = StringConstant["foo"] :
# 1170| r1170_5(char *) = Convert : r1170_4
# 1170| r1170_6(String) = Call : func:r1170_3, this:r1170_1, 0:r1170_5
# 1170| mu1170_7(unknown) = ^CallSideEffect : ~mu1169_3
# 1170| mu1170_8(String) = ^IndirectMayWriteSideEffect[-1] : &:r1170_1
# 1170| v1170_9(void) = ^BufferReadSideEffect[0] : &:r1170_5, ~mu1169_3
# 1170| mu1170_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r1170_5
# 1169| r1169_4(glval<String>) = VariableAddress[#return] :
# 1169| v1169_5(void) = ReturnValue : &:r1169_4, ~mu1169_3
# 1169| v1169_6(void) = UnmodeledUse : mu*
# 1169| v1169_7(void) = AliasedUse : ~mu1169_3
# 1169| v1169_8(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.unaliased_ssa.IRSanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,26 @@
missingOperand
| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
unexpectedOperand
duplicateOperand
missingPhiOperand
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
ambiguousSuccessors
unexplainedLoop
unnecessaryPhiInstruction
operandAcrossFunctions
instructionWithoutUniqueBlock
containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSASanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,2 @@
multipleOperandMemoryLocations
missingVirtualVariableForMemoryLocation

View File

@@ -0,0 +1,87 @@
struct Point {
int x;
int y;
};
struct Base1 {
int b1;
};
struct Base2 {
int b2;
};
struct DerivedSI : Base1 {
int dsi;
};
struct DerivedMI : Base1, Base2 {
int dmi;
};
struct DerivedVI : virtual Base1 {
int dvi;
};
void Locals() {
Point pt = { //$ussa=pt
1, //$ussa=pt[0..4)<int>
2 //$ussa=pt[4..8)<int>
};
int i = pt.x; //$ussa=pt[0..4)<int>
i = pt.y; //$ussa=pt[4..8)<int>
int* p = &pt.x;
i = *p; //$ussa=pt[0..4)<int>
p = &pt.y;
i = *p; //$ussa=pt[4..8)<int>
}
void PointsTo(
int a, //$raw,ussa=a
Point& b, //$raw,ussa=b $ussa=*b
Point* c, //$raw,ussa=c $ussa=*c
int* d, //$raw,ussa=d $ussa=*d
DerivedSI* e, //$raw,ussa=e $ussa=*e
DerivedMI* f, //$raw,ussa=f $ussa=*f
DerivedVI* g //$raw,ussa=g $ussa=*g
) {
int i = a; //$raw,ussa=a
i = *&a; //$raw,ussa=a
i = *(&a + 0); //$raw,ussa=a
i = b.x; //$raw,ussa=b $ussa=*b[0..4)<int>
i = b.y; //$raw,ussa=b $ussa=*b[4..8)<int>
i = c->x; //$raw,ussa=c $ussa=*c[0..4)<int>
i = c->y; //$raw,ussa=c $ussa=*c[4..8)<int>
i = *d; //$raw,ussa=d $ussa=*d[0..4)<int>
i = *(d + 0); //$raw,ussa=d $ussa=*d[0..4)<int>
i = d[5]; //$raw,ussa=d $ussa=*d[20..24)<int>
i = 5[d]; //$raw,ussa=d $ussa=*d[20..24)<int>
i = d[a]; //$raw,ussa=d $raw,ussa=a $ussa=*d[?..?)<int>
i = a[d]; //$raw,ussa=d $raw,ussa=a $ussa=*d[?..?)<int>
int* p = &b.x; //$raw,ussa=b
i = *p; //$ussa=*b[0..4)<int>
p = &b.y; //$raw,ussa=b
i = *p; //$ussa=*b[4..8)<int>
p = &c->x; //$raw,ussa=c
i = *p; //$ussa=*c[0..4)<int>
p = &c->y; //$raw,ussa=c
i = *p; //$ussa=*c[4..8)<int>
p = &d[5]; //$raw,ussa=d
i = *p; //$ussa=*d[20..24)<int>
p = &d[a]; //$raw,ussa=d $raw,ussa=a
i = *p; //$ussa=*d[?..?)<int>
Point* q = &c[a]; //$raw,ussa=c $raw,ussa=a
i = q->x; //$ussa=*c[?..?)<int>
i = q->y; //$ussa=*c[?..?)<int>
i = e->b1; //$raw,ussa=e $ussa=*e[0..4)<int>
i = e->dsi; //$raw,ussa=e $ussa=*e[4..8)<int>
i = f->b1; //$raw,ussa=f $ussa=*f[0..4)<int>
i = f->b2; //$raw,ussa=f $ussa=*f[4..8)<int>
i = f->dmi; //$raw,ussa=f $ussa=*f[8..12)<int>
i = g->b1; //$raw,ussa=g $ussa=*g[?..?)<int>
i = g->dvi; //$raw,ussa=g $ussa=*g[8..12)<int>
}

View File

@@ -0,0 +1,65 @@
import cpp
private import TestUtilities.InlineExpectationsTest
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
private predicate ignoreAllocation(string name) {
name = "i" or
name = "p" or
name = "q"
}
module Raw {
private import semmle.code.cpp.ir.implementation.raw.IR
private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SimpleSSA
private MemoryLocation getAMemoryAccess(Instruction instr) {
result = getResultMemoryLocation(instr) or
result = getOperandMemoryLocation(instr.getAnOperand())
}
class RawPointsToTest extends InlineExpectationsTest {
RawPointsToTest() { this = "RawPointsToTest" }
override string getARelevantTag() { result = "raw" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Instruction instr, MemoryLocation memLocation |
memLocation = getAMemoryAccess(instr) and
tag = "raw" and
not ignoreAllocation(memLocation.getAllocation().getAllocationString()) and
value = memLocation.toString() and
element = instr.toString() and
location = instr.getLocation()
)
}
}
}
module UnaliasedSSA {
private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
private import semmle.code.cpp.ir.implementation.aliased_ssa.internal.AliasedSSA
private MemoryLocation getAMemoryAccess(Instruction instr) {
result = getResultMemoryLocation(instr) or
result = getOperandMemoryLocation(instr.getAnOperand())
}
class UnaliasedSSAPointsToTest extends InlineExpectationsTest {
UnaliasedSSAPointsToTest() { this = "UnaliasedSSAPointsToTest" }
override string getARelevantTag() { result = "ussa" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Instruction instr, MemoryLocation memLocation |
memLocation = getAMemoryAccess(instr) and
not memLocation instanceof AliasedVirtualVariable and
not memLocation instanceof AllNonLocalMemory and
tag = "ussa" and
not ignoreAllocation(memLocation.getAllocation().getAllocationString()) and
value = memLocation.toString() and
element = instr.toString() and
location = instr.getLocation()
)
}
}
}

View File

@@ -8,13 +8,12 @@ ssa.cpp:
# 13| m13_5(Point *) = InitializeParameter[p] : &:r13_4
# 13| r13_6(Point *) = Load : &:r13_4, m13_5
# 13| m13_7(unknown) = InitializeIndirection[p] : &:r13_6
# 13| m13_8(unknown) = Chi : total:m13_2, partial:m13_7
# 13| r13_9(glval<bool>) = VariableAddress[which1] :
# 13| m13_10(bool) = InitializeParameter[which1] : &:r13_9
# 13| r13_11(glval<bool>) = VariableAddress[which2] :
# 13| m13_12(bool) = InitializeParameter[which2] : &:r13_11
# 13| r13_8(glval<bool>) = VariableAddress[which1] :
# 13| m13_9(bool) = InitializeParameter[which1] : &:r13_8
# 13| r13_10(glval<bool>) = VariableAddress[which2] :
# 13| m13_11(bool) = InitializeParameter[which2] : &:r13_10
# 14| r14_1(glval<bool>) = VariableAddress[which1] :
# 14| r14_2(bool) = Load : &:r14_1, m13_10
# 14| r14_2(bool) = Load : &:r14_1, m13_9
# 14| v14_3(void) = ConditionalBranch : r14_2
#-----| False -> Block 2
#-----| True -> Block 1
@@ -23,29 +22,31 @@ ssa.cpp:
# 15| r15_1(glval<Point *>) = VariableAddress[p] :
# 15| r15_2(Point *) = Load : &:r15_1, m13_5
# 15| r15_3(glval<int>) = FieldAddress[x] : r15_2
# 15| r15_4(int) = Load : &:r15_3, ~m13_8
# 15| r15_4(int) = Load : &:r15_3, ~m13_7
# 15| r15_5(int) = Constant[1] :
# 15| r15_6(int) = Add : r15_4, r15_5
# 15| m15_7(int) = Store : &:r15_3, r15_6
# 15| m15_8(unknown) = Chi : total:m13_8, partial:m15_7
# 15| m15_8(unknown) = Chi : total:m13_7, partial:m15_7
#-----| Goto -> Block 3
# 18| Block 2
# 18| r18_1(glval<Point *>) = VariableAddress[p] :
# 18| r18_2(Point *) = Load : &:r18_1, m13_5
# 18| r18_3(glval<int>) = FieldAddress[y] : r18_2
# 18| r18_4(int) = Load : &:r18_3, ~m13_8
# 18| r18_4(int) = Load : &:r18_3, ~m13_7
# 18| r18_5(int) = Constant[1] :
# 18| r18_6(int) = Add : r18_4, r18_5
# 18| m18_7(int) = Store : &:r18_3, r18_6
# 18| m18_8(unknown) = Chi : total:m13_8, partial:m18_7
# 18| m18_8(unknown) = Chi : total:m13_7, partial:m18_7
#-----| Goto -> Block 3
# 21| Block 3
# 21| m21_1(unknown) = Phi : from 1:~m15_8, from 2:~m18_8
# 21| r21_2(glval<bool>) = VariableAddress[which2] :
# 21| r21_3(bool) = Load : &:r21_2, m13_12
# 21| v21_4(void) = ConditionalBranch : r21_3
# 21| m21_1(int) = Phi : from 1:~m13_7, from 2:m18_7
# 21| m21_2(int) = Phi : from 1:m15_7, from 2:~m13_7
# 21| m21_3(unknown) = Phi : from 1:m15_8, from 2:m18_8
# 21| r21_4(glval<bool>) = VariableAddress[which2] :
# 21| r21_5(bool) = Load : &:r21_4, m13_11
# 21| v21_6(void) = ConditionalBranch : r21_5
#-----| False -> Block 5
#-----| True -> Block 4
@@ -53,43 +54,45 @@ ssa.cpp:
# 22| r22_1(glval<Point *>) = VariableAddress[p] :
# 22| r22_2(Point *) = Load : &:r22_1, m13_5
# 22| r22_3(glval<int>) = FieldAddress[x] : r22_2
# 22| r22_4(int) = Load : &:r22_3, ~m21_1
# 22| r22_4(int) = Load : &:r22_3, m21_2
# 22| r22_5(int) = Constant[1] :
# 22| r22_6(int) = Add : r22_4, r22_5
# 22| m22_7(int) = Store : &:r22_3, r22_6
# 22| m22_8(unknown) = Chi : total:m21_1, partial:m22_7
# 22| m22_8(unknown) = Chi : total:m21_3, partial:m22_7
#-----| Goto -> Block 6
# 25| Block 5
# 25| r25_1(glval<Point *>) = VariableAddress[p] :
# 25| r25_2(Point *) = Load : &:r25_1, m13_5
# 25| r25_3(glval<int>) = FieldAddress[y] : r25_2
# 25| r25_4(int) = Load : &:r25_3, ~m21_1
# 25| r25_4(int) = Load : &:r25_3, m21_1
# 25| r25_5(int) = Constant[1] :
# 25| r25_6(int) = Add : r25_4, r25_5
# 25| m25_7(int) = Store : &:r25_3, r25_6
# 25| m25_8(unknown) = Chi : total:m21_1, partial:m25_7
# 25| m25_8(unknown) = Chi : total:m21_3, partial:m25_7
#-----| Goto -> Block 6
# 28| Block 6
# 28| m28_1(unknown) = Phi : from 4:~m22_8, from 5:~m25_8
# 28| r28_2(glval<int>) = VariableAddress[#return] :
# 28| r28_3(glval<Point *>) = VariableAddress[p] :
# 28| r28_4(Point *) = Load : &:r28_3, m13_5
# 28| r28_5(glval<int>) = FieldAddress[x] : r28_4
# 28| r28_6(int) = Load : &:r28_5, ~m28_1
# 28| r28_7(glval<Point *>) = VariableAddress[p] :
# 28| r28_8(Point *) = Load : &:r28_7, m13_5
# 28| r28_9(glval<int>) = FieldAddress[y] : r28_8
# 28| r28_10(int) = Load : &:r28_9, ~m28_1
# 28| r28_11(int) = Add : r28_6, r28_10
# 28| m28_12(int) = Store : &:r28_2, r28_11
# 13| v13_13(void) = ReturnIndirection : &:r13_6, ~m28_1
# 13| r13_14(glval<int>) = VariableAddress[#return] :
# 13| v13_15(void) = ReturnValue : &:r13_14, m28_12
# 13| v13_16(void) = UnmodeledUse : mu*
# 13| v13_17(void) = AliasedUse : ~m28_1
# 13| v13_18(void) = ExitFunction :
# 28| m28_1(int) = Phi : from 4:m21_1, from 5:m25_7
# 28| m28_2(int) = Phi : from 4:m22_7, from 5:m21_2
# 28| m28_3(unknown) = Phi : from 4:m22_8, from 5:m25_8
# 28| r28_4(glval<int>) = VariableAddress[#return] :
# 28| r28_5(glval<Point *>) = VariableAddress[p] :
# 28| r28_6(Point *) = Load : &:r28_5, m13_5
# 28| r28_7(glval<int>) = FieldAddress[x] : r28_6
# 28| r28_8(int) = Load : &:r28_7, m28_2
# 28| r28_9(glval<Point *>) = VariableAddress[p] :
# 28| r28_10(Point *) = Load : &:r28_9, m13_5
# 28| r28_11(glval<int>) = FieldAddress[y] : r28_10
# 28| r28_12(int) = Load : &:r28_11, m28_1
# 28| r28_13(int) = Add : r28_8, r28_12
# 28| m28_14(int) = Store : &:r28_4, r28_13
# 13| v13_12(void) = ReturnIndirection : &:r13_6, m28_3
# 13| r13_13(glval<int>) = VariableAddress[#return] :
# 13| v13_14(void) = ReturnValue : &:r13_13, m28_14
# 13| v13_15(void) = UnmodeledUse : mu*
# 13| v13_16(void) = AliasedUse : ~m13_2
# 13| v13_17(void) = ExitFunction :
# 31| int UnreachableViaGoto()
# 31| Block 0
@@ -212,7 +215,6 @@ ssa.cpp:
# 68| m68_7(char *) = InitializeParameter[p] : &:r68_6
# 68| r68_8(char *) = Load : &:r68_6, m68_7
# 68| m68_9(unknown) = InitializeIndirection[p] : &:r68_8
# 68| m68_10(unknown) = Chi : total:m68_2, partial:m68_9
#-----| Goto -> Block 3
# 70| Block 1
@@ -229,16 +231,16 @@ ssa.cpp:
# 71| Block 2
# 71| v71_1(void) = NoOp :
# 68| v68_11(void) = ReturnIndirection : &:r68_8, ~m69_3
# 68| v68_12(void) = ReturnVoid :
# 68| v68_13(void) = UnmodeledUse : mu*
# 68| v68_14(void) = AliasedUse : ~m69_3
# 68| v68_15(void) = ExitFunction :
# 68| v68_10(void) = ReturnIndirection : &:r68_8, m68_9
# 68| v68_11(void) = ReturnVoid :
# 68| v68_12(void) = UnmodeledUse : mu*
# 68| v68_13(void) = AliasedUse : ~m69_3
# 68| v68_14(void) = ExitFunction :
# 69| Block 3
# 69| m69_1(char *) = Phi : from 0:m68_7, from 1:m70_6
# 69| m69_2(int) = Phi : from 0:m68_5, from 1:m69_8
# 69| m69_3(unknown) = Phi : from 0:~m68_10, from 1:~m70_9
# 69| m69_3(unknown) = Phi : from 0:~m68_2, from 1:~m70_9
# 69| r69_4(glval<int>) = VariableAddress[n] :
# 69| r69_5(int) = Load : &:r69_4, m69_2
# 69| r69_6(int) = Constant[1] :
@@ -759,20 +761,19 @@ ssa.cpp:
# 179| m179_5(int *) = InitializeParameter[p] : &:r179_4
# 179| r179_6(int *) = Load : &:r179_4, m179_5
# 179| m179_7(unknown) = InitializeIndirection[p] : &:r179_6
# 179| m179_8(unknown) = Chi : total:m179_2, partial:m179_7
# 180| m180_1(unknown) = InlineAsm : ~m179_8
# 180| m180_2(unknown) = Chi : total:m179_8, partial:m180_1
# 180| m180_1(unknown) = InlineAsm : ~m179_2
# 180| m180_2(unknown) = Chi : total:m179_2, partial:m180_1
# 181| r181_1(glval<int>) = VariableAddress[#return] :
# 181| r181_2(glval<int *>) = VariableAddress[p] :
# 181| r181_3(int *) = Load : &:r181_2, m179_5
# 181| r181_4(int) = Load : &:r181_3, ~m180_2
# 181| r181_4(int) = Load : &:r181_3, ~m179_7
# 181| m181_5(int) = Store : &:r181_1, r181_4
# 179| v179_9(void) = ReturnIndirection : &:r179_6, ~m180_2
# 179| r179_10(glval<int>) = VariableAddress[#return] :
# 179| v179_11(void) = ReturnValue : &:r179_10, m181_5
# 179| v179_12(void) = UnmodeledUse : mu*
# 179| v179_13(void) = AliasedUse : ~m180_2
# 179| v179_14(void) = ExitFunction :
# 179| v179_8(void) = ReturnIndirection : &:r179_6, m179_7
# 179| r179_9(glval<int>) = VariableAddress[#return] :
# 179| v179_10(void) = ReturnValue : &:r179_9, m181_5
# 179| v179_11(void) = UnmodeledUse : mu*
# 179| v179_12(void) = AliasedUse : ~m180_2
# 179| v179_13(void) = ExitFunction :
# 184| void AsmStmtWithOutputs(unsigned int&, unsigned int&, unsigned int&, unsigned int&)
# 184| Block 0
@@ -783,45 +784,41 @@ ssa.cpp:
# 184| m184_5(unsigned int &) = InitializeParameter[a] : &:r184_4
# 184| r184_6(unsigned int &) = Load : &:r184_4, m184_5
# 184| m184_7(unknown) = InitializeIndirection[a] : &:r184_6
# 184| m184_8(unknown) = Chi : total:m184_2, partial:m184_7
# 184| r184_9(glval<unsigned int &>) = VariableAddress[b] :
# 184| m184_10(unsigned int &) = InitializeParameter[b] : &:r184_9
# 184| r184_11(unsigned int &) = Load : &:r184_9, m184_10
# 184| m184_12(unknown) = InitializeIndirection[b] : &:r184_11
# 184| m184_13(unknown) = Chi : total:m184_8, partial:m184_12
# 184| r184_14(glval<unsigned int &>) = VariableAddress[c] :
# 184| m184_15(unsigned int &) = InitializeParameter[c] : &:r184_14
# 184| r184_16(unsigned int &) = Load : &:r184_14, m184_15
# 184| m184_17(unknown) = InitializeIndirection[c] : &:r184_16
# 184| m184_18(unknown) = Chi : total:m184_13, partial:m184_17
# 184| r184_19(glval<unsigned int &>) = VariableAddress[d] :
# 184| m184_20(unsigned int &) = InitializeParameter[d] : &:r184_19
# 184| r184_21(unsigned int &) = Load : &:r184_19, m184_20
# 184| m184_22(unknown) = InitializeIndirection[d] : &:r184_21
# 184| m184_23(unknown) = Chi : total:m184_18, partial:m184_22
# 184| r184_8(glval<unsigned int &>) = VariableAddress[b] :
# 184| m184_9(unsigned int &) = InitializeParameter[b] : &:r184_8
# 184| r184_10(unsigned int &) = Load : &:r184_8, m184_9
# 184| m184_11(unknown) = InitializeIndirection[b] : &:r184_10
# 184| r184_12(glval<unsigned int &>) = VariableAddress[c] :
# 184| m184_13(unsigned int &) = InitializeParameter[c] : &:r184_12
# 184| r184_14(unsigned int &) = Load : &:r184_12, m184_13
# 184| m184_15(unknown) = InitializeIndirection[c] : &:r184_14
# 184| r184_16(glval<unsigned int &>) = VariableAddress[d] :
# 184| m184_17(unsigned int &) = InitializeParameter[d] : &:r184_16
# 184| r184_18(unsigned int &) = Load : &:r184_16, m184_17
# 184| m184_19(unknown) = InitializeIndirection[d] : &:r184_18
# 189| r189_1(glval<unsigned int &>) = VariableAddress[a] :
# 189| r189_2(unsigned int &) = Load : &:r189_1, m184_5
# 189| r189_3(glval<unsigned int>) = CopyValue : r189_2
# 189| r189_4(glval<unsigned int &>) = VariableAddress[b] :
# 189| r189_5(unsigned int &) = Load : &:r189_4, m184_10
# 189| r189_5(unsigned int &) = Load : &:r189_4, m184_9
# 189| r189_6(glval<unsigned int>) = CopyValue : r189_5
# 190| r190_1(glval<unsigned int &>) = VariableAddress[c] :
# 190| r190_2(unsigned int &) = Load : &:r190_1, m184_15
# 190| r190_3(unsigned int) = Load : &:r190_2, ~m184_23
# 190| r190_2(unsigned int &) = Load : &:r190_1, m184_13
# 190| r190_3(unsigned int) = Load : &:r190_2, ~m184_15
# 190| r190_4(glval<unsigned int &>) = VariableAddress[d] :
# 190| r190_5(unsigned int &) = Load : &:r190_4, m184_20
# 190| r190_6(unsigned int) = Load : &:r190_5, ~m184_23
# 186| m186_1(unknown) = InlineAsm : ~m184_23, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6
# 186| m186_2(unknown) = Chi : total:m184_23, partial:m186_1
# 190| r190_5(unsigned int &) = Load : &:r190_4, m184_17
# 190| r190_6(unsigned int) = Load : &:r190_5, ~m184_19
# 186| m186_1(unknown) = InlineAsm : ~m184_11, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6
# 186| m186_2(unknown) = Chi : total:m184_11, partial:m186_1
# 192| v192_1(void) = NoOp :
# 184| v184_24(void) = ReturnIndirection : &:r184_6, ~m186_2
# 184| v184_25(void) = ReturnIndirection : &:r184_11, ~m186_2
# 184| v184_26(void) = ReturnIndirection : &:r184_16, ~m186_2
# 184| v184_27(void) = ReturnIndirection : &:r184_21, ~m186_2
# 184| v184_28(void) = ReturnVoid :
# 184| v184_29(void) = UnmodeledUse : mu*
# 184| v184_30(void) = AliasedUse : ~m186_2
# 184| v184_31(void) = ExitFunction :
# 184| v184_20(void) = ReturnIndirection : &:r184_6, ~m186_2
# 184| v184_21(void) = ReturnIndirection : &:r184_10, ~m186_2
# 184| v184_22(void) = ReturnIndirection : &:r184_14, m184_15
# 184| v184_23(void) = ReturnIndirection : &:r184_18, m184_19
# 184| v184_24(void) = ReturnVoid :
# 184| v184_25(void) = UnmodeledUse : mu*
# 184| v184_26(void) = AliasedUse : ~m186_2
# 184| v184_27(void) = ExitFunction :
# 198| int PureFunctions(char*, char*, int)
# 198| Block 0
@@ -832,41 +829,39 @@ ssa.cpp:
# 198| m198_5(char *) = InitializeParameter[str1] : &:r198_4
# 198| r198_6(char *) = Load : &:r198_4, m198_5
# 198| m198_7(unknown) = InitializeIndirection[str1] : &:r198_6
# 198| m198_8(unknown) = Chi : total:m198_2, partial:m198_7
# 198| r198_9(glval<char *>) = VariableAddress[str2] :
# 198| m198_10(char *) = InitializeParameter[str2] : &:r198_9
# 198| r198_11(char *) = Load : &:r198_9, m198_10
# 198| m198_12(unknown) = InitializeIndirection[str2] : &:r198_11
# 198| m198_13(unknown) = Chi : total:m198_8, partial:m198_12
# 198| r198_14(glval<int>) = VariableAddress[x] :
# 198| m198_15(int) = InitializeParameter[x] : &:r198_14
# 198| r198_8(glval<char *>) = VariableAddress[str2] :
# 198| m198_9(char *) = InitializeParameter[str2] : &:r198_8
# 198| r198_10(char *) = Load : &:r198_8, m198_9
# 198| m198_11(unknown) = InitializeIndirection[str2] : &:r198_10
# 198| r198_12(glval<int>) = VariableAddress[x] :
# 198| m198_13(int) = InitializeParameter[x] : &:r198_12
# 199| r199_1(glval<int>) = VariableAddress[ret] :
# 199| r199_2(glval<unknown>) = FunctionAddress[strcmp] :
# 199| r199_3(glval<char *>) = VariableAddress[str1] :
# 199| r199_4(char *) = Load : &:r199_3, m198_5
# 199| r199_5(char *) = Convert : r199_4
# 199| r199_6(glval<char *>) = VariableAddress[str2] :
# 199| r199_7(char *) = Load : &:r199_6, m198_10
# 199| r199_7(char *) = Load : &:r199_6, m198_9
# 199| r199_8(char *) = Convert : r199_7
# 199| r199_9(int) = Call : func:r199_2, 0:r199_5, 1:r199_8
# 199| v199_10(void) = ^CallReadSideEffect : ~m198_13
# 199| v199_11(void) = ^BufferReadSideEffect[0] : &:r199_5, ~m198_13
# 199| v199_12(void) = ^BufferReadSideEffect[1] : &:r199_8, ~m198_13
# 199| v199_10(void) = ^CallReadSideEffect : ~m198_2
# 199| v199_11(void) = ^BufferReadSideEffect[0] : &:r199_5, ~m198_7
# 199| v199_12(void) = ^BufferReadSideEffect[1] : &:r199_8, ~m198_11
# 199| m199_13(int) = Store : &:r199_1, r199_9
# 200| r200_1(glval<unknown>) = FunctionAddress[strlen] :
# 200| r200_2(glval<char *>) = VariableAddress[str1] :
# 200| r200_3(char *) = Load : &:r200_2, m198_5
# 200| r200_4(char *) = Convert : r200_3
# 200| r200_5(int) = Call : func:r200_1, 0:r200_4
# 200| v200_6(void) = ^CallReadSideEffect : ~m198_13
# 200| v200_7(void) = ^BufferReadSideEffect[0] : &:r200_4, ~m198_13
# 200| v200_6(void) = ^CallReadSideEffect : ~m198_2
# 200| v200_7(void) = ^BufferReadSideEffect[0] : &:r200_4, ~m198_7
# 200| r200_8(glval<int>) = VariableAddress[ret] :
# 200| r200_9(int) = Load : &:r200_8, m199_13
# 200| r200_10(int) = Add : r200_9, r200_5
# 200| m200_11(int) = Store : &:r200_8, r200_10
# 201| r201_1(glval<unknown>) = FunctionAddress[abs] :
# 201| r201_2(glval<int>) = VariableAddress[x] :
# 201| r201_3(int) = Load : &:r201_2, m198_15
# 201| r201_3(int) = Load : &:r201_2, m198_13
# 201| r201_4(int) = Call : func:r201_1, 0:r201_3
# 201| r201_5(glval<int>) = VariableAddress[ret] :
# 201| r201_6(int) = Load : &:r201_5, m200_11
@@ -876,13 +871,13 @@ ssa.cpp:
# 202| r202_2(glval<int>) = VariableAddress[ret] :
# 202| r202_3(int) = Load : &:r202_2, m201_8
# 202| m202_4(int) = Store : &:r202_1, r202_3
# 198| v198_16(void) = ReturnIndirection : &:r198_6, ~m198_13
# 198| v198_17(void) = ReturnIndirection : &:r198_11, ~m198_13
# 198| r198_18(glval<int>) = VariableAddress[#return] :
# 198| v198_19(void) = ReturnValue : &:r198_18, m202_4
# 198| v198_20(void) = UnmodeledUse : mu*
# 198| v198_21(void) = AliasedUse : ~m198_13
# 198| v198_22(void) = ExitFunction :
# 198| v198_14(void) = ReturnIndirection : &:r198_6, m198_7
# 198| v198_15(void) = ReturnIndirection : &:r198_10, m198_11
# 198| r198_16(glval<int>) = VariableAddress[#return] :
# 198| v198_17(void) = ReturnValue : &:r198_16, m202_4
# 198| v198_18(void) = UnmodeledUse : mu*
# 198| v198_19(void) = AliasedUse : ~m198_2
# 198| v198_20(void) = ExitFunction :
# 207| int ModeledCallTarget(int)
# 207| Block 0

View File

@@ -0,0 +1,6 @@
/**
* @kind graph
*/
import semmle.code.cpp.ir.implementation.aliased_ssa.PrintIR
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IRSanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,22 @@
missingOperand
unexpectedOperand
duplicateOperand
missingPhiOperand
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
ambiguousSuccessors
unexplainedLoop
unnecessaryPhiInstruction
operandAcrossFunctions
instructionWithoutUniqueBlock
containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSASanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,2 @@
multipleOperandMemoryLocations
missingVirtualVariableForMemoryLocation

View File

@@ -0,0 +1,6 @@
/**
* @kind graph
*/
import semmle.code.cpp.ir.implementation.unaliased_ssa.PrintIR
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.unaliased_ssa.IRSanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,22 @@
missingOperand
unexpectedOperand
duplicateOperand
missingPhiOperand
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
ambiguousSuccessors
unexplainedLoop
unnecessaryPhiInstruction
operandAcrossFunctions
instructionWithoutUniqueBlock
containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSASanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,2 @@
multipleOperandMemoryLocations
missingVirtualVariableForMemoryLocation

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -56,8 +56,8 @@ string functionName(Function f) {
(
if exists(f.getATemplateArgument())
then
templateArgs = "<" + concat(int i | | f.getTemplateArgument(i).toString(), "," order by i) +
">"
templateArgs =
"<" + concat(int i | | f.getTemplateArgument(i).toString(), "," order by i) + ">"
else templateArgs = ""
) and
args = "(" + concat(int i | | f.getParameter(i).getType().toString(), "," order by i) + ")"

View File

@@ -4,7 +4,8 @@ from Function f, string call
where
if exists(f.getACallToThisFunction())
then
call = f.getACallToThisFunction().getLocation().toString() + " " +
call =
f.getACallToThisFunction().getLocation().toString() + " " +
f.getACallToThisFunction().toString()
else call = "<none>"
select f, f.getType(), call

View File

@@ -7,7 +7,8 @@ string functionName(Function f) {
(
if exists(f.getATemplateArgument())
then
templateArgs = "<" +
templateArgs =
"<" +
concat(int i |
exists(f.getTemplateArgument(i))
|
@@ -15,7 +16,8 @@ string functionName(Function f) {
) + ">"
else templateArgs = ""
) and
args = "(" +
args =
"(" +
concat(int i |
exists(f.getParameter(i))
|

View File

@@ -21,8 +21,8 @@ predicate isSetFlowEnd(boolean isEdge, int x, int y, string label) {
(setflow(x, _) or setflow(_, x)) and
isEdge = false and
x = y and
label = "set: {" + concat(Element e | pointstosets(x, unresolveElement(e)) | e.toString(), ", ") +
"}"
label =
"set: {" + concat(Element e | pointstosets(x, unresolveElement(e)) | e.toString(), ", ") + "}"
}
predicate isSetFlow(boolean isEdge, int x, int y, string label) {
@@ -35,8 +35,8 @@ predicate isPointsToSetSrc(boolean isEdge, int x, int y, string label) {
pointstosets(x, _) and
isEdge = false and
x = y and
label = "set: {" + concat(Element e | pointstosets(x, unresolveElement(e)) | e.toString(), ", ") +
"}"
label =
"set: {" + concat(Element e | pointstosets(x, unresolveElement(e)) | e.toString(), ", ") + "}"
}
predicate isPointsToSetDest(boolean isEdge, Element x, Element y, string label) {
@@ -57,7 +57,8 @@ predicate isPointsToSetDest(boolean isEdge, Element x, Element y, string label)
predicate isPointsToSets(boolean isEdge, int x, Element y, string label) {
isEdge = true and
pointstosets(x, unresolveElement(y)) and
label = "pt: {" + concat(Element e | pointstosets(x, unresolveElement(e)) | e.toString(), ", ") +
label =
"pt: {" + concat(Element e | pointstosets(x, unresolveElement(e)) | e.toString(), ", ") +
"} -> " + y.toString()
}

View File

@@ -16,8 +16,7 @@
| inline_assembly.c:10:3:10:7 | Store: ... = ... | positive strictlyPositive |
| inline_assembly.c:10:7:10:7 | Constant: (unsigned int)... | positive strictlyPositive |
| inline_assembly.c:12:32:12:32 | Load: y | positive strictlyPositive |
| inline_assembly.c:21:29:21:29 | Load: x | positive |
| inline_assembly.c:21:32:21:32 | Load: y | positive |
| inline_assembly.c:21:32:21:32 | Load: y | positive strictlyPositive |
| minmax.c:16:9:16:10 | Constant: 1 | positive strictlyPositive |
| minmax.c:16:9:16:10 | Store: 1 | positive strictlyPositive |
| minmax.c:16:16:16:17 | Constant: 2 | positive strictlyPositive |

View File

@@ -2,6 +2,6 @@ import cpp
from Struct s, string distinct
where
distinct = count(Struct x | x.getName() = s.getName()) + " different struct(s) called " +
s.getName()
distinct =
count(Struct x | x.getName() = s.getName()) + " different struct(s) called " + s.getName()
select s, distinct

View File

@@ -2,9 +2,10 @@ import cpp
import semmle.code.cpp.controlflow.SubBasicBlocks
string subBasicBlockDebugInfo(SubBasicBlock sbb) {
result = sbb.getStart().toString() + " [line " + sbb.getStart().getLocation().getStartLine() + "-"
+ sbb.getEnd().getLocation().getEndLine() + ", " + sbb.getNumberOfNodes() + " nodes, " +
"pos " + (sbb.getRankInBasicBlock(_) - 1) +
result =
sbb.getStart().toString() + " [line " + sbb.getStart().getLocation().getStartLine() + "-" +
sbb.getEnd().getLocation().getEndLine() + ", " + sbb.getNumberOfNodes() + " nodes, " + "pos " +
(sbb.getRankInBasicBlock(_) - 1) +
any(string s | if sbb.firstInBB() then s = " (first in BB)" else s = "") +
any(string s | if sbb.lastInBB() then s = " (last in BB)" else s = "") + ", " +
count(sbb.getAPredecessor()) + " predecessors, " + count(sbb.getASuccessor()) + " successors" +

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}
@@ -66,7 +67,8 @@ Element getScopeElement(ControlFlowNode x) {
string getScopeName(ControlFlowNode x) {
exists(Function scope | scope = getScopeElement(x) |
differentScope(scope) and
result = scope.getFile().getBaseName().splitAt(".", 0) + "__" +
result =
scope.getFile().getBaseName().splitAt(".", 0) + "__" +
scope.getQualifiedName().replaceAll("::", "_")
)
or

View File

@@ -27,7 +27,6 @@ missingOperand
| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() |
| try_catch.cpp:13:5:13:16 | Chi: call to exn1 | Instruction 'Chi' is missing an expected operand with tag 'ChiTotal' in function '$@'. | try_catch.cpp:11:6:11:17 | IR: bypass_catch | void bypass_catch() |
unexpectedOperand
duplicateOperand
missingPhiOperand
@@ -36,14 +35,14 @@ missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
| VacuousDestructorCall.cpp:2:29:2:29 | Chi: y |
| VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y |
| condition_decls.cpp:16:19:16:20 | Chi: call to BoxedInt |
| condition_decls.cpp:26:23:26:24 | Chi: call to BoxedInt |
| condition_decls.cpp:41:22:41:23 | Chi: call to BoxedInt |
| condition_decls.cpp:48:52:48:53 | Chi: call to BoxedInt |
| cpp17.cpp:15:11:15:21 | Convert: (void *)... |
| misc.c:171:10:171:13 | Uninitialized: definition of str2 |
| misc.c:219:47:219:48 | Chi: sp |
| misc.c:219:47:219:48 | InitializeIndirection: sp |
| ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x |
| ms_try_mix.cpp:11:12:11:15 | Chi: call to C |
| ms_try_mix.cpp:28:12:28:15 | Chi: call to C |

View File

@@ -9,7 +9,8 @@ class FunctionMonkeyPatch extends Function {
(
if exists(this.getATemplateArgument())
then
templateArgs = "<" +
templateArgs =
"<" +
concat(int i |
exists(this.getTemplateArgument(i))
|
@@ -17,7 +18,8 @@ class FunctionMonkeyPatch extends Function {
) + ">"
else templateArgs = ""
) and
args = "(" +
args =
"(" +
concat(int i |
exists(this.getParameter(i))
|

View File

@@ -266,8 +266,6 @@ test.cpp:
# 39| valnum = m39_9
# 39| m39_11(unknown) = InitializeIndirection[p2] : &:r39_10
# 39| valnum = unique
# 39| m39_12(unknown) = Chi : total:m39_2, partial:m39_11
# 39| valnum = unique
# 40| r40_1(glval<int>) = VariableAddress[x] :
# 40| valnum = r40_1
# 40| m40_2(int) = Uninitialized[x] : &:r40_1
@@ -292,7 +290,7 @@ test.cpp:
# 43| valnum = r43_5
# 43| r43_6(glval<int>) = VariableAddress[global03] :
# 43| valnum = r43_6
# 43| r43_7(int) = Load : &:r43_6, ~m39_12
# 43| r43_7(int) = Load : &:r43_6, ~m39_2
# 43| valnum = unique
# 43| r43_8(int) = Add : r43_5, r43_7
# 43| valnum = r43_8
@@ -310,7 +308,7 @@ test.cpp:
# 44| valnum = m39_9
# 44| m44_5(int) = Store : &:r44_4, r44_1
# 44| valnum = r44_1
# 44| m44_6(unknown) = Chi : total:m39_12, partial:m44_5
# 44| m44_6(unknown) = Chi : total:m39_11, partial:m44_5
# 44| valnum = unique
# 45| r45_1(glval<int>) = VariableAddress[p0] :
# 45| valnum = r39_4
@@ -324,7 +322,7 @@ test.cpp:
# 45| valnum = r43_5
# 45| r45_6(glval<int>) = VariableAddress[global03] :
# 45| valnum = r43_6
# 45| r45_7(int) = Load : &:r45_6, ~m44_6
# 45| r45_7(int) = Load : &:r45_6, ~m39_2
# 45| valnum = unique
# 45| r45_8(int) = Add : r45_5, r45_7
# 45| valnum = r45_8
@@ -341,13 +339,13 @@ test.cpp:
# 46| m46_4(int) = Store : &:r46_3, r46_2
# 46| valnum = r45_8
# 47| v47_1(void) = NoOp :
# 39| v39_13(void) = ReturnIndirection : &:r39_10, ~m44_6
# 39| r39_14(glval<int>) = VariableAddress[#return] :
# 39| v39_12(void) = ReturnIndirection : &:r39_10, ~m44_6
# 39| r39_13(glval<int>) = VariableAddress[#return] :
# 39| valnum = unique
# 39| v39_15(void) = ReturnValue : &:r39_14
# 39| v39_16(void) = UnmodeledUse : mu*
# 39| v39_17(void) = AliasedUse : ~m44_6
# 39| v39_18(void) = ExitFunction :
# 39| v39_14(void) = ReturnValue : &:r39_13
# 39| v39_15(void) = UnmodeledUse : mu*
# 39| v39_16(void) = AliasedUse : ~m39_2
# 39| v39_17(void) = ExitFunction :
# 49| unsigned int my_strspn(char const*, char const*)
# 49| Block 0
@@ -364,17 +362,13 @@ test.cpp:
# 49| valnum = m49_5
# 49| m49_7(unknown) = InitializeIndirection[str] : &:r49_6
# 49| valnum = unique
# 49| m49_8(unknown) = Chi : total:m49_2, partial:m49_7
# 49| valnum = unique
# 49| r49_9(glval<char *>) = VariableAddress[chars] :
# 49| valnum = r49_9
# 49| m49_10(char *) = InitializeParameter[chars] : &:r49_9
# 49| valnum = m49_10
# 49| r49_11(char *) = Load : &:r49_9, m49_10
# 49| valnum = m49_10
# 49| m49_12(unknown) = InitializeIndirection[chars] : &:r49_11
# 49| valnum = unique
# 49| m49_13(unknown) = Chi : total:m49_8, partial:m49_12
# 49| r49_8(glval<char *>) = VariableAddress[chars] :
# 49| valnum = r49_8
# 49| m49_9(char *) = InitializeParameter[chars] : &:r49_8
# 49| valnum = m49_9
# 49| r49_10(char *) = Load : &:r49_8, m49_9
# 49| valnum = m49_9
# 49| m49_11(unknown) = InitializeIndirection[chars] : &:r49_10
# 49| valnum = unique
# 50| r50_1(glval<char *>) = VariableAddress[ptr] :
# 50| valnum = r50_1
@@ -395,7 +389,7 @@ test.cpp:
# 53| valnum = r49_4
# 53| r53_3(char *) = Load : &:r53_2, m49_5
# 53| valnum = m49_5
# 53| r53_4(char) = Load : &:r53_3, ~m49_13
# 53| r53_4(char) = Load : &:r53_3, ~m49_7
# 53| valnum = unique
# 53| r53_5(int) = Convert : r53_4
# 53| valnum = unique
@@ -409,13 +403,13 @@ test.cpp:
# 55| Block 2
# 55| r55_1(glval<char *>) = VariableAddress[chars] :
# 55| valnum = r49_9
# 55| r55_2(char *) = Load : &:r55_1, m49_10
# 55| valnum = m49_10
# 55| valnum = r49_8
# 55| r55_2(char *) = Load : &:r55_1, m49_9
# 55| valnum = m49_9
# 55| r55_3(glval<char *>) = VariableAddress[ptr] :
# 55| valnum = r50_1
# 55| m55_4(char *) = Store : &:r55_3, r55_2
# 55| valnum = m49_10
# 55| valnum = m49_9
#-----| Goto -> Block 3
# 56| Block 3
@@ -425,7 +419,7 @@ test.cpp:
# 56| valnum = r50_1
# 56| r56_3(char *) = Load : &:r56_2, m56_1
# 56| valnum = m56_1
# 56| r56_4(char) = Load : &:r56_3, ~m49_13
# 56| r56_4(char) = Load : &:r56_3, ~m49_2
# 56| valnum = unique
# 56| r56_5(int) = Convert : r56_4
# 56| valnum = unique
@@ -433,7 +427,7 @@ test.cpp:
# 56| valnum = r49_4
# 56| r56_7(char *) = Load : &:r56_6, m49_5
# 56| valnum = m49_5
# 56| r56_8(char) = Load : &:r56_7, ~m49_13
# 56| r56_8(char) = Load : &:r56_7, ~m49_7
# 56| valnum = unique
# 56| r56_9(int) = Convert : r56_8
# 56| valnum = unique
@@ -448,7 +442,7 @@ test.cpp:
# 56| valnum = r50_1
# 56| r56_13(char *) = Load : &:r56_12, m56_1
# 56| valnum = m56_1
# 56| r56_14(char) = Load : &:r56_13, ~m49_13
# 56| r56_14(char) = Load : &:r56_13, ~m49_2
# 56| valnum = unique
# 56| r56_15(int) = Convert : r56_14
# 56| valnum = unique
@@ -478,7 +472,7 @@ test.cpp:
# 59| valnum = r50_1
# 59| r59_2(char *) = Load : &:r59_1, m56_1
# 59| valnum = m56_1
# 59| r59_3(char) = Load : &:r59_2, ~m49_13
# 59| r59_3(char) = Load : &:r59_2, ~m49_2
# 59| valnum = unique
# 59| r59_4(int) = Convert : r59_3
# 59| valnum = unique
@@ -517,14 +511,14 @@ test.cpp:
# 65| valnum = m53_1
# 65| m65_4(unsigned int) = Store : &:r65_1, r65_3
# 65| valnum = m53_1
# 49| v49_14(void) = ReturnIndirection : &:r49_6, ~m49_13
# 49| v49_15(void) = ReturnIndirection : &:r49_11, ~m49_13
# 49| r49_16(glval<unsigned int>) = VariableAddress[#return] :
# 49| v49_12(void) = ReturnIndirection : &:r49_6, m49_7
# 49| v49_13(void) = ReturnIndirection : &:r49_10, m49_11
# 49| r49_14(glval<unsigned int>) = VariableAddress[#return] :
# 49| valnum = r65_1
# 49| v49_17(void) = ReturnValue : &:r49_16, m65_4
# 49| v49_18(void) = UnmodeledUse : mu*
# 49| v49_19(void) = AliasedUse : ~m49_13
# 49| v49_20(void) = ExitFunction :
# 49| v49_15(void) = ReturnValue : &:r49_14, m65_4
# 49| v49_16(void) = UnmodeledUse : mu*
# 49| v49_17(void) = AliasedUse : ~m49_2
# 49| v49_18(void) = ExitFunction :
# 75| void test04(two_values*)
# 75| Block 0
@@ -541,17 +535,15 @@ test.cpp:
# 75| valnum = m75_5
# 75| m75_7(unknown) = InitializeIndirection[vals] : &:r75_6
# 75| valnum = unique
# 75| m75_8(unknown) = Chi : total:m75_2, partial:m75_7
# 75| valnum = unique
# 77| r77_1(glval<signed short>) = VariableAddress[v] :
# 77| valnum = r77_1
# 77| r77_2(glval<unknown>) = FunctionAddress[getAValue] :
# 77| valnum = unique
# 77| r77_3(int) = Call : func:r77_2
# 77| valnum = unique
# 77| m77_4(unknown) = ^CallSideEffect : ~m75_8
# 77| m77_4(unknown) = ^CallSideEffect : ~m75_2
# 77| valnum = unique
# 77| m77_5(unknown) = Chi : total:m75_8, partial:m77_4
# 77| m77_5(unknown) = Chi : total:m75_2, partial:m77_4
# 77| valnum = unique
# 77| r77_6(signed short) = Convert : r77_3
# 77| valnum = r77_6
@@ -569,7 +561,7 @@ test.cpp:
# 79| valnum = m75_5
# 79| r79_6(glval<signed short>) = FieldAddress[val1] : r79_5
# 79| valnum = unique
# 79| r79_7(signed short) = Load : &:r79_6, ~m77_5
# 79| r79_7(signed short) = Load : &:r79_6, ~m75_7
# 79| valnum = unique
# 79| r79_8(int) = Convert : r79_7
# 79| valnum = unique
@@ -579,7 +571,7 @@ test.cpp:
# 79| valnum = m75_5
# 79| r79_11(glval<signed short>) = FieldAddress[val2] : r79_10
# 79| valnum = unique
# 79| r79_12(signed short) = Load : &:r79_11, ~m77_5
# 79| r79_12(signed short) = Load : &:r79_11, ~m75_7
# 79| valnum = unique
# 79| r79_13(int) = Convert : r79_12
# 79| valnum = unique
@@ -612,11 +604,11 @@ test.cpp:
# 82| m82_1(unknown) = Phi : from 0:~m77_5, from 1:~m80_4
# 82| valnum = unique
# 82| v82_2(void) = NoOp :
# 75| v75_9(void) = ReturnIndirection : &:r75_6, ~m82_1
# 75| v75_10(void) = ReturnVoid :
# 75| v75_11(void) = UnmodeledUse : mu*
# 75| v75_12(void) = AliasedUse : ~m82_1
# 75| v75_13(void) = ExitFunction :
# 75| v75_8(void) = ReturnIndirection : &:r75_6, m75_7
# 75| v75_9(void) = ReturnVoid :
# 75| v75_10(void) = UnmodeledUse : mu*
# 75| v75_11(void) = AliasedUse : ~m82_1
# 75| v75_12(void) = ExitFunction :
# 84| void test05(int, int, void*)
# 84| Block 0
@@ -641,8 +633,6 @@ test.cpp:
# 84| valnum = m84_9
# 84| m84_11(unknown) = InitializeIndirection[p] : &:r84_10
# 84| valnum = unique
# 84| m84_12(unknown) = Chi : total:m84_2, partial:m84_11
# 84| valnum = unique
# 86| r86_1(glval<int>) = VariableAddress[v] :
# 86| valnum = r86_1
# 86| m86_2(int) = Uninitialized[v] : &:r86_1
@@ -671,11 +661,11 @@ test.cpp:
# 88| m88_10(int) = Store : &:r88_9, r88_8
# 88| valnum = m88_6
# 89| v89_1(void) = NoOp :
# 84| v84_13(void) = ReturnIndirection : &:r84_10, ~m84_12
# 84| v84_14(void) = ReturnVoid :
# 84| v84_15(void) = UnmodeledUse : mu*
# 84| v84_16(void) = AliasedUse : ~m84_12
# 84| v84_17(void) = ExitFunction :
# 84| v84_12(void) = ReturnIndirection : &:r84_10, m84_11
# 84| v84_13(void) = ReturnVoid :
# 84| v84_14(void) = UnmodeledUse : mu*
# 84| v84_15(void) = AliasedUse : ~m84_2
# 84| v84_16(void) = ExitFunction :
# 88| Block 2
# 88| r88_11(glval<int>) = VariableAddress[x] :
@@ -748,8 +738,6 @@ test.cpp:
# 104| valnum = m104_5
# 104| m104_7(unknown) = InitializeIndirection[pd] : &:r104_6
# 104| valnum = unique
# 104| m104_8(unknown) = Chi : total:m104_2, partial:m104_7
# 104| valnum = unique
# 105| r105_1(glval<int>) = VariableAddress[x] :
# 105| valnum = unique
# 105| r105_2(glval<Derived *>) = VariableAddress[pd] :
@@ -760,7 +748,7 @@ test.cpp:
# 105| valnum = r105_4
# 105| r105_5(glval<int>) = FieldAddress[b] : r105_4
# 105| valnum = r105_5
# 105| r105_6(int) = Load : &:r105_5, ~m104_8
# 105| r105_6(int) = Load : &:r105_5, ~m104_7
# 105| valnum = r105_6
# 105| m105_7(int) = Store : &:r105_1, r105_6
# 105| valnum = r105_6
@@ -782,7 +770,7 @@ test.cpp:
# 107| valnum = r105_4
# 107| r107_4(glval<int>) = FieldAddress[b] : r107_3
# 107| valnum = r105_5
# 107| r107_5(int) = Load : &:r107_4, ~m104_8
# 107| r107_5(int) = Load : &:r107_4, ~m104_7
# 107| valnum = r107_5
# 107| m107_6(int) = Store : &:r107_1, r107_5
# 107| valnum = r107_5
@@ -794,13 +782,13 @@ test.cpp:
# 109| valnum = r107_5
# 109| m109_4(int) = Store : &:r109_1, r109_3
# 109| valnum = r107_5
# 104| v104_9(void) = ReturnIndirection : &:r104_6, ~m104_8
# 104| r104_10(glval<int>) = VariableAddress[#return] :
# 104| v104_8(void) = ReturnIndirection : &:r104_6, m104_7
# 104| r104_9(glval<int>) = VariableAddress[#return] :
# 104| valnum = r109_1
# 104| v104_11(void) = ReturnValue : &:r104_10, m109_4
# 104| v104_12(void) = UnmodeledUse : mu*
# 104| v104_13(void) = AliasedUse : ~m104_8
# 104| v104_14(void) = ExitFunction :
# 104| v104_10(void) = ReturnValue : &:r104_9, m109_4
# 104| v104_11(void) = UnmodeledUse : mu*
# 104| v104_12(void) = AliasedUse : ~m104_2
# 104| v104_13(void) = ExitFunction :
# 112| void test06()
# 112| Block 0

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -4,6 +4,7 @@
| test.c:32:20:32:25 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.c:49:20:49:25 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.cpp:24:35:24:40 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.cpp:45:28:45:33 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.cpp:63:28:63:33 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.cpp:71:28:71:33 | call to malloc | This allocation does not include space to null-terminate the string. |
| test.cpp:79:28:79:33 | call to malloc | This allocation does not include space to null-terminate the string. |

View File

@@ -41,7 +41,7 @@ void good1(wchar_t *wstr) {
}
void bad3(char *str) {
// BAD -- zero-termination proved by sprintf (as destination) [NOT DETECTED]
// BAD -- zero-termination proved by sprintf (as destination)
char *buffer = (char *)malloc(strlen(str));
sprintf(buffer, "%s", str);
free(buffer);

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}

View File

@@ -5,7 +5,8 @@ class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
result =
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}