Merge remote-tracking branch 'upstream/main' into incomplete-url-string-sanitization

Conflicts:
	config/identical-files.json
	javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql
	javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll
	ruby/ql/src/queries/security/cwe-020/IncompleteUrlSubstringSanitization.qll
This commit is contained in:
Arthur Baars
2022-03-18 16:08:59 +01:00
1308 changed files with 77789 additions and 53601 deletions

50
.github/workflows/check-qldoc.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: "Check QLdoc coverage"
on:
pull_request:
paths:
- "*/ql/lib/**"
- .github/workflows/check-qldoc.yml
branches:
- main
- "rc/*"
jobs:
qldoc:
runs-on: ubuntu-latest
steps:
- name: Install CodeQL
run: |
gh extension install github/gh-codeql
gh codeql set-channel nightly
gh codeql version
env:
GITHUB_TOKEN: ${{ github.token }}
- uses: actions/checkout@v2
with:
fetch-depth: 2
- name: Check QLdoc coverage
shell: bash
run: |
EXIT_CODE=0
changed_lib_packs="$(git diff --name-only --diff-filter=ACMRT HEAD^ HEAD | { grep -o '^[a-z]*/ql/lib' || true; } | sort -u)"
for pack_dir in ${changed_lib_packs}; do
lang="${pack_dir%/ql/lib}"
gh codeql generate library-doc-coverage --output="${RUNNER_TEMP}/${lang}-current.txt" --dir="${pack_dir}"
done
git checkout HEAD^
for pack_dir in ${changed_lib_packs}; do
lang="${pack_dir%/ql/lib}"
gh codeql generate library-doc-coverage --output="${RUNNER_TEMP}/${lang}-baseline.txt" --dir="${pack_dir}"
awk -F, '{gsub(/"/,""); if ($4==0 && $6=="public") print "\""$3"\"" }' "${RUNNER_TEMP}/${lang}-current.txt" | sort -u > "${RUNNER_TEMP}/current-undocumented.txt"
awk -F, '{gsub(/"/,""); if ($4==0 && $6=="public") print "\""$3"\"" }' "${RUNNER_TEMP}/${lang}-baseline.txt" | sort -u > "${RUNNER_TEMP}/baseline-undocumented.txt"
UNDOCUMENTED="$(grep -f <(comm -13 "${RUNNER_TEMP}/baseline-undocumented.txt" "${RUNNER_TEMP}/current-undocumented.txt") "${RUNNER_TEMP}/${lang}-current.txt" || true)"
if [ -n "$UNDOCUMENTED" ]; then
echo "$UNDOCUMENTED" | awk -F, '{gsub(/"/,""); print "::warning file='"${pack_dir}"'/"$1",line="$2"::Missing QLdoc for "$5, $3 }'
EXIT_CODE=1
fi
done
exit "${EXIT_CODE}"

View File

@@ -0,0 +1,58 @@
import fs from "fs";
import path from "path";
import cp from "child_process";
function* walk(dir) {
for (const file of fs.readdirSync(dir)) {
const filePath = path.join(dir, file);
if (fs.statSync(filePath).isDirectory()) {
yield* walk(filePath);
} else {
yield filePath;
}
}
}
function* deprecatedFiles(dir) {
for (const file of walk(dir)) {
if (file.endsWith(".ql") || file.endsWith(".qll")) {
const contents = fs.readFileSync(file, "utf8");
if (/\sdeprecated\s/.test(contents)) {
yield file;
}
}
}
}
const blameRegExp =
/^(\^?\w+)\s.+\s+(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} (?:\+|-)\d{4})\s+(\d+)\).*$/;
function* deprecationMessages(dir) {
for (const file of deprecatedFiles(dir)) {
const blame = cp.execFileSync("git", ["blame", "--", file]);
const lines = blame.toString().split("\n");
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.includes(" deprecated ")) {
try {
const [_, sha, time, lineNumber] = line.match(blameRegExp);
const date = new Date(time);
// check if it's within the last 14 months (a year, plus 2 months for safety, in case a PR was delayed)
if (date.getTime() >= Date.now() - 14 * 31 * 24 * 60 * 60 * 1000) {
continue;
}
const message = `${file}:${lineNumber} was last updated on ${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
yield [message, date];
} catch (e) {
console.log(e);
console.log("----");
console.log(line);
console.log("----");
process.exit(0);
}
}
}
}
}
[...deprecationMessages(".")]
.sort((a, b) => a[1].getTime() - b[1].getTime())
.forEach((msg) => console.log(msg[0]));

View File

@@ -73,6 +73,14 @@
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll", "java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll" "csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll"
], ],
"Model as Data Generation Java/C# - Utils": [
"java/ql/src/utils/model-generator/ModelGeneratorUtils.qll",
"csharp/ql/src/utils/model-generator/ModelGeneratorUtils.qll"
],
"Model as Data Generation Java/C# - SummaryModels": [
"java/ql/src/utils/model-generator/CaptureSummaryModels.qll",
"csharp/ql/src/utils/model-generator/CaptureSummaryModels.qll"
],
"Sign Java/C#": [ "Sign Java/C#": [
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll", "java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll" "csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll"
@@ -426,7 +434,6 @@
"python/ql/src/Lexical/CommentedOutCodeMetricOverview.inc.qhelp" "python/ql/src/Lexical/CommentedOutCodeMetricOverview.inc.qhelp"
], ],
"FLinesOfDuplicatedCodeCommon.inc.qhelp": [ "FLinesOfDuplicatedCodeCommon.inc.qhelp": [
"cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCodeCommon.inc.qhelp",
"java/ql/src/Metrics/Files/FLinesOfDuplicatedCodeCommon.inc.qhelp", "java/ql/src/Metrics/Files/FLinesOfDuplicatedCodeCommon.inc.qhelp",
"javascript/ql/src/Metrics/FLinesOfDuplicatedCodeCommon.inc.qhelp", "javascript/ql/src/Metrics/FLinesOfDuplicatedCodeCommon.inc.qhelp",
"python/ql/src/Metrics/FLinesOfDuplicatedCodeCommon.inc.qhelp" "python/ql/src/Metrics/FLinesOfDuplicatedCodeCommon.inc.qhelp"
@@ -512,5 +519,13 @@
"IncompleteUrlSubstringSanitization": [ "IncompleteUrlSubstringSanitization": [
"javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll", "javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll",
"ruby/ql/src/queries/security/cwe-020/IncompleteUrlSubstringSanitization.qll" "ruby/ql/src/queries/security/cwe-020/IncompleteUrlSubstringSanitization.qll"
],
"Hostname Regexp queries": [
"javascript/ql/src/Security/CWE-020/HostnameRegexpShared.qll",
"ruby/ql/src/queries/security/cwe-020/HostnameRegexpShared.qll"
],
"ApiGraphModels": [
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll",
"ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll"
] ]
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Remove uniqueness constraint from the uuid property
compatibility: full

View File

@@ -1,3 +1,9 @@
## 0.0.11
### Minor Analysis Improvements
* Many queries now support structured bindings, as structured bindings are now handled in the IR translation.
## 0.0.10 ## 0.0.10
### New Features ### New Features
@@ -6,6 +12,7 @@
## 0.0.9 ## 0.0.9
## 0.0.8 ## 0.0.8
### Deprecated APIs ### Deprecated APIs

View File

@@ -54,11 +54,13 @@ class Options extends string {
* *
* By default, this holds for `exit`, `_exit`, `abort`, `__assert_fail`, * By default, this holds for `exit`, `_exit`, `abort`, `__assert_fail`,
* `longjmp`, `__builtin_unreachable` and any function with a * `longjmp`, `__builtin_unreachable` and any function with a
* `noreturn` attribute. * `noreturn` attribute or specifier.
*/ */
predicate exits(Function f) { predicate exits(Function f) {
f.getAnAttribute().hasName("noreturn") f.getAnAttribute().hasName("noreturn")
or or
f.getASpecifier().hasName("noreturn")
or
f.hasGlobalOrStdName([ f.hasGlobalOrStdName([
"exit", "_exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable" "exit", "_exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable"
]) ])

View File

@@ -39,7 +39,7 @@ class CustomOptions extends Options {
* *
* By default, this holds for `exit`, `_exit`, `abort`, `__assert_fail`, * By default, this holds for `exit`, `_exit`, `abort`, `__assert_fail`,
* `longjmp`, `error`, `__builtin_unreachable` and any function with a * `longjmp`, `error`, `__builtin_unreachable` and any function with a
* `noreturn` attribute. * `noreturn` attribute or specifier.
*/ */
override predicate exits(Function f) { Options.super.exits(f) } override predicate exits(Function f) { Options.super.exits(f) }

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.

View File

@@ -0,0 +1,5 @@
---
category: deprecated
---
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* `hasImplicitCopyConstructor` and `hasImplicitCopyAssignmentOperator` now correctly handle implicitly-deleted operators in templates.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* `DefaultOptions::exits` now holds for C11 functions with the `_Noreturn` or `noreturn` specifier.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* The data flow and taint tracking libraries have been extended with versions of `isBarrierIn`, `isBarrierOut`, and `isBarrierGuard`, respectively `isSanitizerIn`, `isSanitizerOut`, and `isSanitizerGuard`, that support flow states.

View File

@@ -0,0 +1,4 @@
---
category: breaking
---
* The flow state variants of `isBarrier` and `isAdditionalFlowStep` are no longer exposed in the taint tracking library. The `isSanitizer` and `isAdditionalTaintStep` predicates should be used instead.

View File

@@ -1,4 +1,5 @@
--- ## 0.0.11
category: minorAnalysis
--- ### Minor Analysis Improvements
* Many queries now support structured bindings, as structured bindings are now handled in the IR translation. * Many queries now support structured bindings, as structured bindings are now handled in the IR translation.

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.0.10 lastReleaseVersion: 0.0.11

View File

@@ -69,6 +69,4 @@ import semmle.code.cpp.Comments
import semmle.code.cpp.Preprocessor import semmle.code.cpp.Preprocessor
import semmle.code.cpp.Iteration import semmle.code.cpp.Iteration
import semmle.code.cpp.NameQualifiers import semmle.code.cpp.NameQualifiers
import semmle.code.cpp.ObjectiveC
import semmle.code.cpp.exprs.ObjectiveC
import DefaultOptions import DefaultOptions

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all name: codeql/cpp-all
version: 0.0.11-dev version: 0.0.12-dev
groups: cpp groups: cpp
dbscheme: semmlecode.cpp.dbscheme dbscheme: semmlecode.cpp.dbscheme
extractor: cpp extractor: cpp

View File

@@ -111,24 +111,6 @@ class Class extends UserType {
result = this.getCanonicalMember(index).(TemplateVariable).getAnInstantiation() result = this.getCanonicalMember(index).(TemplateVariable).getAnInstantiation()
} }
/**
* DEPRECATED: Use `getCanonicalMember(int)` or `getAMember(int)` instead.
* Gets the `index`th member of this class.
*/
deprecated Declaration getMember(int index) {
member(underlyingElement(this), index, unresolveElement(result))
}
/**
* DEPRECATED: As this includes a somewhat arbitrary number of
* template instantiations, it is unlikely to do what
* you need.
* Gets the number of members that this class has. This includes both
* templates that are in this class, and instantiations of those
* templates.
*/
deprecated int getNumMember() { result = count(this.getAMember()) }
/** /**
* Gets a private member declared in this class, struct or union. * Gets a private member declared in this class, struct or union.
* For template members, this may be either the template or an * For template members, this may be either the template or an
@@ -208,23 +190,6 @@ class Class extends UserType {
*/ */
deprecated predicate hasCopyConstructor() { this.getAMemberFunction() instanceof CopyConstructor } deprecated predicate hasCopyConstructor() { this.getAMemberFunction() instanceof CopyConstructor }
/**
* Holds if this class has a copy assignment operator that is either
* explicitly declared (though possibly `= delete`) or is auto-generated,
* non-trivial and called from somewhere.
*
* DEPRECATED: There is more than one reasonable definition of what it means
* to have a copy assignment operator, and we do not want to promote one
* particular definition by naming it with this predicate. Having a copy
* assignment operator could mean that such a member is declared or defined
* in the source or that it is callable by a particular caller. For C++11,
* there's also a question of whether to include members that are defaulted
* or deleted.
*/
deprecated predicate hasCopyAssignmentOperator() {
this.getAMemberFunction() instanceof CopyAssignmentOperator
}
/** /**
* Like accessOfBaseMember but returns multiple results if there are multiple * Like accessOfBaseMember but returns multiple results if there are multiple
* paths to `base` through the inheritance graph. * paths to `base` through the inheritance graph.
@@ -286,6 +251,16 @@ class Class extends UserType {
not this.implicitCopyConstructorDeleted() and not this.implicitCopyConstructorDeleted() and
forall(CopyConstructor cc | cc = this.getAMemberFunction() | forall(CopyConstructor cc | cc = this.getAMemberFunction() |
cc.isCompilerGenerated() and not cc.isDeleted() cc.isCompilerGenerated() and not cc.isDeleted()
) and
(
not this instanceof ClassTemplateInstantiation
or
this.(ClassTemplateInstantiation).getTemplate().hasImplicitCopyConstructor()
) and
(
not this instanceof PartialClassTemplateSpecialization
or
this.(PartialClassTemplateSpecialization).getPrimaryTemplate().hasImplicitCopyConstructor()
) )
} }
@@ -301,6 +276,18 @@ class Class extends UserType {
not this.implicitCopyAssignmentOperatorDeleted() and not this.implicitCopyAssignmentOperatorDeleted() and
forall(CopyAssignmentOperator ca | ca = this.getAMemberFunction() | forall(CopyAssignmentOperator ca | ca = this.getAMemberFunction() |
ca.isCompilerGenerated() and not ca.isDeleted() ca.isCompilerGenerated() and not ca.isDeleted()
) and
(
not this instanceof ClassTemplateInstantiation
or
this.(ClassTemplateInstantiation).getTemplate().hasImplicitCopyAssignmentOperator()
) and
(
not this instanceof PartialClassTemplateSpecialization
or
this.(PartialClassTemplateSpecialization)
.getPrimaryTemplate()
.hasImplicitCopyAssignmentOperator()
) )
} }
@@ -1070,31 +1057,6 @@ class PartialClassTemplateSpecialization extends ClassTemplateSpecialization {
override string getAPrimaryQlClass() { result = "PartialClassTemplateSpecialization" } override string getAPrimaryQlClass() { result = "PartialClassTemplateSpecialization" }
} }
/**
* An "interface" is a class that only contains pure virtual functions (and contains
* at least one such function). For example:
* ```
* class MyInterfaceClass {
* public:
* virtual void myMethod1() = 0;
* virtual void myMethod2() = 0;
* };
* ```
*
* DEPRECATED: This class is considered to be too specific for general usage.
*/
deprecated class Interface extends Class {
Interface() {
forex(Declaration m |
m.getDeclaringType() = this.getABaseClass*() and not compgenerated(unresolveElement(m))
|
m instanceof PureVirtualFunction
)
}
override string getAPrimaryQlClass() { result = "Interface" }
}
/** /**
* A class/struct derivation that is virtual. For example the derivation in * A class/struct derivation that is virtual. For example the derivation in
* the following code is a `VirtualClassDerivation`: * the following code is a `VirtualClassDerivation`:

View File

@@ -55,9 +55,6 @@ class ElementBase extends @element {
cached cached
string toString() { none() } string toString() { none() }
/** DEPRECATED: use `getAPrimaryQlClass` instead. */
deprecated string getCanonicalQLClass() { result = this.getAPrimaryQlClass() }
/** /**
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. * Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
*/ */
@@ -91,13 +88,6 @@ class Element extends ElementBase {
*/ */
predicate fromSource() { this.getFile().fromSource() } predicate fromSource() { this.getFile().fromSource() }
/**
* Holds if this element may be from a library.
*
* DEPRECATED: always true.
*/
deprecated predicate fromLibrary() { this.getFile().fromLibrary() }
/** Gets the primary location of this element. */ /** Gets the primary location of this element. */
Location getLocation() { none() } Location getLocation() { none() }

View File

@@ -196,31 +196,11 @@ class Folder extends Container, @folder {
*/ */
deprecated string getName() { folders(underlyingElement(this), result) } deprecated string getName() { folders(underlyingElement(this), result) }
/**
* DEPRECATED: use `getAbsolutePath` instead.
* Holds if this element is named `name`.
*/
deprecated predicate hasName(string name) { name = this.getName() }
/**
* DEPRECATED: use `getAbsolutePath` instead.
* Gets the full name of this folder.
*/
deprecated string getFullName() { result = this.getName() }
/** /**
* DEPRECATED: use `getBaseName` instead. * DEPRECATED: use `getBaseName` instead.
* Gets the last part of the folder name. * Gets the last part of the folder name.
*/ */
deprecated string getShortName() { result = this.getBaseName() } deprecated string getShortName() { result = this.getBaseName() }
/**
* DEPRECATED: use `getParentContainer` instead.
* Gets the parent folder.
*/
deprecated Folder getParent() {
containerparent(unresolveElement(result), underlyingElement(this))
}
} }
/** /**
@@ -308,13 +288,6 @@ class File extends Container, @file {
*/ */
override predicate fromSource() { numlines(underlyingElement(this), _, _, _) } override predicate fromSource() { numlines(underlyingElement(this), _, _, _) }
/**
* Holds if this file may be from a library.
*
* DEPRECATED: For historical reasons this is true for any file.
*/
deprecated override predicate fromLibrary() { any() }
/** Gets the metric file. */ /** Gets the metric file. */
MetricFile getMetrics() { result = this } MetricFile getMetrics() { result = this }
@@ -428,25 +401,3 @@ class CppFile extends File {
override string getAPrimaryQlClass() { result = "CppFile" } override string getAPrimaryQlClass() { result = "CppFile" }
} }
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C source file, as determined by file extension.
*
* For the related notion of whether a file is compiled as Objective C
* code, use `File.compiledAsObjC`.
*/
deprecated class ObjCFile extends File {
ObjCFile() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C++ source file, as determined by file extension.
*
* For the related notion of whether a file is compiled as Objective C++
* code, use `File.compiledAsObjCpp`.
*/
deprecated class ObjCppFile extends File {
ObjCppFile() { none() }
}

View File

@@ -105,25 +105,6 @@ class Location extends @location {
} }
} }
/**
* DEPRECATED: Use `Location` instead.
* A location of an element. Not used for expressions or statements, which
* instead use LocationExpr and LocationStmt respectively.
*/
deprecated library class LocationDefault extends Location, @location_default { }
/**
* DEPRECATED: Use `Location` instead.
* A location of a statement.
*/
deprecated library class LocationStmt extends Location, @location_stmt { }
/**
* DEPRECATED: Use `Location` instead.
* A location of an expression.
*/
deprecated library class LocationExpr extends Location, @location_expr { }
/** /**
* Gets the length of the longest line in file `f`. * Gets the length of the longest line in file `f`.
*/ */

View File

@@ -30,16 +30,6 @@ class Macro extends PreprocessorDirective, @ppd_define {
else result = "#define " + this.getHead() + " " + this.getBody() else result = "#define " + this.getHead() + " " + this.getBody()
} }
/**
* Holds if the body of the macro starts with an unmatched closing
* parenthesis. For example:
*
* #define RPAREN() )
*
* DEPRECATED: This predicate has a misleading name.
*/
deprecated predicate isFunctionLike() { this.getBody().regexpMatch("[^(]*\\).*") }
/** /**
* Gets the name of the macro. For example, `MAX` in * Gets the name of the macro. For example, `MAX` in
* `#define MAX(x,y) (((x)>(y))?(x):(y))`. * `#define MAX(x,y) (((x)>(y))?(x):(y))`.
@@ -261,46 +251,6 @@ class MacroInvocation extends MacroAccess {
string getExpandedArgument(int i) { macro_argument_expanded(underlyingElement(this), i, result) } string getExpandedArgument(int i) { macro_argument_expanded(underlyingElement(this), i, result) }
} }
/**
* A top-level expression generated by a macro invocation.
*
* DEPRECATED: Use `MacroInvocation.getExpr()` directly to get an
* expression generated at the top-level of a macro invocation. Use
* `MacroInvocation.getAnAffectedElement()` to get any element generated
* by a macro invocation.
*/
deprecated class MacroInvocationExpr extends Expr {
MacroInvocationExpr() { exists(MacroInvocation i | this = i.getExpr()) }
/**
* Gets the macro invocation of which this is the top-level expression.
*/
MacroInvocation getInvocation() { result.getExpr() = this }
/** Gets the name of the invoked macro. */
string getMacroName() { result = this.getInvocation().getMacroName() }
}
/**
* A top-level statement generated by a macro invocation.
*
* DEPRECATED: Use `MacroInvocation.getStmt()` directly to get a
* statement generated at the top-level of a macro invocation. Use
* `MacroInvocation.getAnAffectedElement()` to get any element generated
* by a macro invocation.
*/
deprecated class MacroInvocationStmt extends Stmt {
MacroInvocationStmt() { exists(MacroInvocation i | this = i.getStmt()) }
/**
* Gets the macro invocation of which this is the top-level statement.
*/
MacroInvocation getInvocation() { result.getStmt() = this }
/** Gets the name of the invoked macro. */
string getMacroName() { result = this.getInvocation().getMacroName() }
}
/** Holds if `l` is the location of a macro. */ /** Holds if `l` is the location of a macro. */
predicate macroLocation(Location l) { macrolocationbind(_, l) } predicate macroLocation(Location l) { macrolocationbind(_, l) }

View File

@@ -233,40 +233,6 @@ class ImplicitConversionFunction extends MemberFunction {
Type getDestType() { none() } // overridden in subclasses Type getDestType() { none() } // overridden in subclasses
} }
/**
* DEPRECATED: as of C++11 this class does not correspond perfectly with the
* language definition of a converting constructor.
*
* A C++ constructor that also defines an implicit conversion. For example the
* function `MyClass` in the following code is a `ConversionConstructor`:
* ```
* class MyClass {
* public:
* MyClass(const MyOtherClass &from) {
* ...
* }
* };
* ```
*/
deprecated class ConversionConstructor extends Constructor, ImplicitConversionFunction {
ConversionConstructor() {
strictcount(Parameter p | p = this.getAParameter() and not p.hasInitializer()) = 1 and
not this.hasSpecifier("explicit")
}
override string getAPrimaryQlClass() {
not this instanceof CopyConstructor and
not this instanceof MoveConstructor and
result = "ConversionConstructor"
}
/** Gets the type this `ConversionConstructor` takes as input. */
override Type getSourceType() { result = this.getParameter(0).getType() }
/** Gets the type this `ConversionConstructor` is a constructor of. */
override Type getDestType() { result = this.getDeclaringType() }
}
private predicate hasCopySignature(MemberFunction f) { private predicate hasCopySignature(MemberFunction f) {
f.getParameter(0).getUnspecifiedType().(LValueReferenceType).getBaseType() = f.getDeclaringType() f.getParameter(0).getUnspecifiedType().(LValueReferenceType).getBaseType() = f.getDeclaringType()
} }

View File

@@ -86,13 +86,6 @@ class Namespace extends NameQualifyingElement, @namespace {
/** Holds if this namespace may be from source. */ /** Holds if this namespace may be from source. */
override predicate fromSource() { this.getADeclaration().fromSource() } override predicate fromSource() { this.getADeclaration().fromSource() }
/**
* Holds if this namespace is in a library.
*
* DEPRECATED: never holds.
*/
deprecated override predicate fromLibrary() { not this.fromSource() }
/** Gets the metric namespace. */ /** Gets the metric namespace. */
MetricNamespace getMetrics() { result = this } MetricNamespace getMetrics() { result = this }
@@ -233,11 +226,6 @@ class GlobalNamespace extends Namespace {
override Namespace getParentNamespace() { none() } override Namespace getParentNamespace() { none() }
/**
* DEPRECATED: use `getName()`.
*/
deprecated string getFullName() { result = this.getName() }
override string getFriendlyName() { result = "(global namespace)" } override string getFriendlyName() { result = "(global namespace)" }
} }

View File

@@ -1,196 +0,0 @@
/**
* DEPRECATED: Objective-C is no longer supported.
*/
import semmle.code.cpp.Class
private import semmle.code.cpp.internal.ResolveClass
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C class.
*/
deprecated class ObjectiveClass extends Class {
ObjectiveClass() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C protocol.
*/
deprecated class Protocol extends Class {
Protocol() { none() }
/**
* Holds if the type implements the protocol, either because the type
* itself does, or because it is a type conforming to the protocol.
*/
predicate isImplementedBy(Type t) { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* A type which conforms to a protocol. Use `getAProtocol` to get a
* protocol that this type conforms to.
*/
deprecated class TypeConformingToProtocol extends DerivedType {
TypeConformingToProtocol() { none() }
/** Gets a protocol that this type conforms to. */
Protocol getAProtocol() { none() }
/** Gets the size of this type. */
override int getSize() { none() }
override int getAlignment() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C `@autoreleasepool` statement, for example
* `@autoreleasepool { int x; int y; }`.
*/
deprecated class AutoReleasePoolStmt extends Stmt {
AutoReleasePoolStmt() { none() }
override string toString() { none() }
/** Gets the body statement of this `@autoreleasepool` statement. */
Stmt getStmt() { none() }
override predicate mayBeImpure() { none() }
override predicate mayBeGloballyImpure() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C `@synchronized statement`, for example
* `@synchronized (x) { [x complicationOperation]; }`.
*/
deprecated class SynchronizedStmt extends Stmt {
SynchronizedStmt() { none() }
override string toString() { none() }
/** Gets the expression which gives the object to be locked. */
Expr getLockedObject() { none() }
/** Gets the body statement of this `@synchronized` statement. */
Stmt getStmt() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C for-in statement.
*/
deprecated class ForInStmt extends Loop {
ForInStmt() { none() }
/**
* Gets the condition expression of the `while` statement that the
* `for...in` statement desugars into.
*/
override Expr getCondition() { none() }
override Expr getControllingExpr() { none() }
/** Gets the collection that the loop iterates over. */
Expr getCollection() { none() }
/** Gets the body of the loop. */
override Stmt getStmt() { none() }
override string toString() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C category or class extension.
*/
deprecated class Category extends Class {
Category() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C class extension.
*/
deprecated class ClassExtension extends Category {
ClassExtension() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C try statement.
*/
deprecated class ObjcTryStmt extends TryStmt {
ObjcTryStmt() { none() }
override string toString() { none() }
/** Gets the finally clause of this try statement, if any. */
FinallyBlock getFinallyClause() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C `@finally` block.
*/
deprecated class FinallyBlock extends BlockStmt {
FinallyBlock() { none() }
/** Gets the try statement corresponding to this finally block. */
ObjcTryStmt getTryStmt() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C `@property`.
*/
deprecated class Property extends Declaration {
Property() { none() }
/** Gets the name of this property. */
override string getName() { none() }
/**
* Gets nothing (provided for compatibility with Declaration).
*
* For the attribute list following the `@property` keyword, use
* `getAnAttribute()`.
*/
override Specifier getASpecifier() { none() }
/**
* Gets an attribute of this property (such as `readonly`, `nonatomic`,
* or `getter=isEnabled`).
*/
Attribute getAnAttribute() { none() }
override Location getADeclarationLocation() { result = getLocation() }
override Location getDefinitionLocation() { result = getLocation() }
override Location getLocation() { none() }
/** Gets the type of this property. */
Type getType() { none() }
/**
* Gets the instance method which is called to get the value of this
* property.
*/
MemberFunction getGetter() { none() }
/**
* Gets the instance method which is called to set the value of this
* property (if it is a writable property).
*/
MemberFunction getSetter() { none() }
/**
* Gets the instance variable which stores the property value (if this
* property was explicitly or automatically `@synthesize`d).
*/
MemberVariable getInstanceVariable() { none() }
}

View File

@@ -95,22 +95,6 @@ class Parameter extends LocalScopeVariable, @parameter {
else result = this.getADeclarationEntry() else result = this.getADeclarationEntry()
} }
/**
* Gets the name of this parameter in the given block (which should be
* the body of a function with which the parameter is associated).
*
* DEPRECATED: this method was used in a previous implementation of
* getName, but is no longer in use.
*/
deprecated string getNameInBlock(BlockStmt b) {
exists(ParameterDeclarationEntry pde |
pde.getFunctionDeclarationEntry().getBlock() = b and
this.getFunction().getBlock() = b and
pde.getVariable() = this and
result = pde.getName()
)
}
/** /**
* Holds if this parameter has a name. * Holds if this parameter has a name.
* *

View File

@@ -8,9 +8,9 @@ private import PrintAST
private predicate shouldPrintDeclaration(Declaration decl) { private predicate shouldPrintDeclaration(Declaration decl) {
not decl instanceof Function not decl instanceof Function
or or
not exists(PrintASTConfiguration c) not exists(PrintAstConfiguration c)
or or
exists(PrintASTConfiguration config | config.shouldPrintFunction(decl)) exists(PrintAstConfiguration config | config.shouldPrintFunction(decl))
} }
/** /**

View File

@@ -12,7 +12,7 @@ import PrintAST
* Temporarily tweak this class or make a copy to control which functions are * Temporarily tweak this class or make a copy to control which functions are
* printed. * printed.
*/ */
class Cfg extends PrintASTConfiguration { class Cfg extends PrintAstConfiguration {
/** /**
* TWEAK THIS PREDICATE AS NEEDED. * TWEAK THIS PREDICATE AS NEEDED.
* Holds if the AST for `func` should be printed. * Holds if the AST for `func` should be printed.

View File

@@ -9,12 +9,12 @@
import cpp import cpp
private import semmle.code.cpp.Print private import semmle.code.cpp.Print
private newtype TPrintASTConfiguration = MkPrintASTConfiguration() private newtype TPrintAstConfiguration = MkPrintAstConfiguration()
/** /**
* The query can extend this class to control which functions are printed. * The query can extend this class to control which functions are printed.
*/ */
class PrintASTConfiguration extends TPrintASTConfiguration { class PrintAstConfiguration extends TPrintAstConfiguration {
/** /**
* Gets a textual representation of this `PrintASTConfiguration`. * Gets a textual representation of this `PrintASTConfiguration`.
*/ */
@@ -27,8 +27,11 @@ class PrintASTConfiguration extends TPrintASTConfiguration {
predicate shouldPrintFunction(Function func) { any() } predicate shouldPrintFunction(Function func) { any() }
} }
/** DEPRECATED: Alias for PrintAstConfiguration */
deprecated class PrintASTConfiguration = PrintAstConfiguration;
private predicate shouldPrintFunction(Function func) { private predicate shouldPrintFunction(Function func) {
exists(PrintASTConfiguration config | config.shouldPrintFunction(func)) exists(PrintAstConfiguration config | config.shouldPrintFunction(func))
} }
bindingset[s] bindingset[s]
@@ -85,8 +88,8 @@ private Function getEnclosingFunction(Locatable ast) {
* Most nodes are just a wrapper around `Locatable`, but we do synthesize new * Most nodes are just a wrapper around `Locatable`, but we do synthesize new
* nodes for things like parameter lists and constructor init lists. * nodes for things like parameter lists and constructor init lists.
*/ */
private newtype TPrintASTNode = private newtype TPrintAstNode =
TASTNode(Locatable ast) { shouldPrintFunction(getEnclosingFunction(ast)) } or TAstNode(Locatable ast) { shouldPrintFunction(getEnclosingFunction(ast)) } or
TDeclarationEntryNode(DeclStmt stmt, DeclarationEntry entry) { TDeclarationEntryNode(DeclStmt stmt, DeclarationEntry entry) {
// We create a unique node for each pair of (stmt, entry), to avoid having one node with // We create a unique node for each pair of (stmt, entry), to avoid having one node with
// multiple parents due to extractor bug CPP-413. // multiple parents due to extractor bug CPP-413.
@@ -106,7 +109,7 @@ private newtype TPrintASTNode =
/** /**
* A node in the output tree. * A node in the output tree.
*/ */
class PrintASTNode extends TPrintASTNode { class PrintAstNode extends TPrintAstNode {
/** /**
* Gets a textual representation of this node in the PrintAST output tree. * Gets a textual representation of this node in the PrintAST output tree.
*/ */
@@ -116,17 +119,17 @@ class PrintASTNode extends TPrintASTNode {
* Gets the child node at index `childIndex`. Child indices must be unique, * Gets the child node at index `childIndex`. Child indices must be unique,
* but need not be contiguous. * but need not be contiguous.
*/ */
abstract PrintASTNode getChildInternal(int childIndex); abstract PrintAstNode getChildInternal(int childIndex);
/** /**
* Gets the child node at index `childIndex`. * Gets the child node at index `childIndex`.
* Adds edges to fully converted expressions, that are not part of the * Adds edges to fully converted expressions, that are not part of the
* regular parent/child relation traversal. * regular parent/child relation traversal.
*/ */
final PrintASTNode getChild(int childIndex) { final PrintAstNode getChild(int childIndex) {
// The exact value of `childIndex` doesn't matter, as long as we preserve the correct order. // The exact value of `childIndex` doesn't matter, as long as we preserve the correct order.
result = result =
rank[childIndex](PrintASTNode child, int nonConvertedIndex, boolean isConverted | rank[childIndex](PrintAstNode child, int nonConvertedIndex, boolean isConverted |
childAndAccessorPredicate(child, _, nonConvertedIndex, isConverted) childAndAccessorPredicate(child, _, nonConvertedIndex, isConverted)
| |
// Unconverted children come first, then sort by original child index within each group. // Unconverted children come first, then sort by original child index within each group.
@@ -138,11 +141,11 @@ class PrintASTNode extends TPrintASTNode {
* Gets the node for the `.getFullyConverted()` version of the child originally at index * Gets the node for the `.getFullyConverted()` version of the child originally at index
* `childIndex`, if that node has any conversions. * `childIndex`, if that node has any conversions.
*/ */
private PrintASTNode getConvertedChild(int childIndex) { private PrintAstNode getConvertedChild(int childIndex) {
exists(Expr expr | exists(Expr expr |
expr = getChildInternal(childIndex).(ASTNode).getAST() and expr = getChildInternal(childIndex).(AstNode).getAst() and
expr.getFullyConverted() instanceof Conversion and expr.getFullyConverted() instanceof Conversion and
result.(ASTNode).getAST() = expr.getFullyConverted() and result.(AstNode).getAst() = expr.getFullyConverted() and
not expr instanceof Conversion not expr instanceof Conversion
) )
} }
@@ -166,12 +169,12 @@ class PrintASTNode extends TPrintASTNode {
/** /**
* Gets the children of this node. * Gets the children of this node.
*/ */
final PrintASTNode getAChild() { result = getChild(_) } final PrintAstNode getAChild() { result = getChild(_) }
/** /**
* Gets the parent of this node, if any. * Gets the parent of this node, if any.
*/ */
final PrintASTNode getParent() { result.getAChild() = this } final PrintAstNode getParent() { result.getAChild() = this }
/** /**
* Gets the location of this node in the source code. * Gets the location of this node in the source code.
@@ -196,7 +199,7 @@ class PrintASTNode extends TPrintASTNode {
* one result tuple, with `isConverted = false`. * one result tuple, with `isConverted = false`.
*/ */
private predicate childAndAccessorPredicate( private predicate childAndAccessorPredicate(
PrintASTNode child, string childPredicate, int nonConvertedIndex, boolean isConverted PrintAstNode child, string childPredicate, int nonConvertedIndex, boolean isConverted
) { ) {
child = getChildInternal(nonConvertedIndex) and child = getChildInternal(nonConvertedIndex) and
childPredicate = getChildAccessorPredicateInternal(nonConvertedIndex) and childPredicate = getChildAccessorPredicateInternal(nonConvertedIndex) and
@@ -234,12 +237,15 @@ class PrintASTNode extends TPrintASTNode {
private Function getEnclosingFunction() { result = getParent*().(FunctionNode).getFunction() } private Function getEnclosingFunction() { result = getParent*().(FunctionNode).getFunction() }
} }
/** DEPRECATED: Alias for PrintAstNode */
deprecated class PrintASTNode = PrintAstNode;
/** /**
* Class that restricts the elements that we compute `qlClass` for. * Class that restricts the elements that we compute `qlClass` for.
*/ */
private class PrintableElement extends Element { private class PrintableElement extends Element {
PrintableElement() { PrintableElement() {
exists(TASTNode(this)) exists(TAstNode(this))
or or
exists(TDeclarationEntryNode(_, this)) exists(TDeclarationEntryNode(_, this))
or or
@@ -262,7 +268,7 @@ private string qlClass(PrintableElement el) {
/** /**
* A node representing an AST node. * A node representing an AST node.
*/ */
abstract class BaseASTNode extends PrintASTNode { abstract class BaseAstNode extends PrintAstNode {
Locatable ast; Locatable ast;
override string toString() { result = qlClass(ast) + ast.toString() } override string toString() { result = qlClass(ast) + ast.toString() }
@@ -272,25 +278,34 @@ abstract class BaseASTNode extends PrintASTNode {
/** /**
* Gets the AST represented by this node. * Gets the AST represented by this node.
*/ */
final Locatable getAST() { result = ast } final Locatable getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated Locatable getAST() { result = getAst() }
} }
/** DEPRECATED: Alias for BaseAstNode */
deprecated class BaseASTNode = BaseAstNode;
/** /**
* A node representing an AST node other than a `DeclarationEntry`. * A node representing an AST node other than a `DeclarationEntry`.
*/ */
abstract class ASTNode extends BaseASTNode, TASTNode { abstract class AstNode extends BaseAstNode, TAstNode {
ASTNode() { this = TASTNode(ast) } AstNode() { this = TAstNode(ast) }
} }
/** DEPRECATED: Alias for AstNode */
deprecated class ASTNode = AstNode;
/** /**
* A node representing an `Expr`. * A node representing an `Expr`.
*/ */
class ExprNode extends ASTNode { class ExprNode extends AstNode {
Expr expr; Expr expr;
ExprNode() { expr = ast } ExprNode() { expr = ast }
override ASTNode getChildInternal(int childIndex) { result.getAST() = expr.getChild(childIndex) } override AstNode getChildInternal(int childIndex) { result.getAst() = expr.getChild(childIndex) }
override string getProperty(string key) { override string getProperty(string key) {
result = super.getProperty(key) result = super.getProperty(key)
@@ -306,7 +321,7 @@ class ExprNode extends ASTNode {
} }
override string getChildAccessorPredicateInternal(int childIndex) { override string getChildAccessorPredicateInternal(int childIndex) {
result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAST()) result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAst())
} }
/** /**
@@ -334,9 +349,9 @@ class ConversionNode extends ExprNode {
ConversionNode() { conv = expr } ConversionNode() { conv = expr }
override ASTNode getChildInternal(int childIndex) { override AstNode getChildInternal(int childIndex) {
childIndex = 0 and childIndex = 0 and
result.getAST() = conv.getExpr() and result.getAst() = conv.getExpr() and
conv.getExpr() instanceof Conversion conv.getExpr() instanceof Conversion
} }
} }
@@ -363,27 +378,27 @@ class CastNode extends ConversionNode {
class StmtExprNode extends ExprNode { class StmtExprNode extends ExprNode {
override StmtExpr expr; override StmtExpr expr;
override ASTNode getChildInternal(int childIndex) { override AstNode getChildInternal(int childIndex) {
childIndex = 0 and childIndex = 0 and
result.getAST() = expr.getStmt() result.getAst() = expr.getStmt()
} }
} }
/** /**
* A node representing a `DeclarationEntry`. * A node representing a `DeclarationEntry`.
*/ */
class DeclarationEntryNode extends BaseASTNode, TDeclarationEntryNode { class DeclarationEntryNode extends BaseAstNode, TDeclarationEntryNode {
override DeclarationEntry ast; override DeclarationEntry ast;
DeclStmt declStmt; DeclStmt declStmt;
DeclarationEntryNode() { this = TDeclarationEntryNode(declStmt, ast) } DeclarationEntryNode() { this = TDeclarationEntryNode(declStmt, ast) }
override PrintASTNode getChildInternal(int childIndex) { none() } override PrintAstNode getChildInternal(int childIndex) { none() }
override string getChildAccessorPredicateInternal(int childIndex) { none() } override string getChildAccessorPredicateInternal(int childIndex) { none() }
override string getProperty(string key) { override string getProperty(string key) {
result = BaseASTNode.super.getProperty(key) result = BaseAstNode.super.getProperty(key)
or or
key = "Type" and key = "Type" and
result = qlClass(ast.getType()) + ast.getType().toString() result = qlClass(ast.getType()) + ast.getType().toString()
@@ -396,9 +411,9 @@ class DeclarationEntryNode extends BaseASTNode, TDeclarationEntryNode {
class VariableDeclarationEntryNode extends DeclarationEntryNode { class VariableDeclarationEntryNode extends DeclarationEntryNode {
override VariableDeclarationEntry ast; override VariableDeclarationEntry ast;
override ASTNode getChildInternal(int childIndex) { override AstNode getChildInternal(int childIndex) {
childIndex = 0 and childIndex = 0 and
result.getAST() = ast.getVariable().getInitializer() result.getAst() = ast.getVariable().getInitializer()
} }
override string getChildAccessorPredicateInternal(int childIndex) { override string getChildAccessorPredicateInternal(int childIndex) {
@@ -410,23 +425,23 @@ class VariableDeclarationEntryNode extends DeclarationEntryNode {
/** /**
* A node representing a `Stmt`. * A node representing a `Stmt`.
*/ */
class StmtNode extends ASTNode { class StmtNode extends AstNode {
Stmt stmt; Stmt stmt;
StmtNode() { stmt = ast } StmtNode() { stmt = ast }
override BaseASTNode getChildInternal(int childIndex) { override BaseAstNode getChildInternal(int childIndex) {
exists(Locatable child | exists(Locatable child |
child = stmt.getChild(childIndex) and child = stmt.getChild(childIndex) and
( (
result.getAST() = child.(Expr) or result.getAst() = child.(Expr) or
result.getAST() = child.(Stmt) result.getAst() = child.(Stmt)
) )
) )
} }
override string getChildAccessorPredicateInternal(int childIndex) { override string getChildAccessorPredicateInternal(int childIndex) {
result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAST()) result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAst())
} }
} }
@@ -449,12 +464,12 @@ class DeclStmtNode extends StmtNode {
/** /**
* A node representing a `Parameter`. * A node representing a `Parameter`.
*/ */
class ParameterNode extends ASTNode { class ParameterNode extends AstNode {
Parameter param; Parameter param;
ParameterNode() { param = ast } ParameterNode() { param = ast }
final override PrintASTNode getChildInternal(int childIndex) { none() } final override PrintAstNode getChildInternal(int childIndex) { none() }
final override string getChildAccessorPredicateInternal(int childIndex) { none() } final override string getChildAccessorPredicateInternal(int childIndex) { none() }
@@ -469,14 +484,14 @@ class ParameterNode extends ASTNode {
/** /**
* A node representing an `Initializer`. * A node representing an `Initializer`.
*/ */
class InitializerNode extends ASTNode { class InitializerNode extends AstNode {
Initializer init; Initializer init;
InitializerNode() { init = ast } InitializerNode() { init = ast }
override ASTNode getChildInternal(int childIndex) { override AstNode getChildInternal(int childIndex) {
childIndex = 0 and childIndex = 0 and
result.getAST() = init.getExpr() result.getAst() = init.getExpr()
} }
override string getChildAccessorPredicateInternal(int childIndex) { override string getChildAccessorPredicateInternal(int childIndex) {
@@ -488,7 +503,7 @@ class InitializerNode extends ASTNode {
/** /**
* A node representing the parameters of a `Function`. * A node representing the parameters of a `Function`.
*/ */
class ParametersNode extends PrintASTNode, TParametersNode { class ParametersNode extends PrintAstNode, TParametersNode {
Function func; Function func;
ParametersNode() { this = TParametersNode(func) } ParametersNode() { this = TParametersNode(func) }
@@ -497,8 +512,8 @@ class ParametersNode extends PrintASTNode, TParametersNode {
final override Location getLocation() { result = getRepresentativeLocation(func) } final override Location getLocation() { result = getRepresentativeLocation(func) }
override ASTNode getChildInternal(int childIndex) { override AstNode getChildInternal(int childIndex) {
result.getAST() = func.getParameter(childIndex) result.getAst() = func.getParameter(childIndex)
} }
override string getChildAccessorPredicateInternal(int childIndex) { override string getChildAccessorPredicateInternal(int childIndex) {
@@ -515,7 +530,7 @@ class ParametersNode extends PrintASTNode, TParametersNode {
/** /**
* A node representing the initializer list of a `Constructor`. * A node representing the initializer list of a `Constructor`.
*/ */
class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializersNode { class ConstructorInitializersNode extends PrintAstNode, TConstructorInitializersNode {
Constructor ctor; Constructor ctor;
ConstructorInitializersNode() { this = TConstructorInitializersNode(ctor) } ConstructorInitializersNode() { this = TConstructorInitializersNode(ctor) }
@@ -524,8 +539,8 @@ class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializers
final override Location getLocation() { result = getRepresentativeLocation(ctor) } final override Location getLocation() { result = getRepresentativeLocation(ctor) }
final override ASTNode getChildInternal(int childIndex) { final override AstNode getChildInternal(int childIndex) {
result.getAST() = ctor.getInitializer(childIndex) result.getAst() = ctor.getInitializer(childIndex)
} }
final override string getChildAccessorPredicateInternal(int childIndex) { final override string getChildAccessorPredicateInternal(int childIndex) {
@@ -542,7 +557,7 @@ class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializers
/** /**
* A node representing the destruction list of a `Destructor`. * A node representing the destruction list of a `Destructor`.
*/ */
class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNode { class DestructorDestructionsNode extends PrintAstNode, TDestructorDestructionsNode {
Destructor dtor; Destructor dtor;
DestructorDestructionsNode() { this = TDestructorDestructionsNode(dtor) } DestructorDestructionsNode() { this = TDestructorDestructionsNode(dtor) }
@@ -551,8 +566,8 @@ class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNo
final override Location getLocation() { result = getRepresentativeLocation(dtor) } final override Location getLocation() { result = getRepresentativeLocation(dtor) }
final override ASTNode getChildInternal(int childIndex) { final override AstNode getChildInternal(int childIndex) {
result.getAST() = dtor.getDestruction(childIndex) result.getAst() = dtor.getDestruction(childIndex)
} }
final override string getChildAccessorPredicateInternal(int childIndex) { final override string getChildAccessorPredicateInternal(int childIndex) {
@@ -569,14 +584,14 @@ class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNo
/** /**
* A node representing a `Function`. * A node representing a `Function`.
*/ */
class FunctionNode extends ASTNode { class FunctionNode extends AstNode {
Function func; Function func;
FunctionNode() { func = ast } FunctionNode() { func = ast }
override string toString() { result = qlClass(func) + getIdentityString(func) } override string toString() { result = qlClass(func) + getIdentityString(func) }
override PrintASTNode getChildInternal(int childIndex) { override PrintAstNode getChildInternal(int childIndex) {
childIndex = 0 and childIndex = 0 and
result.(ParametersNode).getFunction() = func result.(ParametersNode).getFunction() = func
or or
@@ -584,7 +599,7 @@ class FunctionNode extends ASTNode {
result.(ConstructorInitializersNode).getConstructor() = func result.(ConstructorInitializersNode).getConstructor() = func
or or
childIndex = 2 and childIndex = 2 and
result.(ASTNode).getAST() = func.getEntryPoint() result.(AstNode).getAst() = func.getEntryPoint()
or or
childIndex = 3 and childIndex = 3 and
result.(DestructorDestructionsNode).getDestructor() = func result.(DestructorDestructionsNode).getDestructor() = func
@@ -603,7 +618,7 @@ class FunctionNode extends ASTNode {
private int getOrder() { private int getOrder() {
this = this =
rank[result](FunctionNode node, Function function, string file, int line, int column | rank[result](FunctionNode node, Function function, string file, int line, int column |
node.getAST() = function and node.getAst() = function and
locationSortKeys(function, file, line, column) locationSortKeys(function, file, line, column)
| |
node order by file, line, column, getIdentityString(function) node order by file, line, column, getIdentityString(function)
@@ -856,7 +871,7 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
} }
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */ /** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
query predicate nodes(PrintASTNode node, string key, string value) { query predicate nodes(PrintAstNode node, string key, string value) {
node.shouldPrint() and node.shouldPrint() and
value = node.getProperty(key) value = node.getProperty(key)
} }
@@ -865,7 +880,7 @@ query predicate nodes(PrintASTNode node, string key, string value) {
* Holds if `target` is a child of `source` in the AST, and property `key` of the edge has the * Holds if `target` is a child of `source` in the AST, and property `key` of the edge has the
* given `value`. * given `value`.
*/ */
query predicate edges(PrintASTNode source, PrintASTNode target, string key, string value) { query predicate edges(PrintAstNode source, PrintAstNode target, string key, string value) {
exists(int childIndex | exists(int childIndex |
source.shouldPrint() and source.shouldPrint() and
target.shouldPrint() and target.shouldPrint() and

View File

@@ -38,7 +38,7 @@ class FunctionSpecifier extends Specifier {
/** /**
* A C/C++ storage class specifier: `auto`, `register`, `static`, `extern`, * A C/C++ storage class specifier: `auto`, `register`, `static`, `extern`,
* or `mutable". * or `mutable`.
*/ */
class StorageClassSpecifier extends Specifier { class StorageClassSpecifier extends Specifier {
StorageClassSpecifier() { this.hasName(["auto", "register", "static", "extern", "mutable"]) } StorageClassSpecifier() { this.hasName(["auto", "register", "static", "extern", "mutable"]) }

View File

@@ -1085,50 +1085,6 @@ class DerivedType extends Type, @derivedtype {
override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() } override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
override Type stripType() { result = this.getBaseType().stripType() } override Type stripType() { result = this.getBaseType().stripType() }
/**
* Holds if this type has the `__autoreleasing` specifier or if it points to
* a type with the `__autoreleasing` specifier.
*
* DEPRECATED: use `hasSpecifier` directly instead.
*/
deprecated predicate isAutoReleasing() {
this.hasSpecifier("__autoreleasing") or
this.(PointerType).getBaseType().hasSpecifier("__autoreleasing")
}
/**
* Holds if this type has the `__strong` specifier or if it points to
* a type with the `__strong` specifier.
*
* DEPRECATED: use `hasSpecifier` directly instead.
*/
deprecated predicate isStrong() {
this.hasSpecifier("__strong") or
this.(PointerType).getBaseType().hasSpecifier("__strong")
}
/**
* Holds if this type has the `__unsafe_unretained` specifier or if it points
* to a type with the `__unsafe_unretained` specifier.
*
* DEPRECATED: use `hasSpecifier` directly instead.
*/
deprecated predicate isUnsafeRetained() {
this.hasSpecifier("__unsafe_unretained") or
this.(PointerType).getBaseType().hasSpecifier("__unsafe_unretained")
}
/**
* Holds if this type has the `__weak` specifier or if it points to
* a type with the `__weak` specifier.
*
* DEPRECATED: use `hasSpecifier` directly instead.
*/
deprecated predicate isWeak() {
this.hasSpecifier("__weak") or
this.(PointerType).getBaseType().hasSpecifier("__weak")
}
} }
/** /**

View File

@@ -106,25 +106,4 @@ class NestedTypedefType extends TypedefType {
NestedTypedefType() { this.isMember() } NestedTypedefType() { this.isMember() }
override string getAPrimaryQlClass() { result = "NestedTypedefType" } override string getAPrimaryQlClass() { result = "NestedTypedefType" }
/**
* DEPRECATED: use `.hasSpecifier("private")` instead.
*
* Holds if this member is private.
*/
deprecated predicate isPrivate() { this.hasSpecifier("private") }
/**
* DEPRECATED: `.hasSpecifier("protected")` instead.
*
* Holds if this member is protected.
*/
deprecated predicate isProtected() { this.hasSpecifier("protected") }
/**
* DEPRECATED: use `.hasSpecifier("public")` instead.
*
* Holds if this member is public.
*/
deprecated predicate isPublic() { this.hasSpecifier("public") }
} }

View File

@@ -556,24 +556,6 @@ class MemberVariable extends Variable, @membervariable {
private Type getAType() { membervariables(underlyingElement(this), unresolveElement(result), _) } private Type getAType() { membervariables(underlyingElement(this), unresolveElement(result), _) }
} }
/**
* A C/C++ function pointer variable.
*
* DEPRECATED: use `Variable.getType() instanceof FunctionPointerType` instead.
*/
deprecated class FunctionPointerVariable extends Variable {
FunctionPointerVariable() { this.getType() instanceof FunctionPointerType }
}
/**
* A C/C++ function pointer member variable.
*
* DEPRECATED: use `MemberVariable.getType() instanceof FunctionPointerType` instead.
*/
deprecated class FunctionPointerMemberVariable extends MemberVariable {
FunctionPointerMemberVariable() { this instanceof FunctionPointerVariable }
}
/** /**
* A C++14 variable template. For example, in the following code the variable * A C++14 variable template. For example, in the following code the variable
* template `v` defines a family of variables: * template `v` defines a family of variables:

View File

@@ -4,21 +4,14 @@
import semmle.files.FileSystem import semmle.files.FileSystem
private class TXMLLocatable = private class TXmlLocatable =
@xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters; @xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters;
/** An XML element that has a location. */ /** An XML element that has a location. */
class XMLLocatable extends @xmllocatable, TXMLLocatable { class XMLLocatable extends @xmllocatable, TXmlLocatable {
/** Gets the source location for this element. */ /** Gets the source location for this element. */
Location getLocation() { xmllocations(this, result) } Location getLocation() { xmllocations(this, result) }
/**
* DEPRECATED: Use `getLocation()` instead.
*
* Gets the source location for this element.
*/
deprecated Location getALocation() { result = this.getLocation() }
/** /**
* Holds if this element is at the specified location. * Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
@@ -83,21 +76,6 @@ class XMLParent extends @xmlparent {
/** Gets the number of places in the body of this XML parent where text occurs. */ /** Gets the number of places in the body of this XML parent where text occurs. */
int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) } int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) }
/**
* DEPRECATED: Internal.
*
* Append the character sequences of this XML parent from left to right, separated by a space,
* up to a specified (zero-based) index.
*/
deprecated string charsSetUpTo(int n) {
n = 0 and xmlChars(_, result, this, 0, _, _)
or
n > 0 and
exists(string chars | xmlChars(_, chars, this, n, _, _) |
result = this.charsSetUpTo(n - 1) + " " + chars
)
}
/** /**
* Gets the result of appending all the character sequences of this XML parent from * Gets the result of appending all the character sequences of this XML parent from
* left to right, separated by a space. * left to right, separated by a space.

View File

@@ -2,20 +2,6 @@ import cpp
import semmle.code.cpp.models.interfaces.Allocation import semmle.code.cpp.models.interfaces.Allocation
import semmle.code.cpp.models.interfaces.Deallocation import semmle.code.cpp.models.interfaces.Deallocation
/**
* A library routine that allocates memory.
*
* DEPRECATED: Use the `AllocationFunction` class instead of this predicate.
*/
deprecated predicate allocationFunction(Function f) { f instanceof AllocationFunction }
/**
* A call to a library routine that allocates memory.
*
* DEPRECATED: Use `AllocationExpr` instead (this also includes `new` expressions).
*/
deprecated predicate allocationCall(FunctionCall fc) { fc instanceof AllocationExpr }
/** /**
* A library routine that frees memory. * A library routine that frees memory.
*/ */
@@ -33,13 +19,6 @@ predicate freeCall(FunctionCall fc, Expr arg) { arg = fc.(DeallocationExpr).getF
*/ */
predicate isMemoryManagementExpr(Expr e) { isAllocationExpr(e) or e instanceof DeallocationExpr } predicate isMemoryManagementExpr(Expr e) { isAllocationExpr(e) or e instanceof DeallocationExpr }
/**
* Is e an allocation from stdlib.h (`malloc`, `realloc` etc)?
*
* DEPRECATED: Use `AllocationExpr` instead (this also includes `new` expressions).
*/
deprecated predicate isStdLibAllocationExpr(Expr e) { allocationCall(e) }
/** /**
* Is e some kind of allocation (`new`, `alloc`, `realloc` etc)? * Is e some kind of allocation (`new`, `alloc`, `realloc` etc)?
*/ */
@@ -48,19 +27,3 @@ predicate isAllocationExpr(Expr e) {
or or
e = any(NewOrNewArrayExpr new | not exists(new.getPlacementPointer())) e = any(NewOrNewArrayExpr new | not exists(new.getPlacementPointer()))
} }
/**
* Is e some kind of allocation (`new`, `alloc`, `realloc` etc) with a fixed size?
*
* DEPRECATED: Use `AllocationExpr.getSizeBytes()` instead.
*/
deprecated predicate isFixedSizeAllocationExpr(Expr allocExpr, int size) {
size = allocExpr.(AllocationExpr).getSizeBytes()
}
/**
* Is e some kind of deallocation (`delete`, `free`, `realloc` etc)?
*
* DEPRECATED: Use `DeallocationExpr` instead.
*/
deprecated predicate isDeallocationExpr(Expr e) { e instanceof DeallocationExpr }

View File

@@ -207,26 +207,6 @@ predicate variadicFormatter(Function f, string type, int formatParamIndex, int o
callsVariadicFormatter(f, type, formatParamIndex, outputParamIndex) callsVariadicFormatter(f, type, formatParamIndex, outputParamIndex)
} }
/**
* A standard function such as `vprintf` that has a format parameter
* and a variable argument list of type `va_arg`.
*
* DEPRECATED: Use the four argument version instead.
*/
deprecated predicate primitiveVariadicFormatter(TopLevelFunction f, int formatParamIndex) {
primitiveVariadicFormatter(f, _, formatParamIndex, _)
}
/**
* Holds if `f` is a function such as `vprintf` that has a format parameter
* (at `formatParamIndex`) and a variable argument list of type `va_arg`.
*
* DEPRECATED: Use the four argument version instead.
*/
deprecated predicate variadicFormatter(Function f, int formatParamIndex) {
variadicFormatter(f, _, formatParamIndex, _)
}
/** /**
* A function not in the standard library which takes a `printf`-like formatting * A function not in the standard library which takes a `printf`-like formatting
* string and a variable number of arguments. * string and a variable number of arguments.
@@ -428,13 +408,6 @@ class FormatLiteral extends Literal {
*/ */
FormattingFunctionCall getUse() { result.getFormat() = this } FormattingFunctionCall getUse() { result.getFormat() = this }
/**
* Holds if the default meaning of `%s` is a `wchar_t *`, rather than
* a `char *` (either way, `%S` will have the opposite meaning).
* DEPRECATED: Use getDefaultCharType() instead.
*/
deprecated predicate isWideCharDefault() { this.getUse().getTarget().isWideCharDefault() }
/** /**
* Gets the default character type expected for `%s` by this format literal. Typically * Gets the default character type expected for `%s` by this format literal. Typically
* `char` or `wchar_t`. * `char` or `wchar_t`.

View File

@@ -223,20 +223,6 @@ class BasicBlock extends ControlFlowNodeBase {
*/ */
predicate inLoop() { this.getASuccessor+() = this } predicate inLoop() { this.getASuccessor+() = this }
/**
* DEPRECATED since version 1.11: this predicate does not match the standard
* definition of _loop header_.
*
* Holds if this basic block is in a loop of the control-flow graph and
* additionally has an incoming edge that is not part of any loop containing
* this basic block. A typical example would be the basic block that computes
* `x > 0` in an outermost loop `while (x > 0) { ... }`.
*/
deprecated predicate isLoopHeader() {
this.inLoop() and
exists(BasicBlock pred | pred = this.getAPredecessor() and not pred = this.getASuccessor+())
}
/** /**
* Holds if control flow may reach this basic block from a function entry * Holds if control flow may reach this basic block from a function entry
* point or any handler of a reachable `try` statement. * point or any handler of a reachable `try` statement.

View File

@@ -65,7 +65,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
* taken when this expression is true. * taken when this expression is true.
*/ */
ControlFlowNode getATrueSuccessor() { ControlFlowNode getATrueSuccessor() {
qlCFGTrueSuccessor(this, result) and qlCfgTrueSuccessor(this, result) and
result = this.getASuccessor() result = this.getASuccessor()
} }
@@ -74,7 +74,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
* taken when this expression is false. * taken when this expression is false.
*/ */
ControlFlowNode getAFalseSuccessor() { ControlFlowNode getAFalseSuccessor() {
qlCFGFalseSuccessor(this, result) and qlCfgFalseSuccessor(this, result) and
result = this.getASuccessor() result = this.getASuccessor()
} }
@@ -94,24 +94,6 @@ import ControlFlowGraphPublic
*/ */
class ControlFlowNodeBase extends ElementBase, @cfgnode { } class ControlFlowNodeBase extends ElementBase, @cfgnode { }
/**
* DEPRECATED: Use `ControlFlowNode.getATrueSuccessor()` instead.
* Holds when `n2` is a control-flow node such that the control-flow
* edge `(n1, n2)` may be taken when `n1` is an expression that is true.
*/
deprecated predicate truecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
qlCFGTrueSuccessor(n1, n2)
}
/**
* DEPRECATED: Use `ControlFlowNode.getAFalseSuccessor()` instead.
* Holds when `n2` is a control-flow node such that the control-flow
* edge `(n1, n2)` may be taken when `n1` is an expression that is false.
*/
deprecated predicate falsecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
qlCFGFalseSuccessor(n1, n2)
}
/** /**
* An abstract class that can be extended to add additional edges to the * An abstract class that can be extended to add additional edges to the
* control-flow graph. Instances of this class correspond to the source nodes * control-flow graph. Instances of this class correspond to the source nodes
@@ -139,7 +121,7 @@ abstract class AdditionalControlFlowEdge extends ControlFlowNodeBase {
* `AdditionalControlFlowEdge`. Use this relation instead of `qlCFGSuccessor`. * `AdditionalControlFlowEdge`. Use this relation instead of `qlCFGSuccessor`.
*/ */
predicate successors_extended(ControlFlowNodeBase source, ControlFlowNodeBase target) { predicate successors_extended(ControlFlowNodeBase source, ControlFlowNodeBase target) {
qlCFGSuccessor(source, target) qlCfgSuccessor(source, target)
or or
source.(AdditionalControlFlowEdge).getAnEdgeTarget() = target source.(AdditionalControlFlowEdge).getAnEdgeTarget() = target
} }

View File

@@ -33,8 +33,8 @@ class GuardCondition extends Expr {
or or
// the IR short-circuits if(!x) // the IR short-circuits if(!x)
// don't produce a guard condition for `y = !x` and other non-short-circuited cases // don't produce a guard condition for `y = !x` and other non-short-circuited cases
not exists(Instruction inst | this.getFullyConverted() = inst.getAST()) and not exists(Instruction inst | this.getFullyConverted() = inst.getAst()) and
exists(IRGuardCondition ir | this.(NotExpr).getOperand() = ir.getAST()) exists(IRGuardCondition ir | this.(NotExpr).getOperand() = ir.getAst())
} }
/** /**
@@ -146,8 +146,8 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
*/ */
private class GuardConditionFromShortCircuitNot extends GuardCondition, NotExpr { private class GuardConditionFromShortCircuitNot extends GuardCondition, NotExpr {
GuardConditionFromShortCircuitNot() { GuardConditionFromShortCircuitNot() {
not exists(Instruction inst | this.getFullyConverted() = inst.getAST()) and not exists(Instruction inst | this.getFullyConverted() = inst.getAst()) and
exists(IRGuardCondition ir | this.getOperand() = ir.getAST()) exists(IRGuardCondition ir | this.getOperand() = ir.getAst())
} }
override predicate controls(BasicBlock controlled, boolean testIsTrue) { override predicate controls(BasicBlock controlled, boolean testIsTrue) {
@@ -241,7 +241,7 @@ private class GuardConditionFromIR extends GuardCondition {
private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) { private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) {
exists(IRBlock irb | exists(IRBlock irb |
forex(IRGuardCondition inst | inst = ir | inst.controls(irb, testIsTrue)) and forex(IRGuardCondition inst | inst = ir | inst.controls(irb, testIsTrue)) and
irb.getAnInstruction().getAST().(ControlFlowNode).getBasicBlock() = controlled and irb.getAnInstruction().getAst().(ControlFlowNode).getBasicBlock() = controlled and
not isUnreachedBlock(irb) not isUnreachedBlock(irb)
) )
} }

View File

@@ -1,393 +0,0 @@
/**
* DEPRECATED: Use `StackVariableReachability` instead.
*/
import cpp
/**
* DEPRECATED: Use `StackVariableReachability` instead.
*
* A reachability analysis for control-flow nodes involving stack variables.
* This defines sources, sinks, and any other configurable aspect of the
* analysis. Multiple analyses can coexist. To create an analysis, extend this
* class with a subclass whose characteristic predicate is a unique singleton
* string. For example, write
*
* ```
* class MyAnalysisConfiguration extends LocalScopeVariableReachability {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
* // Override `isBarrier`.
* }
* ```
*
* Then, to query whether there is flow between some source and sink, call the
* `reaches` predicate on an instance of `MyAnalysisConfiguration`.
*/
abstract deprecated class LocalScopeVariableReachability extends string {
bindingset[this]
LocalScopeVariableReachability() { length() >= 0 }
/** Holds if `node` is a source for the reachability analysis using variable `v`. */
abstract predicate isSource(ControlFlowNode node, LocalScopeVariable v);
/** Holds if `sink` is a (potential) sink for the reachability analysis using variable `v`. */
abstract predicate isSink(ControlFlowNode node, LocalScopeVariable v);
/** Holds if `node` is a barrier for the reachability analysis using variable `v`. */
abstract predicate isBarrier(ControlFlowNode node, LocalScopeVariable v);
/**
* Holds if the source node `source` can reach the sink `sink` without crossing
* a barrier. This is (almost) equivalent to the following QL predicate but
* uses basic blocks internally for better performance:
*
* ```
* predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
* reachesImpl(source, v, sink)
* and
* isSink(sink, v)
* }
*
* predicate reachesImpl(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
* sink = source.getASuccessor() and isSource(source, v)
* or
* exists(ControlFlowNode mid | reachesImpl(source, v, mid) |
* not isBarrier(mid, v)
* and
* sink = mid.getASuccessor()
* )
* }
* ```
*
* In addition to using a better performing implementation, this analysis
* accounts for loops where the condition is provably true upon entry.
*/
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
/*
* Implementation detail: the predicates in this class are a generalization of
* those in DefinitionsAndUses.qll, and should be kept in sync.
*
* Unfortunately, caching of abstract predicates does not work well, so the
* predicates in DefinitionsAndUses.qll cannot use this library.
*/
exists(BasicBlock bb, int i |
this.isSource(source, v) and
bb.getNode(i) = source and
not bb.isUnreachable()
|
exists(int j |
j > i and
sink = bb.getNode(j) and
this.isSink(sink, v) and
not exists(int k | this.isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
)
or
not exists(int k | this.isBarrier(bb.getNode(k), v) | k > i) and
this.bbSuccessorEntryReaches(bb, v, sink, _)
)
}
private predicate bbSuccessorEntryReaches(
BasicBlock bb, SemanticStackVariable v, ControlFlowNode node,
boolean skipsFirstLoopAlwaysTrueUponEntry
) {
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry)
|
this.bbEntryReachesLocally(succ, v, node) and
succSkipsFirstLoopAlwaysTrueUponEntry = false
or
not this.isBarrier(succ.getNode(_), v) and
this.bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
)
}
private predicate bbEntryReachesLocally(
BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
) {
exists(int n |
node = bb.getNode(n) and
this.isSink(node, v)
|
not exists(this.firstBarrierIndexIn(bb, v))
or
n <= this.firstBarrierIndexIn(bb, v)
)
}
private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) {
result = min(int m | this.isBarrier(bb.getNode(m), v))
}
}
/**
* Holds if `bb` contains the entry point `loop` for a loop at position `i`.
* The condition of that loop is provably true upon entry but not provably
* true in general (if it were, the false-successor had already been removed
* from the CFG).
*
* Examples:
* ```
* for (int i = 0; i < 2; i++) { } // always true upon entry
* for (int i = 0; true; i++) { } // always true
* ```
*/
private predicate bbLoopEntryConditionAlwaysTrueAt(BasicBlock bb, int i, ControlFlowNode loop) {
exists(Expr condition |
loopConditionAlwaysTrueUponEntry(loop, condition) and
not conditionAlwaysTrue(condition) and
bb.getNode(i) = loop
)
}
/**
* Basic block `pred` contains all or part of the condition belonging to a loop,
* and there is an edge from `pred` to `succ` that concludes the condition.
* If the edge corrseponds with the loop condition being found to be `true`, then
* `skipsLoop` is `false`. Otherwise the edge corresponds with the loop condition
* being found to be `false` and `skipsLoop` is `true`. Non-concluding edges
* within a complex loop condition are not matched by this predicate.
*/
private predicate bbLoopConditionAlwaysTrueUponEntrySuccessor(
BasicBlock pred, BasicBlock succ, boolean skipsLoop
) {
exists(Expr cond |
loopConditionAlwaysTrueUponEntry(_, cond) and
cond.getAChild*() = pred.getEnd() and
succ = pred.getASuccessor() and
not cond.getAChild*() = succ.getStart() and
(
succ = pred.getAFalseSuccessor() and
skipsLoop = true
or
succ = pred.getATrueSuccessor() and
skipsLoop = false
)
)
}
/**
* Loop invariant for `bbSuccessorEntryReaches`:
*
* - `succ` is a successor of `pred`.
* - `predSkipsFirstLoopAlwaysTrueUponEntry`: whether the path from
* `pred` (via `succ`) skips the first loop where the condition is
* provably true upon entry.
* - `succSkipsFirstLoopAlwaysTrueUponEntry`: whether the path from
* `succ` skips the first loop where the condition is provably true
* upon entry.
* - If `pred` contains the entry point of a loop where the condition
* is provably true upon entry, then `succ` is not allowed to skip
* that loop (`succSkipsFirstLoopAlwaysTrueUponEntry = false`).
*/
predicate bbSuccessorEntryReachesLoopInvariant(
BasicBlock pred, BasicBlock succ, boolean predSkipsFirstLoopAlwaysTrueUponEntry,
boolean succSkipsFirstLoopAlwaysTrueUponEntry
) {
succ = pred.getASuccessor() and
(succSkipsFirstLoopAlwaysTrueUponEntry = true or succSkipsFirstLoopAlwaysTrueUponEntry = false) and
(
// The edge from `pred` to `succ` is from a loop condition provably
// true upon entry, so the value of `predSkipsFirstLoopAlwaysTrueUponEntry`
// is determined by whether the true edge or the false edge is chosen,
// regardless of the value of `succSkipsFirstLoopAlwaysTrueUponEntry`.
bbLoopConditionAlwaysTrueUponEntrySuccessor(pred, succ, predSkipsFirstLoopAlwaysTrueUponEntry)
or
// The edge from `pred` to `succ` is _not_ from a loop condition provably
// true upon entry, so the values of `predSkipsFirstLoopAlwaysTrueUponEntry`
// and `succSkipsFirstLoopAlwaysTrueUponEntry` must be the same.
not bbLoopConditionAlwaysTrueUponEntrySuccessor(pred, succ, _) and
succSkipsFirstLoopAlwaysTrueUponEntry = predSkipsFirstLoopAlwaysTrueUponEntry and
// Moreover, if `pred` contains the entry point of a loop where the
// condition is provably true upon entry, then `succ` is not allowed
// to skip that loop, and hence `succSkipsFirstLoopAlwaysTrueUponEntry = false`.
(
bbLoopEntryConditionAlwaysTrueAt(pred, _, _)
implies
succSkipsFirstLoopAlwaysTrueUponEntry = false
)
)
}
/**
* DEPRECATED: Use `StackVariableReachabilityWithReassignment` instead.
*
* Reachability analysis for control-flow nodes involving stack variables.
* Unlike `LocalScopeVariableReachability`, this analysis takes variable
* reassignments into account.
*
* This class is used like `LocalScopeVariableReachability`, except that
* subclasses should override `isSourceActual` and `isSinkActual` instead of
* `isSource` and `isSink`, and that there is a `reachesTo` predicate in
* addition to `reaches`.
*/
abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends LocalScopeVariableReachability {
bindingset[this]
LocalScopeVariableReachabilityWithReassignment() { length() >= 0 }
/** Override this predicate rather than `isSource` (`isSource` is used internally). */
abstract predicate isSourceActual(ControlFlowNode node, LocalScopeVariable v);
/** Override this predicate rather than `isSink` (`isSink` is used internally). */
abstract predicate isSinkActual(ControlFlowNode node, LocalScopeVariable v);
/**
* Holds if the source node `source` can reach the sink `sink` without crossing
* a barrier, taking reassignments into account. This is (almost) equivalent
* to the following QL predicate, but uses basic blocks internally for better
* performance:
*
* ```
* predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
* reachesImpl(source, v, sink)
* and
* isSinkActual(sink, v)
* }
*
* predicate reachesImpl(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
* isSourceActual(source, v)
* and
* (
* sink = source.getASuccessor()
* or
* exists(ControlFlowNode mid, SemanticStackVariable v0 | reachesImpl(source, v0, mid) |
* // ordinary successor
* not isBarrier(mid, v) and
* sink = mid.getASuccessor() and
* v = v0
* or
* // reassigned from v0 to v
* exprDefinition(v, mid, v0.getAnAccess()) and
* sink = mid.getASuccessor()
* )
* )
* }
* ```
*
* In addition to using a better performing implementation, this analysis
* accounts for loops where the condition is provably true upon entry.
*/
override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
this.reachesTo(source, v, sink, _)
}
/**
* As `reaches`, but also specifies the last variable it was reassigned to (`v0`).
*/
predicate reachesTo(
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0
) {
exists(ControlFlowNode def |
this.actualSourceReaches(source, v, def, v0) and
LocalScopeVariableReachability.super.reaches(def, v0, sink) and
this.isSinkActual(sink, v0)
)
}
private predicate actualSourceReaches(
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
) {
this.isSourceActual(source, v) and def = source and v0 = v
or
exists(ControlFlowNode source1, SemanticStackVariable v1 |
this.actualSourceReaches(source, v, source1, v1)
|
this.reassignment(source1, v1, def, v0)
)
}
private predicate reassignment(
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
) {
LocalScopeVariableReachability.super.reaches(source, v, def) and
exprDefinition(v0, def, v.getAnAccess())
}
final override predicate isSource(ControlFlowNode node, LocalScopeVariable v) {
this.isSourceActual(node, v)
or
// Reassignment generates a new (non-actual) source
this.reassignment(_, _, node, v)
}
final override predicate isSink(ControlFlowNode node, LocalScopeVariable v) {
this.isSinkActual(node, v)
or
// Reassignment generates a new (non-actual) sink
exprDefinition(_, node, v.getAnAccess())
}
}
/**
* DEPRECATED: Use `StackVariableReachabilityExt` instead.
*
* Same as `LocalScopeVariableReachability`, but `isBarrier` works on control-flow
* edges rather than nodes and is therefore parameterized by the original
* source node as well. Otherwise, this class is used like
* `LocalScopeVariableReachability`.
*/
abstract deprecated class LocalScopeVariableReachabilityExt extends string {
bindingset[this]
LocalScopeVariableReachabilityExt() { length() >= 0 }
/** `node` is a source for the reachability analysis using variable `v`. */
abstract predicate isSource(ControlFlowNode node, LocalScopeVariable v);
/** `sink` is a (potential) sink for the reachability analysis using variable `v`. */
abstract predicate isSink(ControlFlowNode node, LocalScopeVariable v);
/** `node` is a barrier for the reachability analysis using variable `v` and starting from `source`. */
abstract predicate isBarrier(
ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, LocalScopeVariable v
);
/** See `LocalScopeVariableReachability.reaches`. */
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
exists(BasicBlock bb, int i |
this.isSource(source, v) and
bb.getNode(i) = source and
not bb.isUnreachable()
|
exists(int j |
j > i and
sink = bb.getNode(j) and
this.isSink(sink, v) and
not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) |
k in [i .. j - 1]
)
)
or
not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and
this.bbSuccessorEntryReaches(source, bb, v, sink, _)
)
}
private predicate bbSuccessorEntryReaches(
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node,
boolean skipsFirstLoopAlwaysTrueUponEntry
) {
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
succSkipsFirstLoopAlwaysTrueUponEntry) and
not this.isBarrier(source, bb.getEnd(), succ.getStart(), v)
|
this.bbEntryReachesLocally(source, succ, v, node) and
succSkipsFirstLoopAlwaysTrueUponEntry = false
or
not exists(int k | this.isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and
this.bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
)
}
private predicate bbEntryReachesLocally(
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
) {
this.isSource(source, v) and
exists(int n | node = bb.getNode(n) and this.isSink(node, v) |
not exists(int m | m < n | this.isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v))
)
}
}

View File

@@ -156,15 +156,6 @@ class AnalysedExpr extends Expr {
this.isValidCheck(v) and result = this.getATrueSuccessor() this.isValidCheck(v) and result = this.getATrueSuccessor()
} }
/**
* DEPRECATED: Use `getNonNullSuccessor` instead, which does the same.
*/
deprecated ControlFlowNode getValidSuccessor(LocalScopeVariable v) {
this.isValidCheck(v) and result = this.getATrueSuccessor()
or
this.isNullCheck(v) and result = this.getAFalseSuccessor()
}
/** /**
* Holds if this is a `VariableAccess` of `v` nested inside a condition. * Holds if this is a `VariableAccess` of `v` nested inside a condition.
*/ */

View File

@@ -10,10 +10,13 @@ import SSAUtils
* The SSA logic comes in two versions: the standard SSA and range-analysis RangeSSA. * The SSA logic comes in two versions: the standard SSA and range-analysis RangeSSA.
* This class provides the standard SSA logic. * This class provides the standard SSA logic.
*/ */
library class StandardSSA extends SSAHelper { library class StandardSsa extends SsaHelper {
StandardSSA() { this = 0 } StandardSsa() { this = 0 }
} }
/** DEPRECATED: Alias for StandardSsa */
deprecated class StandardSSA = StandardSsa;
/** /**
* A definition of one or more SSA variables, including phi node definitions. * A definition of one or more SSA variables, including phi node definitions.
* An _SSA variable_, as defined in the literature, is effectively the pair of * An _SSA variable_, as defined in the literature, is effectively the pair of
@@ -27,22 +30,22 @@ library class StandardSSA extends SSAHelper {
* statically seen to be unreachable. * statically seen to be unreachable.
*/ */
class SsaDefinition extends ControlFlowNodeBase { class SsaDefinition extends ControlFlowNodeBase {
SsaDefinition() { exists(StandardSSA x | x.ssa_defn(_, this, _, _)) } SsaDefinition() { exists(StandardSsa x | x.ssa_defn(_, this, _, _)) }
/** /**
* Gets a variable corresponding to an SSA StackVariable defined by * Gets a variable corresponding to an SSA StackVariable defined by
* this definition. * this definition.
*/ */
StackVariable getAVariable() { exists(StandardSSA x | x.ssa_defn(result, this, _, _)) } StackVariable getAVariable() { exists(StandardSsa x | x.ssa_defn(result, this, _, _)) }
/** /**
* Gets a string representation of the SSA variable represented by the pair * Gets a string representation of the SSA variable represented by the pair
* `(this, v)`. * `(this, v)`.
*/ */
string toString(StackVariable v) { exists(StandardSSA x | result = x.toString(this, v)) } string toString(StackVariable v) { exists(StandardSsa x | result = x.toString(this, v)) }
/** Gets a use of the SSA variable represented by the pair `(this, v)`. */ /** Gets a use of the SSA variable represented by the pair `(this, v)`. */
VariableAccess getAUse(StackVariable v) { exists(StandardSSA x | result = x.getAUse(this, v)) } VariableAccess getAUse(StackVariable v) { exists(StandardSsa x | result = x.getAUse(this, v)) }
/** /**
* Gets the control-flow node for this definition. This will usually be the * Gets the control-flow node for this definition. This will usually be the
@@ -62,7 +65,7 @@ class SsaDefinition extends ControlFlowNodeBase {
BasicBlock getBasicBlock() { result.contains(this.getDefinition()) } BasicBlock getBasicBlock() { result.contains(this.getDefinition()) }
/** Holds if this definition is a phi node for variable `v`. */ /** Holds if this definition is a phi node for variable `v`. */
predicate isPhiNode(StackVariable v) { exists(StandardSSA x | x.phi_node(v, this)) } predicate isPhiNode(StackVariable v) { exists(StandardSsa x | x.phi_node(v, this)) }
/** Gets the location of this definition. */ /** Gets the location of this definition. */
Location getLocation() { result = this.(ControlFlowNode).getLocation() } Location getLocation() { result = this.(ControlFlowNode).getLocation() }
@@ -124,7 +127,7 @@ class SsaDefinition extends ControlFlowNodeBase {
/** Holds if `(this, v)` reaches the end of basic block `b`. */ /** Holds if `(this, v)` reaches the end of basic block `b`. */
predicate reachesEndOfBB(StackVariable v, BasicBlock b) { predicate reachesEndOfBB(StackVariable v, BasicBlock b) {
exists(StandardSSA x | x.ssaDefinitionReachesEndOfBB(v, this, b)) exists(StandardSsa x | x.ssaDefinitionReachesEndOfBB(v, this, b))
} }
/** /**
@@ -147,15 +150,4 @@ class SsaDefinition extends ControlFlowNodeBase {
Expr getAnUltimateDefiningValue(StackVariable v) { Expr getAnUltimateDefiningValue(StackVariable v) {
result = this.getAnUltimateSsaDefinition(v).getDefiningValue(v) result = this.getAnUltimateSsaDefinition(v).getDefiningValue(v)
} }
/**
* DEPRECATED: this is the old name for `getAnUltimateDefiningValue`. The
* name was confusing as it seemed analogous to `getDefinition` rather than
* `getDefiningValue`. The SSA libraries for other languages use the name
* `getAnUltimateSsaDefinition` to refer to a predicate named
* `getAnUltimateSsaDefinition` in this class.
*/
deprecated Expr getAnUltimateDefinition(StackVariable v) {
result = this.getAnUltimateDefiningValue(v)
}
} }

View File

@@ -114,10 +114,10 @@ private predicate live_at_exit_of_bb(StackVariable v, BasicBlock b) {
/** Common SSA logic for standard SSA and range-analysis SSA. */ /** Common SSA logic for standard SSA and range-analysis SSA. */
cached cached
library class SSAHelper extends int { library class SsaHelper extends int {
/* 0 = StandardSSA, 1 = RangeSSA */ /* 0 = StandardSSA, 1 = RangeSSA */
cached cached
SSAHelper() { this in [0 .. 1] } SsaHelper() { this in [0 .. 1] }
/** /**
* Override to insert a custom phi node for variable `v` at the start of * Override to insert a custom phi node for variable `v` at the start of
@@ -311,3 +311,6 @@ library class SSAHelper extends int {
ssa_use(v, result, _, _) ssa_use(v, result, _, _)
} }
} }
/** DEPRECATED: Alias for SsaHelper */
deprecated class SSAHelper = SsaHelper;

View File

@@ -447,26 +447,6 @@ private predicate skipInitializer(Initializer init) {
) )
} }
/**
* Holds if `e` is an expression in a static initializer that must be evaluated
* at run time. This predicate computes "is non-const" instead of "is const" in
* order to avoid recursion through forall.
*/
private predicate runtimeExprInStaticInitializer(Expr e) {
inStaticInitializer(e) and
if e instanceof AggregateLiteral
then runtimeExprInStaticInitializer(e.getAChild())
else not e.getFullyConverted().isConstant()
}
/** Holds if `e` is part of the initializer of a local static variable. */
private predicate inStaticInitializer(Expr e) {
exists(LocalVariable local |
local.isStatic() and
e.getParent+() = local.getInitializer()
)
}
/** /**
* Gets the `i`th child of `n` in control-flow order, where the `i`-indexes are * Gets the `i`th child of `n` in control-flow order, where the `i`-indexes are
* contiguous, and the first index is 0. * contiguous, and the first index is 0.
@@ -1379,7 +1359,7 @@ private module Cached {
* true-successors and false-successors. * true-successors and false-successors.
*/ */
cached cached
predicate qlCFGSuccessor(Node n1, Node n2) { predicate qlCfgSuccessor(Node n1, Node n2) {
exists(Node memberNode, Pos memberPos | exists(Node memberNode, Pos memberPos |
subEdgeIncludingDestructors(any(Pos at | at.isAt()), n1, memberNode, memberPos) and subEdgeIncludingDestructors(any(Pos at | at.isAt()), n1, memberNode, memberPos) and
normalGroupMember(memberNode, memberPos, n2) normalGroupMember(memberNode, memberPos, n2)
@@ -1388,23 +1368,32 @@ private module Cached {
conditionalSuccessor(n1, _, n2) conditionalSuccessor(n1, _, n2)
} }
/** DEPRECATED: Alias for qlCfgSuccessor */
deprecated predicate qlCFGSuccessor = qlCfgSuccessor/2;
/** /**
* Holds if `n2` is a control-flow node such that the control-flow * Holds if `n2` is a control-flow node such that the control-flow
* edge `(n1, n2)` may be taken when `n1` is an expression that is true. * edge `(n1, n2)` may be taken when `n1` is an expression that is true.
*/ */
cached cached
predicate qlCFGTrueSuccessor(Node n1, Node n2) { predicate qlCfgTrueSuccessor(Node n1, Node n2) {
conditionalSuccessor(n1, true, n2) and conditionalSuccessor(n1, true, n2) and
not conditionalSuccessor(n1, false, n2) not conditionalSuccessor(n1, false, n2)
} }
/** DEPRECATED: Alias for qlCfgTrueSuccessor */
deprecated predicate qlCFGTrueSuccessor = qlCfgTrueSuccessor/2;
/** /**
* Holds if `n2` is a control-flow node such that the control-flow * Holds if `n2` is a control-flow node such that the control-flow
* edge `(n1, n2)` may be taken when `n1` is an expression that is false. * edge `(n1, n2)` may be taken when `n1` is an expression that is false.
*/ */
cached cached
predicate qlCFGFalseSuccessor(Node n1, Node n2) { predicate qlCfgFalseSuccessor(Node n1, Node n2) {
conditionalSuccessor(n1, false, n2) and conditionalSuccessor(n1, false, n2) and
not conditionalSuccessor(n1, true, n2) not conditionalSuccessor(n1, true, n2)
} }
/** DEPRECATED: Alias for qlCfgFalseSuccessor */
deprecated predicate qlCFGFalseSuccessor = qlCfgFalseSuccessor/2;
} }

View File

@@ -188,8 +188,8 @@ private predicate nonAnalyzableFunction(Function f) {
*/ */
private predicate impossibleFalseEdge(Expr condition, Node succ) { private predicate impossibleFalseEdge(Expr condition, Node succ) {
conditionAlwaysTrue(condition) and conditionAlwaysTrue(condition) and
qlCFGFalseSuccessor(condition, succ) and qlCfgFalseSuccessor(condition, succ) and
not qlCFGTrueSuccessor(condition, succ) not qlCfgTrueSuccessor(condition, succ)
} }
/** /**
@@ -197,8 +197,8 @@ private predicate impossibleFalseEdge(Expr condition, Node succ) {
*/ */
private predicate impossibleTrueEdge(Expr condition, Node succ) { private predicate impossibleTrueEdge(Expr condition, Node succ) {
conditionAlwaysFalse(condition) and conditionAlwaysFalse(condition) and
qlCFGTrueSuccessor(condition, succ) and qlCfgTrueSuccessor(condition, succ) and
not qlCFGFalseSuccessor(condition, succ) not qlCfgFalseSuccessor(condition, succ)
} }
/** /**
@@ -960,9 +960,9 @@ library class ConditionEvaluator extends ExprEvaluator {
ConditionEvaluator() { this = 0 } ConditionEvaluator() { this = 0 }
override predicate interesting(Expr e) { override predicate interesting(Expr e) {
qlCFGFalseSuccessor(e, _) qlCfgFalseSuccessor(e, _)
or or
qlCFGTrueSuccessor(e, _) qlCfgTrueSuccessor(e, _)
} }
} }

View File

@@ -20,10 +20,4 @@ import semmle.code.cpp.dataflow.DataFlow2
module TaintTracking { module TaintTracking {
import semmle.code.cpp.dataflow.internal.tainttracking1.TaintTrackingImpl import semmle.code.cpp.dataflow.internal.tainttracking1.TaintTrackingImpl
private import semmle.code.cpp.dataflow.TaintTracking2
/**
* DEPRECATED: Use TaintTracking2::Configuration instead.
*/
deprecated class Configuration2 = TaintTracking2::Configuration;
} }

View File

@@ -87,12 +87,30 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */ /** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() } predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() } predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if the additional flow step from `node1` to `node2` must be taken * Holds if the additional flow step from `node1` to `node2` must be taken
* into account in the analysis. * into account in the analysis.
@@ -305,7 +323,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate inBarrier(NodeEx node, Configuration config) { private predicate fullInBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -314,7 +332,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate outBarrier(NodeEx node, Configuration config) { private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierOut(n) config.isBarrierOut(n)
@@ -323,6 +350,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -345,9 +381,19 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic] pragma[nomagic]
private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n | exists(Node n | node.asNode() = n |
node.asNode() = n and
config.isBarrier(n, state) config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }
@@ -376,8 +422,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */ /** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline] pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and not fullOutBarrier(node1, config) and
not inBarrier(node2, config) and not fullInBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -430,6 +476,8 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) not stateBarrier(node2, s2, config)
) )
@@ -471,6 +519,8 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -870,8 +920,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) { private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and revFlow(node, true, config) and
fwdFlow(node, true, config) and fwdFlow(node, true, config) and
not inBarrier(node, config) and not fullInBarrier(node, config) and
not outBarrier(node, config) not fullOutBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -966,8 +1016,8 @@ private predicate flowOutOfCallNodeCand1(
) { ) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and not fullOutBarrier(ret, config) and
not inBarrier(out, config) not fullInBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -988,8 +1038,8 @@ private predicate flowIntoCallNodeCand1(
) { ) {
viableParamArgNodeCand1(call, p, arg, config) and viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and Stage1::revFlow(p, config) and
not outBarrier(arg, config) and not fullOutBarrier(arg, config) and
not inBarrier(p, config) not fullInBarrier(p, config)
} }
/** /**
@@ -1706,18 +1756,31 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) or sourceNode(node, state, config)
jumpStep(_, node, config) or or
additionalJumpStep(_, node, config) or jumpStep(_, node, config)
additionalJumpStateStep(_, _, node, state, config) or or
node instanceof ParamNodeEx or additionalJumpStep(_, node, config)
node.asNode() instanceof OutNodeExt or or
store(_, _, node, _, config) or additionalJumpStateStep(_, _, node, state, config)
read(_, _, node, config) or or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
node instanceof FlowCheckNode node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
) )
} }
@@ -1737,6 +1800,9 @@ private module LocalFlowBigStep {
or or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config) additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
) )
or or
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
@@ -1770,42 +1836,40 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
DataFlowType t, Configuration config, LocalCallContext cc Configuration config, LocalCallContext cc
) { ) {
not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
( (
localFlowEntry(node1, pragma[only_bind_into](state1), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and
( (
localFlowStepNodeCand1(node1, node2, config) and localFlowStepNodeCand1(node1, node2, config) and
state1 = state2 and
preservesValue = true and preservesValue = true and
t = node1.getDataFlowType() // irrelevant dummy value t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType()
) and ) and
node1 != node2 and node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and cc.relevantFor(node1.getEnclosingCallable()) and
not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall())
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), preservesValue, t, localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t,
pragma[only_bind_into](config), cc) and pragma[only_bind_into](config), cc) and
localFlowStepNodeCand1(mid, node2, config) and localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid, FlowState st | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() and t = node2.getDataFlowType()
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1819,9 +1883,19 @@ private module LocalFlowBigStep {
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) { ) {
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config, localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
callContext) and localFlowExit(node2, state1, config) and
localFlowExit(node2, state2, config) state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
} }
} }
@@ -2695,10 +2769,10 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result = result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) node.getEnclosingCallable()) and
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,12 +87,30 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */ /** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() } predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() } predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if the additional flow step from `node1` to `node2` must be taken * Holds if the additional flow step from `node1` to `node2` must be taken
* into account in the analysis. * into account in the analysis.
@@ -305,7 +323,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate inBarrier(NodeEx node, Configuration config) { private predicate fullInBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -314,7 +332,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate outBarrier(NodeEx node, Configuration config) { private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierOut(n) config.isBarrierOut(n)
@@ -323,6 +350,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -345,9 +381,19 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic] pragma[nomagic]
private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n | exists(Node n | node.asNode() = n |
node.asNode() = n and
config.isBarrier(n, state) config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }
@@ -376,8 +422,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */ /** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline] pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and not fullOutBarrier(node1, config) and
not inBarrier(node2, config) and not fullInBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -430,6 +476,8 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) not stateBarrier(node2, s2, config)
) )
@@ -471,6 +519,8 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -870,8 +920,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) { private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and revFlow(node, true, config) and
fwdFlow(node, true, config) and fwdFlow(node, true, config) and
not inBarrier(node, config) and not fullInBarrier(node, config) and
not outBarrier(node, config) not fullOutBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -966,8 +1016,8 @@ private predicate flowOutOfCallNodeCand1(
) { ) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and not fullOutBarrier(ret, config) and
not inBarrier(out, config) not fullInBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -988,8 +1038,8 @@ private predicate flowIntoCallNodeCand1(
) { ) {
viableParamArgNodeCand1(call, p, arg, config) and viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and Stage1::revFlow(p, config) and
not outBarrier(arg, config) and not fullOutBarrier(arg, config) and
not inBarrier(p, config) not fullInBarrier(p, config)
} }
/** /**
@@ -1706,18 +1756,31 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) or sourceNode(node, state, config)
jumpStep(_, node, config) or or
additionalJumpStep(_, node, config) or jumpStep(_, node, config)
additionalJumpStateStep(_, _, node, state, config) or or
node instanceof ParamNodeEx or additionalJumpStep(_, node, config)
node.asNode() instanceof OutNodeExt or or
store(_, _, node, _, config) or additionalJumpStateStep(_, _, node, state, config)
read(_, _, node, config) or or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
node instanceof FlowCheckNode node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
) )
} }
@@ -1737,6 +1800,9 @@ private module LocalFlowBigStep {
or or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config) additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
) )
or or
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
@@ -1770,42 +1836,40 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
DataFlowType t, Configuration config, LocalCallContext cc Configuration config, LocalCallContext cc
) { ) {
not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
( (
localFlowEntry(node1, pragma[only_bind_into](state1), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and
( (
localFlowStepNodeCand1(node1, node2, config) and localFlowStepNodeCand1(node1, node2, config) and
state1 = state2 and
preservesValue = true and preservesValue = true and
t = node1.getDataFlowType() // irrelevant dummy value t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType()
) and ) and
node1 != node2 and node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and cc.relevantFor(node1.getEnclosingCallable()) and
not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall())
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), preservesValue, t, localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t,
pragma[only_bind_into](config), cc) and pragma[only_bind_into](config), cc) and
localFlowStepNodeCand1(mid, node2, config) and localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid, FlowState st | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() and t = node2.getDataFlowType()
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1819,9 +1883,19 @@ private module LocalFlowBigStep {
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) { ) {
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config, localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
callContext) and localFlowExit(node2, state1, config) and
localFlowExit(node2, state2, config) state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
} }
} }
@@ -2695,10 +2769,10 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result = result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) node.getEnclosingCallable()) and
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,12 +87,30 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */ /** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() } predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() } predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if the additional flow step from `node1` to `node2` must be taken * Holds if the additional flow step from `node1` to `node2` must be taken
* into account in the analysis. * into account in the analysis.
@@ -305,7 +323,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate inBarrier(NodeEx node, Configuration config) { private predicate fullInBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -314,7 +332,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate outBarrier(NodeEx node, Configuration config) { private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierOut(n) config.isBarrierOut(n)
@@ -323,6 +350,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -345,9 +381,19 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic] pragma[nomagic]
private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n | exists(Node n | node.asNode() = n |
node.asNode() = n and
config.isBarrier(n, state) config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }
@@ -376,8 +422,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */ /** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline] pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and not fullOutBarrier(node1, config) and
not inBarrier(node2, config) and not fullInBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -430,6 +476,8 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) not stateBarrier(node2, s2, config)
) )
@@ -471,6 +519,8 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -870,8 +920,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) { private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and revFlow(node, true, config) and
fwdFlow(node, true, config) and fwdFlow(node, true, config) and
not inBarrier(node, config) and not fullInBarrier(node, config) and
not outBarrier(node, config) not fullOutBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -966,8 +1016,8 @@ private predicate flowOutOfCallNodeCand1(
) { ) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and not fullOutBarrier(ret, config) and
not inBarrier(out, config) not fullInBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -988,8 +1038,8 @@ private predicate flowIntoCallNodeCand1(
) { ) {
viableParamArgNodeCand1(call, p, arg, config) and viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and Stage1::revFlow(p, config) and
not outBarrier(arg, config) and not fullOutBarrier(arg, config) and
not inBarrier(p, config) not fullInBarrier(p, config)
} }
/** /**
@@ -1706,18 +1756,31 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) or sourceNode(node, state, config)
jumpStep(_, node, config) or or
additionalJumpStep(_, node, config) or jumpStep(_, node, config)
additionalJumpStateStep(_, _, node, state, config) or or
node instanceof ParamNodeEx or additionalJumpStep(_, node, config)
node.asNode() instanceof OutNodeExt or or
store(_, _, node, _, config) or additionalJumpStateStep(_, _, node, state, config)
read(_, _, node, config) or or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
node instanceof FlowCheckNode node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
) )
} }
@@ -1737,6 +1800,9 @@ private module LocalFlowBigStep {
or or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config) additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
) )
or or
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
@@ -1770,42 +1836,40 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
DataFlowType t, Configuration config, LocalCallContext cc Configuration config, LocalCallContext cc
) { ) {
not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
( (
localFlowEntry(node1, pragma[only_bind_into](state1), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and
( (
localFlowStepNodeCand1(node1, node2, config) and localFlowStepNodeCand1(node1, node2, config) and
state1 = state2 and
preservesValue = true and preservesValue = true and
t = node1.getDataFlowType() // irrelevant dummy value t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType()
) and ) and
node1 != node2 and node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and cc.relevantFor(node1.getEnclosingCallable()) and
not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall())
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), preservesValue, t, localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t,
pragma[only_bind_into](config), cc) and pragma[only_bind_into](config), cc) and
localFlowStepNodeCand1(mid, node2, config) and localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid, FlowState st | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() and t = node2.getDataFlowType()
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1819,9 +1883,19 @@ private module LocalFlowBigStep {
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) { ) {
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config, localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
callContext) and localFlowExit(node2, state1, config) and
localFlowExit(node2, state2, config) state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
} }
} }
@@ -2695,10 +2769,10 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result = result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) node.getEnclosingCallable()) and
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,12 +87,30 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */ /** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() } predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() } predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if the additional flow step from `node1` to `node2` must be taken * Holds if the additional flow step from `node1` to `node2` must be taken
* into account in the analysis. * into account in the analysis.
@@ -305,7 +323,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate inBarrier(NodeEx node, Configuration config) { private predicate fullInBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -314,7 +332,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate outBarrier(NodeEx node, Configuration config) { private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierOut(n) config.isBarrierOut(n)
@@ -323,6 +350,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -345,9 +381,19 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic] pragma[nomagic]
private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n | exists(Node n | node.asNode() = n |
node.asNode() = n and
config.isBarrier(n, state) config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }
@@ -376,8 +422,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */ /** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline] pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and not fullOutBarrier(node1, config) and
not inBarrier(node2, config) and not fullInBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -430,6 +476,8 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) not stateBarrier(node2, s2, config)
) )
@@ -471,6 +519,8 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -870,8 +920,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) { private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and revFlow(node, true, config) and
fwdFlow(node, true, config) and fwdFlow(node, true, config) and
not inBarrier(node, config) and not fullInBarrier(node, config) and
not outBarrier(node, config) not fullOutBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -966,8 +1016,8 @@ private predicate flowOutOfCallNodeCand1(
) { ) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and not fullOutBarrier(ret, config) and
not inBarrier(out, config) not fullInBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -988,8 +1038,8 @@ private predicate flowIntoCallNodeCand1(
) { ) {
viableParamArgNodeCand1(call, p, arg, config) and viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and Stage1::revFlow(p, config) and
not outBarrier(arg, config) and not fullOutBarrier(arg, config) and
not inBarrier(p, config) not fullInBarrier(p, config)
} }
/** /**
@@ -1706,18 +1756,31 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) or sourceNode(node, state, config)
jumpStep(_, node, config) or or
additionalJumpStep(_, node, config) or jumpStep(_, node, config)
additionalJumpStateStep(_, _, node, state, config) or or
node instanceof ParamNodeEx or additionalJumpStep(_, node, config)
node.asNode() instanceof OutNodeExt or or
store(_, _, node, _, config) or additionalJumpStateStep(_, _, node, state, config)
read(_, _, node, config) or or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
node instanceof FlowCheckNode node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
) )
} }
@@ -1737,6 +1800,9 @@ private module LocalFlowBigStep {
or or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config) additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
) )
or or
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
@@ -1770,42 +1836,40 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
DataFlowType t, Configuration config, LocalCallContext cc Configuration config, LocalCallContext cc
) { ) {
not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
( (
localFlowEntry(node1, pragma[only_bind_into](state1), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and
( (
localFlowStepNodeCand1(node1, node2, config) and localFlowStepNodeCand1(node1, node2, config) and
state1 = state2 and
preservesValue = true and preservesValue = true and
t = node1.getDataFlowType() // irrelevant dummy value t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType()
) and ) and
node1 != node2 and node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and cc.relevantFor(node1.getEnclosingCallable()) and
not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall())
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), preservesValue, t, localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t,
pragma[only_bind_into](config), cc) and pragma[only_bind_into](config), cc) and
localFlowStepNodeCand1(mid, node2, config) and localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid, FlowState st | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() and t = node2.getDataFlowType()
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1819,9 +1883,19 @@ private module LocalFlowBigStep {
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) { ) {
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config, localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
callContext) and localFlowExit(node2, state1, config) and
localFlowExit(node2, state2, config) state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
} }
} }
@@ -2695,10 +2769,10 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result = result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) node.getEnclosingCallable()) and
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,12 +87,30 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */ /** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() } predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() } predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if the additional flow step from `node1` to `node2` must be taken * Holds if the additional flow step from `node1` to `node2` must be taken
* into account in the analysis. * into account in the analysis.
@@ -305,7 +323,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate inBarrier(NodeEx node, Configuration config) { private predicate fullInBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -314,7 +332,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate outBarrier(NodeEx node, Configuration config) { private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierOut(n) config.isBarrierOut(n)
@@ -323,6 +350,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -345,9 +381,19 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic] pragma[nomagic]
private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n | exists(Node n | node.asNode() = n |
node.asNode() = n and
config.isBarrier(n, state) config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }
@@ -376,8 +422,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */ /** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline] pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and not fullOutBarrier(node1, config) and
not inBarrier(node2, config) and not fullInBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -430,6 +476,8 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) not stateBarrier(node2, s2, config)
) )
@@ -471,6 +519,8 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -870,8 +920,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) { private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and revFlow(node, true, config) and
fwdFlow(node, true, config) and fwdFlow(node, true, config) and
not inBarrier(node, config) and not fullInBarrier(node, config) and
not outBarrier(node, config) not fullOutBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -966,8 +1016,8 @@ private predicate flowOutOfCallNodeCand1(
) { ) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and not fullOutBarrier(ret, config) and
not inBarrier(out, config) not fullInBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -988,8 +1038,8 @@ private predicate flowIntoCallNodeCand1(
) { ) {
viableParamArgNodeCand1(call, p, arg, config) and viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and Stage1::revFlow(p, config) and
not outBarrier(arg, config) and not fullOutBarrier(arg, config) and
not inBarrier(p, config) not fullInBarrier(p, config)
} }
/** /**
@@ -1706,18 +1756,31 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) or sourceNode(node, state, config)
jumpStep(_, node, config) or or
additionalJumpStep(_, node, config) or jumpStep(_, node, config)
additionalJumpStateStep(_, _, node, state, config) or or
node instanceof ParamNodeEx or additionalJumpStep(_, node, config)
node.asNode() instanceof OutNodeExt or or
store(_, _, node, _, config) or additionalJumpStateStep(_, _, node, state, config)
read(_, _, node, config) or or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
node instanceof FlowCheckNode node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
) )
} }
@@ -1737,6 +1800,9 @@ private module LocalFlowBigStep {
or or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config) additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
) )
or or
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
@@ -1770,42 +1836,40 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
DataFlowType t, Configuration config, LocalCallContext cc Configuration config, LocalCallContext cc
) { ) {
not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
( (
localFlowEntry(node1, pragma[only_bind_into](state1), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and
( (
localFlowStepNodeCand1(node1, node2, config) and localFlowStepNodeCand1(node1, node2, config) and
state1 = state2 and
preservesValue = true and preservesValue = true and
t = node1.getDataFlowType() // irrelevant dummy value t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType()
) and ) and
node1 != node2 and node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and cc.relevantFor(node1.getEnclosingCallable()) and
not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall())
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), preservesValue, t, localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t,
pragma[only_bind_into](config), cc) and pragma[only_bind_into](config), cc) and
localFlowStepNodeCand1(mid, node2, config) and localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid, FlowState st | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() and t = node2.getDataFlowType()
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1819,9 +1883,19 @@ private module LocalFlowBigStep {
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) { ) {
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config, localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
callContext) and localFlowExit(node2, state1, config) and
localFlowExit(node2, state2, config) state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
} }
} }
@@ -2695,10 +2769,10 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result = result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) node.getEnclosingCallable()) and
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -113,10 +113,6 @@ private module PartialDefinitions {
abstract class PartialDefinition extends Expr { abstract class PartialDefinition extends Expr {
ControlFlowNode node; ControlFlowNode node;
abstract deprecated predicate partiallyDefines(Variable v);
abstract deprecated predicate partiallyDefinesThis(ThisExpr e);
/** /**
* Gets the subBasicBlock where this `PartialDefinition` is defined. * Gets the subBasicBlock where this `PartialDefinition` is defined.
*/ */
@@ -189,10 +185,6 @@ private module PartialDefinitions {
) )
} }
deprecated override predicate partiallyDefines(Variable v) { v = collection }
deprecated override predicate partiallyDefinesThis(ThisExpr e) { none() }
override predicate definesExpressions(Expr inner, Expr outer) { override predicate definesExpressions(Expr inner, Expr outer) {
inner = innerDefinedExpr and inner = innerDefinedExpr and
outer = this outer = this
@@ -217,12 +209,6 @@ private module PartialDefinitions {
VariablePartialDefinition() { innerDefinedExpr = getInnerDefinedExpr(this, node) } VariablePartialDefinition() { innerDefinedExpr = getInnerDefinedExpr(this, node) }
deprecated override predicate partiallyDefines(Variable v) {
innerDefinedExpr = v.getAnAccess()
}
deprecated override predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
/** /**
* Holds if this partial definition may modify `inner` (or what it points * Holds if this partial definition may modify `inner` (or what it points
* to) through `outer`. These expressions will never be `Conversion`s. * to) through `outer`. These expressions will never be `Conversion`s.

View File

@@ -64,13 +64,30 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() } override predicate isSource(DataFlow::Node source) { none() }
/** /**
* Holds if `sink` is a relevant taint sink. * Holds if `source` is a relevant taint source with the given initial
* `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
/**
* Holds if `sink` is a relevant taint sink
* *
* The smaller this predicate is, the faster `hasFlow()` will converge. * The smaller this predicate is, the faster `hasFlow()` will converge.
*/ */
// overridden to provide taint-tracking specific qldoc // overridden to provide taint-tracking specific qldoc
override predicate isSink(DataFlow::Node sink) { none() } override predicate isSink(DataFlow::Node sink) { none() }
/**
* Holds if `sink` is a relevant taint sink accepting `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() }
/** Holds if the node `node` is a taint sanitizer. */ /** Holds if the node `node` is a taint sanitizer. */
predicate isSanitizer(DataFlow::Node node) { none() } predicate isSanitizer(DataFlow::Node node) { none() }
@@ -79,9 +96,29 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintSanitizer(node) defaultTaintSanitizer(node)
} }
/**
* Holds if the node `node` is a taint sanitizer when the flow state is
* `state`.
*/
predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizer(node, state)
}
/** Holds if taint propagation into `node` is prohibited. */ /** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() } predicate isSanitizerIn(DataFlow::Node node) { none() }
/**
* Holds if taint propagation into `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerIn(node, state)
}
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */ /** Holds if taint propagation out of `node` is prohibited. */
@@ -89,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/**
* Holds if taint propagation out of `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerOut(node, state)
}
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
@@ -96,6 +143,16 @@ abstract class Configuration extends DataFlow::Configuration {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
} }
/**
* Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`.
*/
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
this.isSanitizerGuard(guard, state)
}
/** /**
* Holds if the additional taint propagation step from `node1` to `node2` * Holds if the additional taint propagation step from `node1` to `node2`
* must be taken into account in the analysis. * must be taken into account in the analysis.
@@ -107,6 +164,25 @@ abstract class Configuration extends DataFlow::Configuration {
defaultAdditionalTaintStep(node1, node2) defaultAdditionalTaintStep(node1, node2)
} }
/**
* Holds if the additional taint propagation step from `node1` to `node2`
* must be taken into account in the analysis. This step is only applicable
* in `state1` and updates the flow state to `state2`.
*/
predicate isAdditionalTaintStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
none()
}
final override predicate isAdditionalFlowStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
this.isAdditionalTaintStep(node1, state1, node2, state2)
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) { override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and (this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
defaultImplicitTaintRead(node, c) defaultImplicitTaintRead(node, c)

View File

@@ -64,13 +64,30 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() } override predicate isSource(DataFlow::Node source) { none() }
/** /**
* Holds if `sink` is a relevant taint sink. * Holds if `source` is a relevant taint source with the given initial
* `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
/**
* Holds if `sink` is a relevant taint sink
* *
* The smaller this predicate is, the faster `hasFlow()` will converge. * The smaller this predicate is, the faster `hasFlow()` will converge.
*/ */
// overridden to provide taint-tracking specific qldoc // overridden to provide taint-tracking specific qldoc
override predicate isSink(DataFlow::Node sink) { none() } override predicate isSink(DataFlow::Node sink) { none() }
/**
* Holds if `sink` is a relevant taint sink accepting `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() }
/** Holds if the node `node` is a taint sanitizer. */ /** Holds if the node `node` is a taint sanitizer. */
predicate isSanitizer(DataFlow::Node node) { none() } predicate isSanitizer(DataFlow::Node node) { none() }
@@ -79,9 +96,29 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintSanitizer(node) defaultTaintSanitizer(node)
} }
/**
* Holds if the node `node` is a taint sanitizer when the flow state is
* `state`.
*/
predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizer(node, state)
}
/** Holds if taint propagation into `node` is prohibited. */ /** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() } predicate isSanitizerIn(DataFlow::Node node) { none() }
/**
* Holds if taint propagation into `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerIn(node, state)
}
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */ /** Holds if taint propagation out of `node` is prohibited. */
@@ -89,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/**
* Holds if taint propagation out of `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerOut(node, state)
}
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
@@ -96,6 +143,16 @@ abstract class Configuration extends DataFlow::Configuration {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
} }
/**
* Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`.
*/
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
this.isSanitizerGuard(guard, state)
}
/** /**
* Holds if the additional taint propagation step from `node1` to `node2` * Holds if the additional taint propagation step from `node1` to `node2`
* must be taken into account in the analysis. * must be taken into account in the analysis.
@@ -107,6 +164,25 @@ abstract class Configuration extends DataFlow::Configuration {
defaultAdditionalTaintStep(node1, node2) defaultAdditionalTaintStep(node1, node2)
} }
/**
* Holds if the additional taint propagation step from `node1` to `node2`
* must be taken into account in the analysis. This step is only applicable
* in `state1` and updates the flow state to `state2`.
*/
predicate isAdditionalTaintStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
none()
}
final override predicate isAdditionalFlowStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
this.isAdditionalTaintStep(node1, state1, node2, state2)
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) { override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and (this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
defaultImplicitTaintRead(node, c) defaultImplicitTaintRead(node, c)

View File

@@ -226,13 +226,6 @@ class AssignPointerSubExpr extends AssignOperation, @assignpsubexpr {
* ``` * ```
*/ */
class ConditionDeclExpr extends Expr, @condition_decl { class ConditionDeclExpr extends Expr, @condition_decl {
/**
* DEPRECATED: Use `getVariableAccess()` or `getInitializingExpr()` instead.
*
* Gets the access using the condition for this declaration.
*/
deprecated Expr getExpr() { result = this.getChild(0) }
override string getAPrimaryQlClass() { result = "ConditionDeclExpr" } override string getAPrimaryQlClass() { result = "ConditionDeclExpr" }
/** /**

View File

@@ -118,11 +118,6 @@ class BuiltInNoOp extends BuiltInOperation, @noopexpr {
override string getAPrimaryQlClass() { result = "BuiltInNoOp" } override string getAPrimaryQlClass() { result = "BuiltInNoOp" }
} }
/**
* DEPRECATED: Use `BuiltInOperationBuiltInOffsetOf` instead.
*/
deprecated class BuiltInOperationOffsetOf = BuiltInOperationBuiltInOffsetOf;
/** /**
* A C/C++ `__builtin_offsetof` built-in operation (used by some implementations * A C/C++ `__builtin_offsetof` built-in operation (used by some implementations
* of `offsetof`). The operation retains its semantics even in the presence * of `offsetof`). The operation retains its semantics even in the presence
@@ -465,11 +460,6 @@ class BuiltInOperationIsUnion extends BuiltInOperation, @isunionexpr {
override string getAPrimaryQlClass() { result = "BuiltInOperationIsUnion" } override string getAPrimaryQlClass() { result = "BuiltInOperationIsUnion" }
} }
/**
* DEPRECATED: Use `BuiltInOperationBuiltInTypesCompatibleP` instead.
*/
deprecated class BuiltInOperationBuiltInTypes = BuiltInOperationBuiltInTypesCompatibleP;
/** /**
* A C++ `__builtin_types_compatible_p` built-in operation (used by some * A C++ `__builtin_types_compatible_p` built-in operation (used by some
* implementations of the `<type_traits>` header). * implementations of the `<type_traits>` header).

View File

@@ -666,13 +666,6 @@ class TypeidOperator extends Expr, @type_id {
*/ */
Type getResultType() { typeid_bind(underlyingElement(this), unresolveElement(result)) } Type getResultType() { typeid_bind(underlyingElement(this), unresolveElement(result)) }
/**
* DEPRECATED: Use `getResultType()` instead.
*
* Gets the type that is returned by this typeid expression.
*/
deprecated Type getSpecifiedType() { result = this.getResultType() }
override string getAPrimaryQlClass() { result = "TypeidOperator" } override string getAPrimaryQlClass() { result = "TypeidOperator" }
/** /**
@@ -731,13 +724,6 @@ class SizeofExprOperator extends SizeofOperator {
/** Gets the contained expression. */ /** Gets the contained expression. */
Expr getExprOperand() { result = this.getChild(0) } Expr getExprOperand() { result = this.getChild(0) }
/**
* DEPRECATED: Use `getExprOperand()` instead
*
* Gets the contained expression.
*/
deprecated Expr getExpr() { result = this.getExprOperand() }
override string toString() { result = "sizeof(<expr>)" } override string toString() { result = "sizeof(<expr>)" }
override predicate mayBeImpure() { this.getExprOperand().mayBeImpure() } override predicate mayBeImpure() { this.getExprOperand().mayBeImpure() }
@@ -759,13 +745,6 @@ class SizeofTypeOperator extends SizeofOperator {
/** Gets the contained type. */ /** Gets the contained type. */
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) } Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
/**
* DEPRECATED: Use `getTypeOperand()` instead
*
* Gets the contained type.
*/
deprecated Type getSpecifiedType() { result = this.getTypeOperand() }
override string toString() { result = "sizeof(" + this.getTypeOperand().getName() + ")" } override string toString() { result = "sizeof(" + this.getTypeOperand().getName() + ")" }
override predicate mayBeImpure() { none() } override predicate mayBeImpure() { none() }
@@ -794,11 +773,6 @@ class AlignofExprOperator extends AlignofOperator {
*/ */
Expr getExprOperand() { result = this.getChild(0) } Expr getExprOperand() { result = this.getChild(0) }
/**
* DEPRECATED: Use `getExprOperand()` instead.
*/
deprecated Expr getExpr() { result = this.getExprOperand() }
override string toString() { result = "alignof(<expr>)" } override string toString() { result = "alignof(<expr>)" }
} }
@@ -814,11 +788,6 @@ class AlignofTypeOperator extends AlignofOperator {
/** Gets the contained type. */ /** Gets the contained type. */
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) } Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
/**
* DEPRECATED: Use `getTypeOperand()` instead.
*/
deprecated Type getSpecifiedType() { result = this.getTypeOperand() }
override string toString() { result = "alignof(" + this.getTypeOperand().getName() + ")" } override string toString() { result = "alignof(" + this.getTypeOperand().getName() + ")" }
} }

View File

@@ -48,16 +48,6 @@ class NEExpr extends EqualityOperation, @neexpr {
class RelationalOperation extends ComparisonOperation, @rel_op_expr { class RelationalOperation extends ComparisonOperation, @rel_op_expr {
override int getPrecedence() { result = 10 } override int getPrecedence() { result = 10 }
/**
* DEPRECATED: Use `getGreaterOperand()` instead.
*/
deprecated Expr getLarge() { result = getGreaterOperand() }
/**
* DEPRECATED: Use `getLesserOperand()` instead.
*/
deprecated Expr getSmall() { result = getLesserOperand() }
/** /**
* Gets the operand on the "greater" (or "greater-or-equal") side * Gets the operand on the "greater" (or "greater-or-equal") side
* of this relational expression, that is, the side that is larger * of this relational expression, that is, the side that is larger

View File

@@ -114,13 +114,6 @@ class Expr extends StmtParent, @expr {
*/ */
Type getUnspecifiedType() { result = this.getType().getUnspecifiedType() } Type getUnspecifiedType() { result = this.getType().getUnspecifiedType() }
/**
* Gets an integer indicating the type of expression that this represents.
*
* DEPRECATED: use the subclasses of `Expr` rather than relying on this predicate.
*/
deprecated int getKind() { exprs(underlyingElement(this), result, _) }
/** Gets a textual representation of this expression. */ /** Gets a textual representation of this expression. */
override string toString() { none() } override string toString() { none() }

View File

@@ -164,16 +164,6 @@ class HexLiteral extends Literal {
class AggregateLiteral extends Expr, @aggregateliteral { class AggregateLiteral extends Expr, @aggregateliteral {
override string getAPrimaryQlClass() { result = "AggregateLiteral" } override string getAPrimaryQlClass() { result = "AggregateLiteral" }
/**
* DEPRECATED: Use ClassAggregateLiteral.getFieldExpr() instead.
*
* Gets the expression within the aggregate literal that is used to initialise field `f`,
* if this literal is being used to initialise a class/struct instance.
*/
deprecated Expr getCorrespondingExpr(Field f) {
result = this.(ClassAggregateLiteral).getFieldExpr(f)
}
override predicate mayBeImpure() { this.getAChild().mayBeImpure() } override predicate mayBeImpure() { this.getAChild().mayBeImpure() }
override predicate mayBeGloballyImpure() { this.getAChild().mayBeGloballyImpure() } override predicate mayBeGloballyImpure() { this.getAChild().mayBeGloballyImpure() }

View File

@@ -1,297 +0,0 @@
/**
* DEPRECATED: Objective-C is no longer supported.
*/
import semmle.code.cpp.exprs.Expr
import semmle.code.cpp.Class
import semmle.code.cpp.ObjectiveC
private import semmle.code.cpp.internal.ResolveClass
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C message expression, for example `[myColor changeColorToRed:5.0 green:2.0 blue:6.0]`.
*/
deprecated class MessageExpr extends Expr, Call {
MessageExpr() { none() }
override string toString() { none() }
/**
* Gets the selector of this message expression, for example `-changeColorToRed:green:blue:`.
*/
string getSelector() { none() }
/**
* Gets the function invoked by this message expression, as inferred by the compiler.
*
* If the compiler could infer the type of the receiver, and that type had a method
* whose name matched the selector, then the result of this predicate is said method.
* Otherwise this predicate has no result.
*
* In all cases, actual function dispatch isn't performed until runtime, but the
* lack of a static target is often cause for concern.
*/
MemberFunction getStaticTarget() { none() }
/**
* Provided for compatibility with Call. It is the same as the static target.
*/
override MemberFunction getTarget() { none() }
/**
* Holds if the compiler could infer a function as the target of this message.
*
* In all cases, actual function dispatch isn't performed until runtime, but the
* lack of a static target is often cause for concern.
*/
predicate hasStaticTarget() { none() }
/**
* Gets the number of arguments passed by this message expression.
*
* In most cases, this equals the number of colons in the selector, but this needn't be the
* case for variadic methods like "-initWithFormat:", which can have more than one argument.
*/
override int getNumberOfArguments() { none() }
/**
* Gets an argument passed by this message expression.
*/
override Expr getAnArgument() { none() }
/**
* Gets the nth argument passed by this message expression.
*
* The range of `n` is [`0` .. `getNumberOfArguments()`].
*/
override Expr getArgument(int n) { none() }
override int getPrecedence() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C message expression whose receiver is `super`, for example `[super init]`.
*/
deprecated class SuperMessageExpr extends MessageExpr {
SuperMessageExpr() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C message expression whose receiver is the name of a class, and
* is therefore calling a class method rather than an instance method. This occurs
* most commonly for the "+alloc", "+new", and "+class" selectors.
*/
deprecated class ClassMessageExpr extends MessageExpr {
ClassMessageExpr() { none() }
/**
* Gets the class which is the receiver of this message.
*/
Type getReceiver() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C message expression whose receiver is an expression (which includes the
* common case of the receiver being "self").
*/
deprecated class ExprMessageExpr extends MessageExpr {
ExprMessageExpr() { none() }
/**
* Gets the expression which gives the receiver of this message.
*/
Expr getReceiver() { none() }
/**
* Gets the Objective C class of which the receiving expression is an instance.
*
* If the receiving expression has type `id` or type `id<P>` for some protocol `P`,
* then there will be no result. If the receiving expression has type `C*` or type
* `C<P>*` for some protocol `P`, then the result will be the type `C`.
*/
ObjectiveClass getReceiverClass() { none() }
/**
* Gets the Objective C classes and/or protocols which are statically implemented
* by the receiving expression.
*
* If the receiving expression has type `id`, then there will be no result.
* If the receiving expression has type `id<P>`, then `P` will be the sole result.
* If the receiving expression has type `C*`, then `C` will be the sole result.
* If the receiving expression has type `C<P>*`, then `C` and `P` will both be results.
*/
Class getAReceiverClassOrProtocol() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An access to an Objective C property using dot syntax.
*
* Such accesses are de-sugared into a message expression to the property's getter or setter.
*/
deprecated class PropertyAccess extends ExprMessageExpr {
PropertyAccess() { none() }
/**
* Gets the property being accessed by this expression.
*/
Property getProperty() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C `@selector` expression, for example `@selector(driveForDistance:)`.
*/
deprecated class AtSelectorExpr extends Expr {
AtSelectorExpr() { none() }
override string toString() { none() }
/**
* Gets the selector of this `@selector` expression, for example `driveForDistance:`.
*/
string getSelector() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C `@protocol` expression, for example `@protocol(SomeProtocol)`.
*/
deprecated class AtProtocolExpr extends Expr {
AtProtocolExpr() { none() }
override string toString() { none() }
/**
* Gets the protocol of this `@protocol` expression, for example `SomeProtocol`.
*/
Protocol getProtocol() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C `@encode` expression, for example `@encode(int *)`.
*/
deprecated class AtEncodeExpr extends Expr {
AtEncodeExpr() { none() }
override string toString() { none() }
/**
* Gets the type this `@encode` expression encodes, for example `int *`.
*/
Type getEncodedType() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C throw expression.
*/
deprecated class ObjcThrowExpr extends ThrowExpr {
ObjcThrowExpr() { none() }
override string toString() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C throw expression with no argument (which causes the
* current exception to be re-thrown).
*/
deprecated class ObjcReThrowExpr extends ReThrowExpr, ObjcThrowExpr {
ObjcReThrowExpr() { none() }
override string toString() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C @ expression which boxes a single value, such as @(22).
*/
deprecated class AtExpr extends UnaryOperation {
AtExpr() { none() }
override string toString() { none() }
override string getOperator() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C @[...] literal.
*/
deprecated class ArrayLiteral extends Expr {
ArrayLiteral() { none() }
/** Gets a textual representation of this array literal. */
override string toString() { none() }
/** An element of the array */
Expr getElement(int i) { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C @{...} literal.
*/
deprecated class DictionaryLiteral extends Expr {
DictionaryLiteral() { none() }
/** Gets a textual representation of this dictionary literal. */
override string toString() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C @"..." string literal.
*/
deprecated class ObjCLiteralString extends TextLiteral {
ObjCLiteralString() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C/C++ overloaded subscripting access expression.
*
* Either
* obj[idx]
* or
* obj[idx] = expr
*/
deprecated class SubscriptExpr extends Expr {
SubscriptExpr() { none() }
/**
* Gets the object expression being subscripted.
*/
Expr getSubscriptBase() { none() }
/**
* Gets the expression giving the index into the object.
*/
Expr getSubscriptIndex() { none() }
/**
* Gets the expression being assigned (if this is an assignment).
*/
Expr getAssignedExpr() { none() }
override string toString() { none() }
}
/**
* DEPRECATED: Objective-C is no longer supported.
* An Objective C _cmd expression.
*/
deprecated class CmdExpr extends Expr {
CmdExpr() { none() }
override string toString() { none() }
override predicate mayBeImpure() { none() }
override predicate mayBeGloballyImpure() { none() }
}

View File

@@ -39,19 +39,6 @@ class CorrectIncludeGuard extends IncludeGuardedHeader {
PreprocessorEndif getEndif() { correctIncludeGuard(this, _, _, result, _) } PreprocessorEndif getEndif() { correctIncludeGuard(this, _, _, result, _) }
} }
/**
* DEPRECATED: no longer useful.
*/
deprecated class NotIncludedGuard extends IncludeGuardedHeader {
NotIncludedGuard() { none() }
/** Gets the `#ifndef` directive used to prevent multiple inclusion of this file. */
PreprocessorIfndef getIfndef() { result.getFile() = this }
/** Gets the `#endif` directive closing this file. */
PreprocessorEndif getEndif() { result.getFile() = this }
}
/** /**
* A file with no code in it. * A file with no code in it.
*/ */

View File

@@ -129,11 +129,11 @@ private class FromGlobalVarTaintTrackingCfg extends TaintTracking2::Configuratio
} }
private predicate readsVariable(LoadInstruction load, Variable var) { private predicate readsVariable(LoadInstruction load, Variable var) {
load.getSourceAddress().(VariableAddressInstruction).getASTVariable() = var load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
} }
private predicate writesVariable(StoreInstruction store, Variable var) { private predicate writesVariable(StoreInstruction store, Variable var) {
store.getDestinationAddress().(VariableAddressInstruction).getASTVariable() = var store.getDestinationAddress().(VariableAddressInstruction).getAstVariable() = var
} }
/** /**
@@ -489,9 +489,9 @@ module TaintedWithPath {
/** Gets the element that `pathNode` wraps, if any. */ /** Gets the element that `pathNode` wraps, if any. */
Element getElementFromPathNode(PathNode pathNode) { Element getElementFromPathNode(PathNode pathNode) {
exists(DataFlow::Node node | node = pathNode.(WrapPathNode).inner().getNode() | exists(DataFlow::Node node | node = pathNode.(WrapPathNode).inner().getNode() |
result = node.asInstruction().getAST() result = node.asInstruction().getAst()
or or
result = node.asOperand().getDef().getAST() result = node.asOperand().getDef().getAst()
) )
or or
result = pathNode.(EndpointPathNode).inner() result = pathNode.(EndpointPathNode).inner()

View File

@@ -0,0 +1,270 @@
/**
* This file provides a library for inter-procedural must-flow data flow analysis.
* Unlike `DataFlow.qll`, the analysis provided by this file checks whether data _must_ flow
* from a source to a _sink_.
*/
private import cpp
import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.IR
/**
* A configuration of a data flow analysis that performs must-flow analysis. This is different
* from `DataFlow.qll` which performs may-flow analysis (i.e., it finds paths where the source _may_
* flow to the sink).
*
* Like in `DataFlow.qll`, each use of the `MustFlow.qll` library must define its own unique extension
* of this abstract class. To create a configuration, extend this class with a subclass whose
* characteristic predicate is a unique singleton string and override `isSource`, `isSink` (and
* `isAdditionalFlowStep` if additional steps are required).
*/
abstract class MustFlowConfiguration extends string {
bindingset[this]
MustFlowConfiguration() { any() }
/**
* Holds if `source` is a relevant data flow source.
*/
abstract predicate isSource(DataFlow::Node source);
/**
* Holds if `sink` is a relevant data flow sink.
*/
abstract predicate isSink(DataFlow::Node sink);
/**
* Holds if the additional flow step from `node1` to `node2` must be taken
* into account in the analysis.
*/
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
/**
* Holds if data must flow from `source` to `sink` for this configuration.
*
* The corresponding paths are generated from the end-points and the graph
* included in the module `PathGraph`.
*/
final predicate hasFlowPath(MustFlowPathNode source, MustFlowPathSink sink) {
this.isSource(source.getNode()) and
source.getASuccessor+() = sink
}
}
/** Holds if `node` flows from a source. */
pragma[nomagic]
private predicate flowsFromSource(DataFlow::Node node, MustFlowConfiguration config) {
config.isSource(node)
or
exists(DataFlow::Node mid |
step(mid, node, config) and
flowsFromSource(mid, pragma[only_bind_into](config))
)
}
/** Holds if `node` flows to a sink. */
pragma[nomagic]
private predicate flowsToSink(DataFlow::Node node, MustFlowConfiguration config) {
flowsFromSource(node, pragma[only_bind_into](config)) and
(
config.isSink(node)
or
exists(DataFlow::Node mid |
step(node, mid, config) and
flowsToSink(mid, pragma[only_bind_into](config))
)
)
}
cached
private module Cached {
/** Holds if `p` is the `n`'th parameter of the non-virtual function `f`. */
private predicate parameterOf(Parameter p, Function f, int n) {
not f.isVirtual() and f.getParameter(n) = p
}
/**
* Holds if `instr` is the `n`'th argument to a call to the non-virtual function `f`, and
* `init` is the corresponding initialization instruction that receives the value of `instr` in `f`.
*/
private predicate flowIntoParameter(
Function f, int n, CallInstruction call, Instruction instr, InitializeParameterInstruction init
) {
not f.isVirtual() and
call.getPositionalArgument(n) = instr and
f = call.getStaticCallTarget() and
getEnclosingNonVirtualFunctionInitializeParameter(init, f) and
init.getParameter().getIndex() = pragma[only_bind_into](pragma[only_bind_out](n))
}
/**
* Holds if `instr` is an argument to a call to the function `f`, and `init` is the
* corresponding initialization instruction that receives the value of `instr` in `f`.
*/
pragma[noinline]
private predicate getPositionalArgumentInitParam(
CallInstruction call, Instruction instr, InitializeParameterInstruction init, Function f
) {
exists(int n |
parameterOf(_, f, n) and
flowIntoParameter(f, pragma[only_bind_into](pragma[only_bind_out](n)), call, instr, init)
)
}
/**
* Holds if `instr` is the qualifier to a call to the non-virtual function `f`, and
* `init` is the corresponding initialization instruction that receives the value of
* `instr` in `f`.
*/
pragma[noinline]
private predicate getThisArgumentInitParam(
CallInstruction call, Instruction instr, InitializeParameterInstruction init, Function f
) {
not f.isVirtual() and
call.getStaticCallTarget() = f and
getEnclosingNonVirtualFunctionInitializeParameter(init, f) and
call.getThisArgument() = instr and
init.getIRVariable() instanceof IRThisVariable
}
/** Holds if `f` is the enclosing non-virtual function of `init`. */
private predicate getEnclosingNonVirtualFunctionInitializeParameter(
InitializeParameterInstruction init, Function f
) {
not f.isVirtual() and
init.getEnclosingFunction() = f
}
/** Holds if `f` is the enclosing non-virtual function of `init`. */
private predicate getEnclosingNonVirtualFunctionInitializeIndirection(
InitializeIndirectionInstruction init, Function f
) {
not f.isVirtual() and
init.getEnclosingFunction() = f
}
/**
* Holds if `instr` is an argument (or argument indirection) to a call, and
* `succ` is the corresponding initialization instruction in the call target.
*/
private predicate flowThroughCallable(Instruction argument, Instruction parameter) {
// Flow from an argument to a parameter
exists(CallInstruction call, InitializeParameterInstruction init | init = parameter |
getPositionalArgumentInitParam(call, argument, init, call.getStaticCallTarget())
or
getThisArgumentInitParam(call, argument, init, call.getStaticCallTarget())
)
or
// Flow from argument indirection to parameter indirection
exists(
CallInstruction call, ReadSideEffectInstruction read, InitializeIndirectionInstruction init
|
init = parameter and
read.getPrimaryInstruction() = call and
getEnclosingNonVirtualFunctionInitializeIndirection(init, call.getStaticCallTarget())
|
exists(int n |
read.getSideEffectOperand().getAnyDef() = argument and
read.getIndex() = pragma[only_bind_into](n) and
init.getParameter().getIndex() = pragma[only_bind_into](n)
)
or
call.getThisArgument() = argument and
init.getIRVariable() instanceof IRThisVariable
)
}
private predicate instructionToOperandStep(Instruction instr, Operand operand) {
operand.getDef() = instr
}
/**
* Holds if data flows from `operand` to `instr`.
*
* This predicate ignores flow through `PhiInstruction`s to create a 'must flow' relation.
*/
private predicate operandToInstructionStep(Operand operand, Instruction instr) {
instr.(CopyInstruction).getSourceValueOperand() = operand
or
instr.(ConvertInstruction).getUnaryOperand() = operand
or
instr.(CheckedConvertOrNullInstruction).getUnaryOperand() = operand
or
instr.(InheritanceConversionInstruction).getUnaryOperand() = operand
or
instr.(ChiInstruction).getTotalOperand() = operand
}
cached
predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
instructionToOperandStep(nodeFrom.asInstruction(), nodeTo.asOperand())
or
flowThroughCallable(nodeFrom.asInstruction(), nodeTo.asInstruction())
or
operandToInstructionStep(nodeFrom.asOperand(), nodeTo.asInstruction())
}
}
/** Holds if `nodeFrom` flows to `nodeTo`. */
private predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, MustFlowConfiguration config) {
exists(config) and
Cached::step(nodeFrom, nodeTo)
or
config.isAdditionalFlowStep(nodeFrom, nodeTo)
}
private newtype TLocalPathNode =
MkLocalPathNode(DataFlow::Node n, MustFlowConfiguration config) {
flowsToSink(n, config) and
(
config.isSource(n)
or
exists(MustFlowPathNode mid | step(mid.getNode(), n, config))
)
}
/** A `Node` that is in a path from a source to a sink. */
class MustFlowPathNode extends TLocalPathNode {
DataFlow::Node n;
MustFlowPathNode() { this = MkLocalPathNode(n, _) }
/** Gets the underlying node. */
DataFlow::Node getNode() { result = n }
/** Gets a textual representation of this node. */
string toString() { result = n.toString() }
/** Gets the location of this element. */
Location getLocation() { result = n.getLocation() }
/** Gets a successor node, if any. */
MustFlowPathNode getASuccessor() {
step(this.getNode(), result.getNode(), this.getConfiguration())
}
/** Gets the associated configuration. */
MustFlowConfiguration getConfiguration() { this = MkLocalPathNode(_, result) }
}
private class MustFlowPathSink extends MustFlowPathNode {
MustFlowPathSink() { this.getConfiguration().isSink(this.getNode()) }
}
/**
* Provides the query predicates needed to include a graph in a path-problem query.
*/
module PathGraph {
private predicate reach(MustFlowPathNode n) {
n instanceof MustFlowPathSink or reach(n.getASuccessor())
}
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(MustFlowPathNode a, MustFlowPathNode b) {
a.getASuccessor() = b and reach(b)
}
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(MustFlowPathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
}
}

View File

@@ -17,7 +17,7 @@ private import semmle.code.cpp.ir.IR
*/ */
Function resolveCall(Call call) { Function resolveCall(Call call) {
exists(CallInstruction callInstruction | exists(CallInstruction callInstruction |
callInstruction.getAST() = call and callInstruction.getAst() = call and
result = viableCallable(callInstruction) result = viableCallable(callInstruction)
) )
} }

View File

@@ -20,10 +20,4 @@ import semmle.code.cpp.ir.dataflow.DataFlow2
module TaintTracking { module TaintTracking {
import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl
private import semmle.code.cpp.ir.dataflow.TaintTracking2
/**
* DEPRECATED: Use TaintTracking2::Configuration instead.
*/
deprecated class Configuration2 = TaintTracking2::Configuration;
} }

View File

@@ -116,12 +116,12 @@ private module VirtualDispatch {
/** Holds if `addressInstr` is an instruction that produces the address of `var`. */ /** Holds if `addressInstr` is an instruction that produces the address of `var`. */
private predicate addressOfGlobal(Instruction addressInstr, GlobalOrNamespaceVariable var) { private predicate addressOfGlobal(Instruction addressInstr, GlobalOrNamespaceVariable var) {
// Access directly to the global variable // Access directly to the global variable
addressInstr.(VariableAddressInstruction).getASTVariable() = var addressInstr.(VariableAddressInstruction).getAstVariable() = var
or or
// Access to a field on a global union // Access to a field on a global union
exists(FieldAddressInstruction fa | exists(FieldAddressInstruction fa |
fa = addressInstr and fa = addressInstr and
fa.getObjectAddress().(VariableAddressInstruction).getASTVariable() = var and fa.getObjectAddress().(VariableAddressInstruction).getAstVariable() = var and
fa.getField().getDeclaringType() instanceof Union fa.getField().getDeclaringType() instanceof Union
) )
} }

View File

@@ -87,12 +87,30 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */ /** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() } predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() } predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if the additional flow step from `node1` to `node2` must be taken * Holds if the additional flow step from `node1` to `node2` must be taken
* into account in the analysis. * into account in the analysis.
@@ -305,7 +323,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate inBarrier(NodeEx node, Configuration config) { private predicate fullInBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -314,7 +332,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate outBarrier(NodeEx node, Configuration config) { private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierOut(n) config.isBarrierOut(n)
@@ -323,6 +350,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -345,9 +381,19 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic] pragma[nomagic]
private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n | exists(Node n | node.asNode() = n |
node.asNode() = n and
config.isBarrier(n, state) config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }
@@ -376,8 +422,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */ /** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline] pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and not fullOutBarrier(node1, config) and
not inBarrier(node2, config) and not fullInBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -430,6 +476,8 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) not stateBarrier(node2, s2, config)
) )
@@ -471,6 +519,8 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -870,8 +920,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) { private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and revFlow(node, true, config) and
fwdFlow(node, true, config) and fwdFlow(node, true, config) and
not inBarrier(node, config) and not fullInBarrier(node, config) and
not outBarrier(node, config) not fullOutBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -966,8 +1016,8 @@ private predicate flowOutOfCallNodeCand1(
) { ) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and not fullOutBarrier(ret, config) and
not inBarrier(out, config) not fullInBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -988,8 +1038,8 @@ private predicate flowIntoCallNodeCand1(
) { ) {
viableParamArgNodeCand1(call, p, arg, config) and viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and Stage1::revFlow(p, config) and
not outBarrier(arg, config) and not fullOutBarrier(arg, config) and
not inBarrier(p, config) not fullInBarrier(p, config)
} }
/** /**
@@ -1706,18 +1756,31 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) or sourceNode(node, state, config)
jumpStep(_, node, config) or or
additionalJumpStep(_, node, config) or jumpStep(_, node, config)
additionalJumpStateStep(_, _, node, state, config) or or
node instanceof ParamNodeEx or additionalJumpStep(_, node, config)
node.asNode() instanceof OutNodeExt or or
store(_, _, node, _, config) or additionalJumpStateStep(_, _, node, state, config)
read(_, _, node, config) or or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
node instanceof FlowCheckNode node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
) )
} }
@@ -1737,6 +1800,9 @@ private module LocalFlowBigStep {
or or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config) additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
) )
or or
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
@@ -1770,42 +1836,40 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
DataFlowType t, Configuration config, LocalCallContext cc Configuration config, LocalCallContext cc
) { ) {
not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
( (
localFlowEntry(node1, pragma[only_bind_into](state1), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and
( (
localFlowStepNodeCand1(node1, node2, config) and localFlowStepNodeCand1(node1, node2, config) and
state1 = state2 and
preservesValue = true and preservesValue = true and
t = node1.getDataFlowType() // irrelevant dummy value t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType()
) and ) and
node1 != node2 and node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and cc.relevantFor(node1.getEnclosingCallable()) and
not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall())
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), preservesValue, t, localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t,
pragma[only_bind_into](config), cc) and pragma[only_bind_into](config), cc) and
localFlowStepNodeCand1(mid, node2, config) and localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid, FlowState st | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() and t = node2.getDataFlowType()
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1819,9 +1883,19 @@ private module LocalFlowBigStep {
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) { ) {
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config, localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
callContext) and localFlowExit(node2, state1, config) and
localFlowExit(node2, state2, config) state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
} }
} }
@@ -2695,10 +2769,10 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result = result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) node.getEnclosingCallable()) and
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,12 +87,30 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */ /** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() } predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() } predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if the additional flow step from `node1` to `node2` must be taken * Holds if the additional flow step from `node1` to `node2` must be taken
* into account in the analysis. * into account in the analysis.
@@ -305,7 +323,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate inBarrier(NodeEx node, Configuration config) { private predicate fullInBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -314,7 +332,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate outBarrier(NodeEx node, Configuration config) { private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierOut(n) config.isBarrierOut(n)
@@ -323,6 +350,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -345,9 +381,19 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic] pragma[nomagic]
private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n | exists(Node n | node.asNode() = n |
node.asNode() = n and
config.isBarrier(n, state) config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }
@@ -376,8 +422,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */ /** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline] pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and not fullOutBarrier(node1, config) and
not inBarrier(node2, config) and not fullInBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -430,6 +476,8 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) not stateBarrier(node2, s2, config)
) )
@@ -471,6 +519,8 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -870,8 +920,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) { private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and revFlow(node, true, config) and
fwdFlow(node, true, config) and fwdFlow(node, true, config) and
not inBarrier(node, config) and not fullInBarrier(node, config) and
not outBarrier(node, config) not fullOutBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -966,8 +1016,8 @@ private predicate flowOutOfCallNodeCand1(
) { ) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and not fullOutBarrier(ret, config) and
not inBarrier(out, config) not fullInBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -988,8 +1038,8 @@ private predicate flowIntoCallNodeCand1(
) { ) {
viableParamArgNodeCand1(call, p, arg, config) and viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and Stage1::revFlow(p, config) and
not outBarrier(arg, config) and not fullOutBarrier(arg, config) and
not inBarrier(p, config) not fullInBarrier(p, config)
} }
/** /**
@@ -1706,18 +1756,31 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) or sourceNode(node, state, config)
jumpStep(_, node, config) or or
additionalJumpStep(_, node, config) or jumpStep(_, node, config)
additionalJumpStateStep(_, _, node, state, config) or or
node instanceof ParamNodeEx or additionalJumpStep(_, node, config)
node.asNode() instanceof OutNodeExt or or
store(_, _, node, _, config) or additionalJumpStateStep(_, _, node, state, config)
read(_, _, node, config) or or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
node instanceof FlowCheckNode node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
) )
} }
@@ -1737,6 +1800,9 @@ private module LocalFlowBigStep {
or or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config) additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
) )
or or
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
@@ -1770,42 +1836,40 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
DataFlowType t, Configuration config, LocalCallContext cc Configuration config, LocalCallContext cc
) { ) {
not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
( (
localFlowEntry(node1, pragma[only_bind_into](state1), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and
( (
localFlowStepNodeCand1(node1, node2, config) and localFlowStepNodeCand1(node1, node2, config) and
state1 = state2 and
preservesValue = true and preservesValue = true and
t = node1.getDataFlowType() // irrelevant dummy value t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType()
) and ) and
node1 != node2 and node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and cc.relevantFor(node1.getEnclosingCallable()) and
not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall())
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), preservesValue, t, localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t,
pragma[only_bind_into](config), cc) and pragma[only_bind_into](config), cc) and
localFlowStepNodeCand1(mid, node2, config) and localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid, FlowState st | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() and t = node2.getDataFlowType()
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1819,9 +1883,19 @@ private module LocalFlowBigStep {
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) { ) {
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config, localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
callContext) and localFlowExit(node2, state1, config) and
localFlowExit(node2, state2, config) state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
} }
} }
@@ -2695,10 +2769,10 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result = result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) node.getEnclosingCallable()) and
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,12 +87,30 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */ /** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() } predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() } predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if the additional flow step from `node1` to `node2` must be taken * Holds if the additional flow step from `node1` to `node2` must be taken
* into account in the analysis. * into account in the analysis.
@@ -305,7 +323,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate inBarrier(NodeEx node, Configuration config) { private predicate fullInBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -314,7 +332,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate outBarrier(NodeEx node, Configuration config) { private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierOut(n) config.isBarrierOut(n)
@@ -323,6 +350,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -345,9 +381,19 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic] pragma[nomagic]
private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n | exists(Node n | node.asNode() = n |
node.asNode() = n and
config.isBarrier(n, state) config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }
@@ -376,8 +422,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */ /** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline] pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and not fullOutBarrier(node1, config) and
not inBarrier(node2, config) and not fullInBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -430,6 +476,8 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) not stateBarrier(node2, s2, config)
) )
@@ -471,6 +519,8 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -870,8 +920,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) { private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and revFlow(node, true, config) and
fwdFlow(node, true, config) and fwdFlow(node, true, config) and
not inBarrier(node, config) and not fullInBarrier(node, config) and
not outBarrier(node, config) not fullOutBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -966,8 +1016,8 @@ private predicate flowOutOfCallNodeCand1(
) { ) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and not fullOutBarrier(ret, config) and
not inBarrier(out, config) not fullInBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -988,8 +1038,8 @@ private predicate flowIntoCallNodeCand1(
) { ) {
viableParamArgNodeCand1(call, p, arg, config) and viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and Stage1::revFlow(p, config) and
not outBarrier(arg, config) and not fullOutBarrier(arg, config) and
not inBarrier(p, config) not fullInBarrier(p, config)
} }
/** /**
@@ -1706,18 +1756,31 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) or sourceNode(node, state, config)
jumpStep(_, node, config) or or
additionalJumpStep(_, node, config) or jumpStep(_, node, config)
additionalJumpStateStep(_, _, node, state, config) or or
node instanceof ParamNodeEx or additionalJumpStep(_, node, config)
node.asNode() instanceof OutNodeExt or or
store(_, _, node, _, config) or additionalJumpStateStep(_, _, node, state, config)
read(_, _, node, config) or or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
node instanceof FlowCheckNode node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
) )
} }
@@ -1737,6 +1800,9 @@ private module LocalFlowBigStep {
or or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config) additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
) )
or or
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
@@ -1770,42 +1836,40 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
DataFlowType t, Configuration config, LocalCallContext cc Configuration config, LocalCallContext cc
) { ) {
not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
( (
localFlowEntry(node1, pragma[only_bind_into](state1), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and
( (
localFlowStepNodeCand1(node1, node2, config) and localFlowStepNodeCand1(node1, node2, config) and
state1 = state2 and
preservesValue = true and preservesValue = true and
t = node1.getDataFlowType() // irrelevant dummy value t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType()
) and ) and
node1 != node2 and node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and cc.relevantFor(node1.getEnclosingCallable()) and
not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall())
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), preservesValue, t, localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t,
pragma[only_bind_into](config), cc) and pragma[only_bind_into](config), cc) and
localFlowStepNodeCand1(mid, node2, config) and localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid, FlowState st | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() and t = node2.getDataFlowType()
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1819,9 +1883,19 @@ private module LocalFlowBigStep {
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) { ) {
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config, localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
callContext) and localFlowExit(node2, state1, config) and
localFlowExit(node2, state2, config) state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
} }
} }
@@ -2695,10 +2769,10 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result = result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) node.getEnclosingCallable()) and
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,12 +87,30 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */ /** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() } predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */ /** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() } predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */ /** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() } predicate isBarrierGuard(BarrierGuard guard) { none() }
/**
* Holds if data flow through nodes guarded by `guard` is prohibited when
* the flow state is `state`
*/
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
/** /**
* Holds if the additional flow step from `node1` to `node2` must be taken * Holds if the additional flow step from `node1` to `node2` must be taken
* into account in the analysis. * into account in the analysis.
@@ -305,7 +323,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate inBarrier(NodeEx node, Configuration config) { private predicate fullInBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -314,7 +332,16 @@ private predicate inBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate outBarrier(NodeEx node, Configuration config) { private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierOut(n) config.isBarrierOut(n)
@@ -323,6 +350,15 @@ private predicate outBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic] pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) { private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n | exists(Node n | node.asNode() = n |
@@ -345,9 +381,19 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic] pragma[nomagic]
private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n | exists(Node n | node.asNode() = n |
node.asNode() = n and
config.isBarrier(n, state) config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
)
) )
} }
@@ -376,8 +422,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */ /** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline] pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not outBarrier(node1, config) and not fullOutBarrier(node1, config) and
not inBarrier(node2, config) and not fullInBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -430,6 +476,8 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) not stateBarrier(node2, s2, config)
) )
@@ -471,6 +519,8 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -870,8 +920,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) { private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and revFlow(node, true, config) and
fwdFlow(node, true, config) and fwdFlow(node, true, config) and
not inBarrier(node, config) and not fullInBarrier(node, config) and
not outBarrier(node, config) not fullOutBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -966,8 +1016,8 @@ private predicate flowOutOfCallNodeCand1(
) { ) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and Stage1::revFlow(ret, config) and
not outBarrier(ret, config) and not fullOutBarrier(ret, config) and
not inBarrier(out, config) not fullInBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -988,8 +1038,8 @@ private predicate flowIntoCallNodeCand1(
) { ) {
viableParamArgNodeCand1(call, p, arg, config) and viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and Stage1::revFlow(p, config) and
not outBarrier(arg, config) and not fullOutBarrier(arg, config) and
not inBarrier(p, config) not fullInBarrier(p, config)
} }
/** /**
@@ -1706,18 +1756,31 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local * Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path. * flow steps in a dataflow path.
*/ */
predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) or sourceNode(node, state, config)
jumpStep(_, node, config) or or
additionalJumpStep(_, node, config) or jumpStep(_, node, config)
additionalJumpStateStep(_, _, node, state, config) or or
node instanceof ParamNodeEx or additionalJumpStep(_, node, config)
node.asNode() instanceof OutNodeExt or or
store(_, _, node, _, config) or additionalJumpStateStep(_, _, node, state, config)
read(_, _, node, config) or or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
node instanceof FlowCheckNode node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
) )
} }
@@ -1737,6 +1800,9 @@ private module LocalFlowBigStep {
or or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config) additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
) )
or or
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
@@ -1770,42 +1836,40 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
DataFlowType t, Configuration config, LocalCallContext cc Configuration config, LocalCallContext cc
) { ) {
not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
( (
localFlowEntry(node1, pragma[only_bind_into](state1), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and
( (
localFlowStepNodeCand1(node1, node2, config) and localFlowStepNodeCand1(node1, node2, config) and
state1 = state2 and
preservesValue = true and preservesValue = true and
t = node1.getDataFlowType() // irrelevant dummy value t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType()
) and ) and
node1 != node2 and node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and cc.relevantFor(node1.getEnclosingCallable()) and
not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall())
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), preservesValue, t, localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t,
pragma[only_bind_into](config), cc) and pragma[only_bind_into](config), cc) and
localFlowStepNodeCand1(mid, node2, config) and localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid, FlowState st | exists(NodeEx mid |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() and t = node2.getDataFlowType()
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1819,9 +1883,19 @@ private module LocalFlowBigStep {
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) { ) {
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config, localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
callContext) and localFlowExit(node2, state1, config) and
localFlowExit(node2, state2, config) state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
} }
} }
@@ -2695,10 +2769,10 @@ private module Stage4 {
bindingset[node, cc, config] bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result = result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) node.getEnclosingCallable()) and
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -158,14 +158,6 @@ class Node extends TIRDataFlowNode {
*/ */
Expr asPartialDefinition() { result = this.(PartialDefinitionNode).getDefinedExpr() } Expr asPartialDefinition() { result = this.(PartialDefinitionNode).getDefinedExpr() }
/**
* DEPRECATED: See UninitializedNode.
*
* Gets the uninitialized local variable corresponding to this node, if
* any.
*/
deprecated LocalVariable asUninitialized() { none() }
/** /**
* Gets an upper bound on the type of this node. * Gets an upper bound on the type of this node.
*/ */
@@ -439,7 +431,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
SsaPhiNode() { this = TSsaPhiNode(phi) } SsaPhiNode() { this = TSsaPhiNode(phi) }
/* Get the phi node associated with this node. */ /** Gets the phi node associated with this node. */
Ssa::PhiNode getPhiNode() { result = phi } Ssa::PhiNode getPhiNode() { result = phi }
override Declaration getEnclosingCallable() { result = this.getFunction() } override Declaration getEnclosingCallable() { result = this.getFunction() }
@@ -560,22 +552,6 @@ class ParameterIndirectionNode extends ParameterNode {
override string toString() { result = "*" + instr.getIRVariable().toString() } override string toString() { result = "*" + instr.getIRVariable().toString() }
} }
/**
* DEPRECATED: Data flow was never an accurate way to determine what
* expressions might be uninitialized. It errs on the side of saying that
* everything is uninitialized, and this is even worse in the IR because the IR
* doesn't use syntactic hints to rule out variables that are definitely
* initialized.
*
* The value of an uninitialized local variable, viewed as a node in a data
* flow graph.
*/
deprecated class UninitializedNode extends Node {
UninitializedNode() { none() }
LocalVariable getLocalVariable() { none() }
}
/** /**
* A node associated with an object after an operation that might have * A node associated with an object after an operation that might have
* changed its state. * changed its state.
@@ -725,14 +701,6 @@ InstructionNode instructionNode(Instruction instr) { result.getInstruction() = i
*/ */
OperandNode operandNode(Operand operand) { result.getOperand() = operand } OperandNode operandNode(Operand operand) { result.getOperand() = operand }
/**
* DEPRECATED: use `definitionByReferenceNodeFromArgument` instead.
*
* Gets the `Node` corresponding to a definition by reference of the variable
* that is passed as `argument` of a call.
*/
deprecated DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e }
/** /**
* Gets the `Node` corresponding to the value of evaluating `e` or any of its * Gets the `Node` corresponding to the value of evaluating `e` or any of its
* conversions. There is no result if `e` is a `Conversion`. For data flowing * conversions. There is no result if `e` is a `Conversion`. For data flowing

View File

@@ -287,20 +287,6 @@ private module SsaDefReaches {
) )
} }
/**
* Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition
* `redef` in the same basic block, without crossing another SSA definition of `v`.
*/
predicate ssaDefReachesUncertainDefWithinBlock(
SourceVariable v, Definition def, UncertainWriteDefinition redef
) {
exists(BasicBlock bb, int rnk, int i |
ssaDefReachesRank(bb, def, rnk, v) and
rnk = ssaRefRank(bb, i, v, SsaDef()) - 1 and
redef.definesAt(v, bb, i)
)
}
/** /**
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`. * Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
*/ */

View File

@@ -64,13 +64,30 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() } override predicate isSource(DataFlow::Node source) { none() }
/** /**
* Holds if `sink` is a relevant taint sink. * Holds if `source` is a relevant taint source with the given initial
* `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
/**
* Holds if `sink` is a relevant taint sink
* *
* The smaller this predicate is, the faster `hasFlow()` will converge. * The smaller this predicate is, the faster `hasFlow()` will converge.
*/ */
// overridden to provide taint-tracking specific qldoc // overridden to provide taint-tracking specific qldoc
override predicate isSink(DataFlow::Node sink) { none() } override predicate isSink(DataFlow::Node sink) { none() }
/**
* Holds if `sink` is a relevant taint sink accepting `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() }
/** Holds if the node `node` is a taint sanitizer. */ /** Holds if the node `node` is a taint sanitizer. */
predicate isSanitizer(DataFlow::Node node) { none() } predicate isSanitizer(DataFlow::Node node) { none() }
@@ -79,9 +96,29 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintSanitizer(node) defaultTaintSanitizer(node)
} }
/**
* Holds if the node `node` is a taint sanitizer when the flow state is
* `state`.
*/
predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizer(node, state)
}
/** Holds if taint propagation into `node` is prohibited. */ /** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() } predicate isSanitizerIn(DataFlow::Node node) { none() }
/**
* Holds if taint propagation into `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerIn(node, state)
}
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */ /** Holds if taint propagation out of `node` is prohibited. */
@@ -89,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/**
* Holds if taint propagation out of `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerOut(node, state)
}
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
@@ -96,6 +143,16 @@ abstract class Configuration extends DataFlow::Configuration {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
} }
/**
* Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`.
*/
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
this.isSanitizerGuard(guard, state)
}
/** /**
* Holds if the additional taint propagation step from `node1` to `node2` * Holds if the additional taint propagation step from `node1` to `node2`
* must be taken into account in the analysis. * must be taken into account in the analysis.
@@ -107,6 +164,25 @@ abstract class Configuration extends DataFlow::Configuration {
defaultAdditionalTaintStep(node1, node2) defaultAdditionalTaintStep(node1, node2)
} }
/**
* Holds if the additional taint propagation step from `node1` to `node2`
* must be taken into account in the analysis. This step is only applicable
* in `state1` and updates the flow state to `state2`.
*/
predicate isAdditionalTaintStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
none()
}
final override predicate isAdditionalFlowStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
this.isAdditionalTaintStep(node1, state1, node2, state2)
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) { override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and (this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
defaultImplicitTaintRead(node, c) defaultImplicitTaintRead(node, c)

View File

@@ -64,13 +64,30 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() } override predicate isSource(DataFlow::Node source) { none() }
/** /**
* Holds if `sink` is a relevant taint sink. * Holds if `source` is a relevant taint source with the given initial
* `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
/**
* Holds if `sink` is a relevant taint sink
* *
* The smaller this predicate is, the faster `hasFlow()` will converge. * The smaller this predicate is, the faster `hasFlow()` will converge.
*/ */
// overridden to provide taint-tracking specific qldoc // overridden to provide taint-tracking specific qldoc
override predicate isSink(DataFlow::Node sink) { none() } override predicate isSink(DataFlow::Node sink) { none() }
/**
* Holds if `sink` is a relevant taint sink accepting `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() }
/** Holds if the node `node` is a taint sanitizer. */ /** Holds if the node `node` is a taint sanitizer. */
predicate isSanitizer(DataFlow::Node node) { none() } predicate isSanitizer(DataFlow::Node node) { none() }
@@ -79,9 +96,29 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintSanitizer(node) defaultTaintSanitizer(node)
} }
/**
* Holds if the node `node` is a taint sanitizer when the flow state is
* `state`.
*/
predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizer(node, state)
}
/** Holds if taint propagation into `node` is prohibited. */ /** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() } predicate isSanitizerIn(DataFlow::Node node) { none() }
/**
* Holds if taint propagation into `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerIn(node, state)
}
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */ /** Holds if taint propagation out of `node` is prohibited. */
@@ -89,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/**
* Holds if taint propagation out of `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerOut(node, state)
}
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
@@ -96,6 +143,16 @@ abstract class Configuration extends DataFlow::Configuration {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
} }
/**
* Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`.
*/
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
this.isSanitizerGuard(guard, state)
}
/** /**
* Holds if the additional taint propagation step from `node1` to `node2` * Holds if the additional taint propagation step from `node1` to `node2`
* must be taken into account in the analysis. * must be taken into account in the analysis.
@@ -107,6 +164,25 @@ abstract class Configuration extends DataFlow::Configuration {
defaultAdditionalTaintStep(node1, node2) defaultAdditionalTaintStep(node1, node2)
} }
/**
* Holds if the additional taint propagation step from `node1` to `node2`
* must be taken into account in the analysis. This step is only applicable
* in `state1` and updates the flow state to `state2`.
*/
predicate isAdditionalTaintStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
none()
}
final override predicate isAdditionalFlowStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
this.isAdditionalTaintStep(node1, state1, node2, state2)
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) { override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and (this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
defaultImplicitTaintRead(node, c) defaultImplicitTaintRead(node, c)

View File

@@ -64,13 +64,30 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() } override predicate isSource(DataFlow::Node source) { none() }
/** /**
* Holds if `sink` is a relevant taint sink. * Holds if `source` is a relevant taint source with the given initial
* `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
/**
* Holds if `sink` is a relevant taint sink
* *
* The smaller this predicate is, the faster `hasFlow()` will converge. * The smaller this predicate is, the faster `hasFlow()` will converge.
*/ */
// overridden to provide taint-tracking specific qldoc // overridden to provide taint-tracking specific qldoc
override predicate isSink(DataFlow::Node sink) { none() } override predicate isSink(DataFlow::Node sink) { none() }
/**
* Holds if `sink` is a relevant taint sink accepting `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() }
/** Holds if the node `node` is a taint sanitizer. */ /** Holds if the node `node` is a taint sanitizer. */
predicate isSanitizer(DataFlow::Node node) { none() } predicate isSanitizer(DataFlow::Node node) { none() }
@@ -79,9 +96,29 @@ abstract class Configuration extends DataFlow::Configuration {
defaultTaintSanitizer(node) defaultTaintSanitizer(node)
} }
/**
* Holds if the node `node` is a taint sanitizer when the flow state is
* `state`.
*/
predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizer(node, state)
}
/** Holds if taint propagation into `node` is prohibited. */ /** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() } predicate isSanitizerIn(DataFlow::Node node) { none() }
/**
* Holds if taint propagation into `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerIn(node, state)
}
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */ /** Holds if taint propagation out of `node` is prohibited. */
@@ -89,6 +126,16 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/**
* Holds if taint propagation out of `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerOut(node, state)
}
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */ /** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
@@ -96,6 +143,16 @@ abstract class Configuration extends DataFlow::Configuration {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard) this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
} }
/**
* Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`.
*/
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
this.isSanitizerGuard(guard, state)
}
/** /**
* Holds if the additional taint propagation step from `node1` to `node2` * Holds if the additional taint propagation step from `node1` to `node2`
* must be taken into account in the analysis. * must be taken into account in the analysis.
@@ -107,6 +164,25 @@ abstract class Configuration extends DataFlow::Configuration {
defaultAdditionalTaintStep(node1, node2) defaultAdditionalTaintStep(node1, node2)
} }
/**
* Holds if the additional taint propagation step from `node1` to `node2`
* must be taken into account in the analysis. This step is only applicable
* in `state1` and updates the flow state to `state2`.
*/
predicate isAdditionalTaintStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
none()
}
final override predicate isAdditionalFlowStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
this.isAdditionalTaintStep(node1, state1, node2, state2)
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) { override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and (this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
defaultImplicitTaintRead(node, c) defaultImplicitTaintRead(node, c)

View File

@@ -55,7 +55,10 @@ class IRVariable extends TIRVariable {
* Gets the AST node that declared this variable, or that introduced this * Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation. * variable as part of the AST-to-IR translation.
*/ */
Language::AST getAST() { none() } Language::AST getAst() { none() }
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = getAst() }
/** /**
* Gets an identifier string for the variable. This identifier is unique * Gets an identifier string for the variable. This identifier is unique
@@ -66,7 +69,7 @@ class IRVariable extends TIRVariable {
/** /**
* Gets the source location of this variable. * Gets the source location of this variable.
*/ */
final Language::Location getLocation() { result = getAST().getLocation() } final Language::Location getLocation() { result = getAst().getLocation() }
/** /**
* Gets the IR for the function that references this variable. * Gets the IR for the function that references this variable.
@@ -90,7 +93,10 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
final override string toString() { result = getVariable().toString() } final override string toString() { result = getVariable().toString() }
final override Language::AST getAST() { result = var } final override Language::AST getAst() { result = var }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = getAst() }
final override string getUniqueId() { final override string getUniqueId() {
result = getVariable().toString() + " " + getVariable().getLocation().toString() result = getVariable().toString() + " " + getVariable().getLocation().toString()
@@ -157,7 +163,10 @@ class IRGeneratedVariable extends IRVariable {
final override Language::LanguageType getLanguageType() { result = type } final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAST() { result = ast } final override Language::AST getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = getAst() }
override string toString() { result = getBaseString() + getLocationString() } override string toString() { result = getBaseString() + getLocationString() }

View File

@@ -41,7 +41,7 @@ class Instruction extends Construction::TStageInstruction {
} }
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */
final string toString() { result = this.getOpcode().toString() + ": " + this.getAST().toString() } final string toString() { result = this.getOpcode().toString() + ": " + this.getAst().toString() }
/** /**
* Gets a string showing the result, opcode, and operands of the instruction, equivalent to what * Gets a string showing the result, opcode, and operands of the instruction, equivalent to what
@@ -136,7 +136,7 @@ class Instruction extends Construction::TStageInstruction {
string getResultId() { string getResultId() {
this.shouldGenerateDumpStrings() and this.shouldGenerateDumpStrings() and
result = result =
this.getResultPrefix() + this.getAST().getLocation().getStartLine() + "_" + this.getLineRank() this.getResultPrefix() + this.getAst().getLocation().getStartLine() + "_" + this.getLineRank()
} }
/** /**
@@ -208,12 +208,15 @@ class Instruction extends Construction::TStageInstruction {
/** /**
* Gets the AST that caused this instruction to be generated. * Gets the AST that caused this instruction to be generated.
*/ */
final Language::AST getAST() { result = Construction::getInstructionAST(this) } final Language::AST getAst() { result = Construction::getInstructionAst(this) }
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
/** /**
* Gets the location of the source code for this instruction. * Gets the location of the source code for this instruction.
*/ */
final Language::Location getLocation() { result = this.getAST().getLocation() } final Language::Location getLocation() { result = this.getAst().getLocation() }
/** /**
* Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a * Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a
@@ -459,7 +462,10 @@ class VariableInstruction extends Instruction {
/** /**
* Gets the AST variable that this instruction's IR variable refers to, if one exists. * Gets the AST variable that this instruction's IR variable refers to, if one exists.
*/ */
final Language::Variable getASTVariable() { result = var.(IRUserVariable).getVariable() } final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
/** DEPRECATED: Alias for getAstVariable */
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
} }
/** /**

View File

@@ -18,7 +18,7 @@ private import internal.OperandInternal
* of `TOperand` that are used in this stage. * of `TOperand` that are used in this stage.
*/ */
private class TStageOperand = private class TStageOperand =
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand; TRegisterOperand or TNonSsaMemoryOperand or TPhiOperand or TChiOperand;
/** /**
* A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as * A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as
@@ -38,7 +38,7 @@ class Operand extends TStageOperand {
// Ensure that the operand does not refer to instructions from earlier stages that are unreachable here // Ensure that the operand does not refer to instructions from earlier stages that are unreachable here
exists(Instruction use, Instruction def | this = registerOperand(use, _, def)) exists(Instruction use, Instruction def | this = registerOperand(use, _, def))
or or
exists(Instruction use | this = nonSSAMemoryOperand(use, _)) exists(Instruction use | this = nonSsaMemoryOperand(use, _))
or or
exists(Instruction use, Instruction def, IRBlock predecessorBlock | exists(Instruction use, Instruction def, IRBlock predecessorBlock |
this = phiOperand(use, def, predecessorBlock, _) or this = phiOperand(use, def, predecessorBlock, _) or
@@ -209,7 +209,7 @@ class Operand extends TStageOperand {
class MemoryOperand extends Operand { class MemoryOperand extends Operand {
cached cached
MemoryOperand() { MemoryOperand() {
this instanceof TNonSSAMemoryOperand or this instanceof TNonSsaMemoryOperand or
this instanceof TPhiOperand or this instanceof TPhiOperand or
this instanceof TChiOperand this instanceof TChiOperand
} }
@@ -249,7 +249,7 @@ class NonPhiOperand extends Operand {
NonPhiOperand() { NonPhiOperand() {
this = registerOperand(useInstr, tag, _) or this = registerOperand(useInstr, tag, _) or
this = nonSSAMemoryOperand(useInstr, tag) or this = nonSsaMemoryOperand(useInstr, tag) or
this = chiOperand(useInstr, tag) this = chiOperand(useInstr, tag)
} }
@@ -299,7 +299,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
cached cached
NonPhiMemoryOperand() { NonPhiMemoryOperand() {
this = nonSSAMemoryOperand(useInstr, tag) this = nonSsaMemoryOperand(useInstr, tag)
or or
this = chiOperand(useInstr, tag) this = chiOperand(useInstr, tag)
} }

View File

@@ -99,7 +99,7 @@ private predicate filteredNumberableInstruction(Instruction instr) {
// count rather than strictcount to handle missing AST elements // count rather than strictcount to handle missing AST elements
// separate instanceof and inline casts to avoid failed casts with a count of 0 // separate instanceof and inline casts to avoid failed casts with a count of 0
instr instanceof VariableAddressInstruction and instr instanceof VariableAddressInstruction and
count(instr.(VariableAddressInstruction).getIRVariable().getAST()) != 1 count(instr.(VariableAddressInstruction).getIRVariable().getAst()) != 1
or or
instr instanceof ConstantInstruction and instr instanceof ConstantInstruction and
count(instr.getResultIRType()) != 1 count(instr.getResultIRType()) != 1
@@ -121,7 +121,7 @@ private predicate variableAddressValueNumber(
// The underlying AST element is used as value-numbering key instead of the // The underlying AST element is used as value-numbering key instead of the
// `IRVariable` to work around a problem where a variable or expression with // `IRVariable` to work around a problem where a variable or expression with
// multiple types gives rise to multiple `IRVariable`s. // multiple types gives rise to multiple `IRVariable`s.
unique( | | instr.getIRVariable().getAST()) = ast unique( | | instr.getIRVariable().getAst()) = ast
} }
private predicate initializeParameterValueNumber( private predicate initializeParameterValueNumber(
@@ -131,7 +131,7 @@ private predicate initializeParameterValueNumber(
// The underlying AST element is used as value-numbering key instead of the // The underlying AST element is used as value-numbering key instead of the
// `IRVariable` to work around a problem where a variable or expression with // `IRVariable` to work around a problem where a variable or expression with
// multiple types gives rise to multiple `IRVariable`s. // multiple types gives rise to multiple `IRVariable`s.
instr.getIRVariable().getAST() = var instr.getIRVariable().getAst() = var
} }
private predicate constantValueNumber( private predicate constantValueNumber(

View File

@@ -2,12 +2,12 @@ private import AliasConfigurationInternal
private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
private import cpp private import cpp
private import AliasAnalysis private import AliasAnalysis
private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SimpleSSA as UnaliasedSSA private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SimpleSSA as UnaliasedSsa
private newtype TAllocation = private newtype TAllocation =
TVariableAllocation(IRVariable var) { TVariableAllocation(IRVariable var) {
// Only model variables that were not already handled in unaliased SSA. // Only model variables that were not already handled in unaliased SSA.
not UnaliasedSSA::canReuseSSAForVariable(var) not UnaliasedSsa::canReuseSsaForVariable(var)
} or } or
TIndirectParameterAllocation(IRAutomaticVariable var) { TIndirectParameterAllocation(IRAutomaticVariable var) {
exists(InitializeIndirectionInstruction instr | instr.getIRVariable() = var) exists(InitializeIndirectionInstruction instr | instr.getIRVariable() = var)

View File

@@ -133,7 +133,10 @@ abstract class MemoryLocation extends TMemoryLocation {
*/ */
predicate isAlwaysAllocatedOnStack() { none() } predicate isAlwaysAllocatedOnStack() { none() }
final predicate canReuseSSA() { none() } final predicate canReuseSsa() { none() }
/** DEPRECATED: Alias for canReuseSsa */
deprecated predicate canReuseSSA() { canReuseSsa() }
} }
/** /**
@@ -569,13 +572,16 @@ private Overlap getVariableMemoryLocationOverlap(
* Holds if the def/use information for the result of `instr` can be reused from the previous * Holds if the def/use information for the result of `instr` can be reused from the previous
* iteration of the IR. * iteration of the IR.
*/ */
predicate canReuseSSAForOldResult(Instruction instr) { OldSSA::canReuseSSAForMemoryResult(instr) } predicate canReuseSsaForOldResult(Instruction instr) { OldSSA::canReuseSsaForMemoryResult(instr) }
/** DEPRECATED: Alias for canReuseSsaForOldResult */
deprecated predicate canReuseSSAForOldResult = canReuseSsaForOldResult/1;
bindingset[result, b] bindingset[result, b]
private boolean unbindBool(boolean b) { result != b.booleanNot() } private boolean unbindBool(boolean b) { result != b.booleanNot() }
MemoryLocation getResultMemoryLocation(Instruction instr) { MemoryLocation getResultMemoryLocation(Instruction instr) {
not canReuseSSAForOldResult(instr) and not canReuseSsaForOldResult(instr) and
exists(MemoryAccessKind kind, boolean isMayAccess | exists(MemoryAccessKind kind, boolean isMayAccess |
kind = instr.getResultMemoryAccess() and kind = instr.getResultMemoryAccess() and
(if instr.hasResultMayMemoryAccess() then isMayAccess = true else isMayAccess = false) and (if instr.hasResultMayMemoryAccess() then isMayAccess = true else isMayAccess = false) and
@@ -608,7 +614,7 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
} }
MemoryLocation getOperandMemoryLocation(MemoryOperand operand) { MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
not canReuseSSAForOldResult(operand.getAnyDef()) and not canReuseSsaForOldResult(operand.getAnyDef()) and
exists(MemoryAccessKind kind, boolean isMayAccess | exists(MemoryAccessKind kind, boolean isMayAccess |
kind = operand.getMemoryAccess() and kind = operand.getMemoryAccess() and
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and (if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and

View File

@@ -1,2 +1,2 @@
private import semmle.code.cpp.ir.implementation.internal.TOperand private import semmle.code.cpp.ir.implementation.internal.TOperand
import AliasedSSAOperands import AliasedSsaOperands

View File

@@ -2,7 +2,7 @@ private import SSAConstructionInternal
private import OldIR private import OldIR
private import Alias private import Alias
private import SSAConstruction private import SSAConstruction
private import DebugSSA private import DebugSsa
bindingset[offset] bindingset[offset]
private string getKeySuffixForOffset(int offset) { private string getKeySuffixForOffset(int offset) {

View File

@@ -1,2 +1,2 @@
private import SSAConstruction as SSA private import SSAConstruction as SSA
import SSA::SSAConsistency import SSA::SsaConsistency

View File

@@ -112,7 +112,7 @@ private module Cached {
exists(Alias::getResultMemoryLocation(oldInstruction)) exists(Alias::getResultMemoryLocation(oldInstruction))
or or
// This result was already modeled by a previous iteration of SSA. // This result was already modeled by a previous iteration of SSA.
Alias::canReuseSSAForOldResult(oldInstruction) Alias::canReuseSsaForOldResult(oldInstruction)
} }
cached cached
@@ -182,7 +182,7 @@ private module Cached {
* unreachable, this predicate will recurse through any degenerate `Phi` instructions to find the * unreachable, this predicate will recurse through any degenerate `Phi` instructions to find the
* true definition. * true definition.
*/ */
private Instruction getNewDefinitionFromOldSSA(OldIR::MemoryOperand oldOperand, Overlap overlap) { private Instruction getNewDefinitionFromOldSsa(OldIR::MemoryOperand oldOperand, Overlap overlap) {
exists(Overlap originalOverlap | exists(Overlap originalOverlap |
originalOverlap = oldOperand.getDefinitionOverlap() and originalOverlap = oldOperand.getDefinitionOverlap() and
( (
@@ -191,7 +191,7 @@ private module Cached {
or or
exists(OldIR::PhiInputOperand phiOperand, Overlap phiOperandOverlap | exists(OldIR::PhiInputOperand phiOperand, Overlap phiOperandOverlap |
phiOperand = getDegeneratePhiOperand(oldOperand.getAnyDef()) and phiOperand = getDegeneratePhiOperand(oldOperand.getAnyDef()) and
result = getNewDefinitionFromOldSSA(phiOperand, phiOperandOverlap) and result = getNewDefinitionFromOldSsa(phiOperand, phiOperandOverlap) and
overlap = overlap =
combineOverlap(pragma[only_bind_out](phiOperandOverlap), combineOverlap(pragma[only_bind_out](phiOperandOverlap),
pragma[only_bind_out](originalOverlap)) pragma[only_bind_out](originalOverlap))
@@ -233,7 +233,7 @@ private module Cached {
) )
or or
exists(OldIR::NonPhiMemoryOperand oldOperand | exists(OldIR::NonPhiMemoryOperand oldOperand |
result = getNewDefinitionFromOldSSA(oldOperand, overlap) and result = getNewDefinitionFromOldSsa(oldOperand, overlap) and
oldOperand.getUse() = instruction and oldOperand.getUse() = instruction and
tag = oldOperand.getOperandTag() tag = oldOperand.getOperandTag()
) )
@@ -307,13 +307,13 @@ private module Cached {
* Gets the new definition instruction for the operand of `instr` that flows from the block * Gets the new definition instruction for the operand of `instr` that flows from the block
* `newPredecessorBlock`, based on that operand's definition in the old IR. * `newPredecessorBlock`, based on that operand's definition in the old IR.
*/ */
private Instruction getNewPhiOperandDefinitionFromOldSSA( private Instruction getNewPhiOperandDefinitionFromOldSsa(
Instruction instr, IRBlock newPredecessorBlock, Overlap overlap Instruction instr, IRBlock newPredecessorBlock, Overlap overlap
) { ) {
exists(OldIR::PhiInstruction oldPhi, OldIR::PhiInputOperand oldOperand | exists(OldIR::PhiInstruction oldPhi, OldIR::PhiInputOperand oldOperand |
oldPhi = getOldInstruction(instr) and oldPhi = getOldInstruction(instr) and
oldOperand = oldPhi.getInputOperand(getOldBlock(newPredecessorBlock)) and oldOperand = oldPhi.getInputOperand(getOldBlock(newPredecessorBlock)) and
result = getNewDefinitionFromOldSSA(oldOperand, overlap) result = getNewDefinitionFromOldSsa(oldOperand, overlap)
) )
} }
@@ -333,7 +333,7 @@ private module Cached {
overlap = Alias::getOverlap(actualDefLocation, useLocation) overlap = Alias::getOverlap(actualDefLocation, useLocation)
) )
or or
result = getNewPhiOperandDefinitionFromOldSSA(instr, newPredecessorBlock, overlap) result = getNewPhiOperandDefinitionFromOldSsa(instr, newPredecessorBlock, overlap)
} }
cached cached
@@ -412,17 +412,17 @@ private module Cached {
} }
cached cached
Language::AST getInstructionAST(Instruction instr) { Language::AST getInstructionAst(Instruction instr) {
result = getOldInstruction(instr).getAST() result = getOldInstruction(instr).getAst()
or or
exists(RawIR::Instruction blockStartInstr | exists(RawIR::Instruction blockStartInstr |
instr = phiInstruction(blockStartInstr, _) and instr = phiInstruction(blockStartInstr, _) and
result = blockStartInstr.getAST() result = blockStartInstr.getAst()
) )
or or
exists(RawIR::Instruction primaryInstr | exists(RawIR::Instruction primaryInstr |
instr = chiInstruction(primaryInstr) and instr = chiInstruction(primaryInstr) and
result = primaryInstr.getAST() result = primaryInstr.getAst()
) )
or or
exists(IRFunctionBase irFunc | exists(IRFunctionBase irFunc |
@@ -430,6 +430,12 @@ private module Cached {
) )
} }
/** DEPRECATED: Alias for getInstructionAst */
cached
deprecated Language::AST getInstructionAST(Instruction instr) {
result = getInstructionAst(instr)
}
cached cached
Language::LanguageType getInstructionResultType(Instruction instr) { Language::LanguageType getInstructionResultType(Instruction instr) {
result = instr.(RawIR::Instruction).getResultLanguageType() result = instr.(RawIR::Instruction).getResultLanguageType()
@@ -975,35 +981,41 @@ module DefUse {
} }
} }
predicate canReuseSSAForMemoryResult(Instruction instruction) { predicate canReuseSsaForMemoryResult(Instruction instruction) {
exists(OldInstruction oldInstruction | exists(OldInstruction oldInstruction |
oldInstruction = getOldInstruction(instruction) and oldInstruction = getOldInstruction(instruction) and
( (
// The previous iteration said it was reusable, so we should mark it as reusable as well. // The previous iteration said it was reusable, so we should mark it as reusable as well.
Alias::canReuseSSAForOldResult(oldInstruction) Alias::canReuseSsaForOldResult(oldInstruction)
or or
// The current alias analysis says it is reusable. // The current alias analysis says it is reusable.
Alias::getResultMemoryLocation(oldInstruction).canReuseSSA() Alias::getResultMemoryLocation(oldInstruction).canReuseSsa()
) )
) )
or or
exists(Alias::MemoryLocation defLocation | exists(Alias::MemoryLocation defLocation |
// This is a `Phi` for a reusable location, so the result of the `Phi` is reusable as well. // This is a `Phi` for a reusable location, so the result of the `Phi` is reusable as well.
instruction = phiInstruction(_, defLocation) and instruction = phiInstruction(_, defLocation) and
defLocation.canReuseSSA() defLocation.canReuseSsa()
) )
// We don't support reusing SSA for any location that could create a `Chi` instruction. // We don't support reusing SSA for any location that could create a `Chi` instruction.
} }
/** DEPRECATED: Alias for canReuseSsaForMemoryResult */
deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1;
/** /**
* Expose some of the internal predicates to PrintSSA.qll. We do this by publically importing those modules in the * Expose some of the internal predicates to PrintSSA.qll. We do this by publically importing those modules in the
* `DebugSSA` module, which is then imported by PrintSSA. * `DebugSSA` module, which is then imported by PrintSSA.
*/ */
module DebugSSA { module DebugSsa {
import PhiInsertion import PhiInsertion
import DefUse import DefUse
} }
/** DEPRECATED: Alias for DebugSsa */
deprecated module DebugSSA = DebugSsa;
import CachedForDebugging import CachedForDebugging
cached cached
@@ -1038,7 +1050,7 @@ private module CachedForDebugging {
private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) { private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) {
result.getEnclosingFunction() = var.getEnclosingFunction() and result.getEnclosingFunction() = var.getEnclosingFunction() and
result.getAST() = var.getAST() and result.getAst() = var.getAst() and
result.getTag() = var.getTag() result.getTag() = var.getTag()
} }
@@ -1061,7 +1073,7 @@ private module CachedForDebugging {
int maxValue() { result = 2147483647 } int maxValue() { result = 2147483647 }
} }
module SSAConsistency { module SsaConsistency {
/** /**
* Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis. * Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis.
*/ */
@@ -1114,6 +1126,9 @@ module SSAConsistency {
} }
} }
/** DEPRECATED: Alias for SsaConsistency */
deprecated module SSAConsistency = SsaConsistency;
/** /**
* Provides the portion of the parameterized IR interface that is used to construct the SSA stages * Provides the portion of the parameterized IR interface that is used to construct the SSA stages
* of the IR. The raw stage of the IR does not expose these predicates. * of the IR. The raw stage of the IR does not expose these predicates.

View File

@@ -2,7 +2,7 @@ import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as OldIR
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.ReachableBlock as Reachability import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.ReachableBlock as Reachability
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.Dominance as Dominance import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.Dominance as Dominance
import semmle.code.cpp.ir.implementation.aliased_ssa.IR as NewIR import semmle.code.cpp.ir.implementation.aliased_ssa.IR as NewIR
import semmle.code.cpp.ir.implementation.internal.TInstruction::AliasedSSAInstructions as SSAInstructions import semmle.code.cpp.ir.implementation.internal.TInstruction::AliasedSsaInstructions as SSAInstructions
import semmle.code.cpp.ir.internal.IRCppLanguage as Language import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import AliasedSSA as Alias import AliasedSSA as Alias
import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSSAOperands as SSAOperands import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSsaOperands as SSAOperands

View File

@@ -19,24 +19,24 @@ newtype TInstruction =
) { ) {
IRConstruction::Raw::hasInstruction(tag1, tag2) IRConstruction::Raw::hasInstruction(tag1, tag2)
} or } or
TUnaliasedSSAPhiInstruction( TUnaliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, UnaliasedSSA::SSA::MemoryLocation memoryLocation TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation
) { ) {
UnaliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) UnaliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
} or } or
TUnaliasedSSAChiInstruction(TRawInstruction primaryInstruction) { none() } or TUnaliasedSsaChiInstruction(TRawInstruction primaryInstruction) { none() } or
TUnaliasedSSAUnreachedInstruction(IRFunctionBase irFunc) { TUnaliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
UnaliasedSSA::SSA::hasUnreachedInstruction(irFunc) UnaliasedSsa::SSA::hasUnreachedInstruction(irFunc)
} or } or
TAliasedSSAPhiInstruction( TAliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
) { ) {
AliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) AliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
} or } or
TAliasedSSAChiInstruction(TRawInstruction primaryInstruction) { TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
AliasedSSA::SSA::hasChiInstruction(primaryInstruction) AliasedSSA::SSA::hasChiInstruction(primaryInstruction)
} or } or
TAliasedSSAUnreachedInstruction(IRFunctionBase irFunc) { TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
AliasedSSA::SSA::hasUnreachedInstruction(irFunc) AliasedSSA::SSA::hasUnreachedInstruction(irFunc)
} }
@@ -46,58 +46,64 @@ newtype TInstruction =
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via * These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
* a class alias. * a class alias.
*/ */
module UnaliasedSSAInstructions { module UnaliasedSsaInstructions {
class TPhiInstruction = TUnaliasedSSAPhiInstruction; class TPhiInstruction = TUnaliasedSsaPhiInstruction;
TPhiInstruction phiInstruction( TPhiInstruction phiInstruction(
TRawInstruction blockStartInstr, UnaliasedSSA::SSA::MemoryLocation memoryLocation TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation
) { ) {
result = TUnaliasedSSAPhiInstruction(blockStartInstr, memoryLocation) result = TUnaliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
} }
TRawInstruction reusedPhiInstruction(TRawInstruction blockStartInstr) { none() } TRawInstruction reusedPhiInstruction(TRawInstruction blockStartInstr) { none() }
class TChiInstruction = TUnaliasedSSAChiInstruction; class TChiInstruction = TUnaliasedSsaChiInstruction;
TChiInstruction chiInstruction(TRawInstruction primaryInstruction) { TChiInstruction chiInstruction(TRawInstruction primaryInstruction) {
result = TUnaliasedSSAChiInstruction(primaryInstruction) result = TUnaliasedSsaChiInstruction(primaryInstruction)
} }
class TUnreachedInstruction = TUnaliasedSSAUnreachedInstruction; class TUnreachedInstruction = TUnaliasedSsaUnreachedInstruction;
TUnreachedInstruction unreachedInstruction(IRFunctionBase irFunc) { TUnreachedInstruction unreachedInstruction(IRFunctionBase irFunc) {
result = TUnaliasedSSAUnreachedInstruction(irFunc) result = TUnaliasedSsaUnreachedInstruction(irFunc)
} }
} }
/** DEPRECATED: Alias for UnaliasedSsaInstructions */
deprecated module UnaliasedSSAInstructions = UnaliasedSsaInstructions;
/** /**
* Provides wrappers for the constructors of each branch of `TInstruction` that is used by the * Provides wrappers for the constructors of each branch of `TInstruction` that is used by the
* aliased SSA stage. * aliased SSA stage.
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via * These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
* a class alias. * a class alias.
*/ */
module AliasedSSAInstructions { module AliasedSsaInstructions {
class TPhiInstruction = TAliasedSSAPhiInstruction or TUnaliasedSSAPhiInstruction; class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction;
TPhiInstruction phiInstruction( TPhiInstruction phiInstruction(
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
) { ) {
result = TAliasedSSAPhiInstruction(blockStartInstr, memoryLocation) result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
} }
TPhiInstruction reusedPhiInstruction(TRawInstruction blockStartInstr) { TPhiInstruction reusedPhiInstruction(TRawInstruction blockStartInstr) {
result = TUnaliasedSSAPhiInstruction(blockStartInstr, _) result = TUnaliasedSsaPhiInstruction(blockStartInstr, _)
} }
class TChiInstruction = TAliasedSSAChiInstruction; class TChiInstruction = TAliasedSsaChiInstruction;
TChiInstruction chiInstruction(TRawInstruction primaryInstruction) { TChiInstruction chiInstruction(TRawInstruction primaryInstruction) {
result = TAliasedSSAChiInstruction(primaryInstruction) result = TAliasedSsaChiInstruction(primaryInstruction)
} }
class TUnreachedInstruction = TAliasedSSAUnreachedInstruction; class TUnreachedInstruction = TAliasedSsaUnreachedInstruction;
TUnreachedInstruction unreachedInstruction(IRFunctionBase irFunc) { TUnreachedInstruction unreachedInstruction(IRFunctionBase irFunc) {
result = TAliasedSSAUnreachedInstruction(irFunc) result = TAliasedSsaUnreachedInstruction(irFunc)
} }
} }
/** DEPRECATED: Alias for AliasedSsaInstructions */
deprecated module AliasedSSAInstructions = AliasedSsaInstructions;

View File

@@ -1,4 +1,4 @@
import semmle.code.cpp.ir.internal.IRCppLanguage as Language import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedSSA import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedSsa
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as AliasedSSA import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as AliasedSSA

View File

@@ -31,7 +31,7 @@ private module Internal {
TNoOperand() { none() } or TNoOperand() { none() } or
// Can be "removed" later when there's unreachable code // Can be "removed" later when there's unreachable code
// These operands can be reused across all three stages. They just get different defs. // These operands can be reused across all three stages. They just get different defs.
TNonSSAMemoryOperand(Raw::Instruction useInstr, MemoryOperandTag tag) { TNonSsaMemoryOperand(Raw::Instruction useInstr, MemoryOperandTag tag) {
// Has no definition in raw but will get definitions later // Has no definition in raw but will get definitions later
useInstr.getOpcode().hasOperand(tag) useInstr.getOpcode().hasOperand(tag)
} or } or
@@ -49,11 +49,11 @@ private module Internal {
// important that we use the same definition of "is variable aliased" across // important that we use the same definition of "is variable aliased" across
// the phases. // the phases.
TAliasedPhiOperand( TAliasedPhiOperand(
TAliasedSSAPhiInstruction useInstr, Aliased::IRBlock predecessorBlock, Overlap overlap TAliasedSsaPhiInstruction useInstr, Aliased::IRBlock predecessorBlock, Overlap overlap
) { ) {
exists(AliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap)) exists(AliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap))
} or } or
TAliasedChiOperand(TAliasedSSAChiInstruction useInstr, ChiOperandTag tag) { any() } TAliasedChiOperand(TAliasedSsaChiInstruction useInstr, ChiOperandTag tag) { any() }
} }
/** /**
@@ -72,13 +72,21 @@ private module Shared {
result = Internal::TRegisterOperand(useInstr, tag, defInstr) result = Internal::TRegisterOperand(useInstr, tag, defInstr)
} }
class TNonSSAMemoryOperand = Internal::TNonSSAMemoryOperand; class TNonSsaMemoryOperand = Internal::TNonSsaMemoryOperand;
/** DEPRECATED: Alias for TNonSsaMemoryOperand */
deprecated class TNonSSAMemoryOperand = TNonSsaMemoryOperand;
/** /**
* Returns the non-Phi memory operand with the specified parameters. * Returns the non-Phi memory operand with the specified parameters.
*/ */
TNonSSAMemoryOperand nonSSAMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) { TNonSsaMemoryOperand nonSsaMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) {
result = Internal::TNonSSAMemoryOperand(useInstr, tag) result = Internal::TNonSsaMemoryOperand(useInstr, tag)
}
/** DEPRECATED: Alias for nonSsaMemoryOperand */
deprecated TNonSSAMemoryOperand nonSSAMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) {
result = nonSsaMemoryOperand(useInstr, tag)
} }
} }
@@ -95,7 +103,7 @@ module RawOperands {
class TChiOperand = Internal::TNoOperand; class TChiOperand = Internal::TNoOperand;
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand; class TNonPhiMemoryOperand = TNonSsaMemoryOperand or TChiOperand;
/** /**
* Returns the Phi operand with the specified parameters. * Returns the Phi operand with the specified parameters.
@@ -126,14 +134,14 @@ module RawOperands {
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via * These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
* a class alias. * a class alias.
*/ */
module UnaliasedSSAOperands { module UnaliasedSsaOperands {
import Shared import Shared
class TPhiOperand = Internal::TUnaliasedPhiOperand; class TPhiOperand = Internal::TUnaliasedPhiOperand;
class TChiOperand = Internal::TNoOperand; class TChiOperand = Internal::TNoOperand;
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand; class TNonPhiMemoryOperand = TNonSsaMemoryOperand or TChiOperand;
/** /**
* Returns the Phi operand with the specified parameters. * Returns the Phi operand with the specified parameters.
@@ -159,20 +167,23 @@ module UnaliasedSSAOperands {
TChiOperand chiOperand(Unaliased::Instruction useInstr, ChiOperandTag tag) { none() } TChiOperand chiOperand(Unaliased::Instruction useInstr, ChiOperandTag tag) { none() }
} }
/** DEPRECATED: Alias for UnaliasedSsaOperands */
deprecated module UnaliasedSSAOperands = UnaliasedSsaOperands;
/** /**
* Provides wrappers for the constructors of each branch of `TOperand` that is used by the * Provides wrappers for the constructors of each branch of `TOperand` that is used by the
* asliased SSA stage. * asliased SSA stage.
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via * These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
* a class alias. * a class alias.
*/ */
module AliasedSSAOperands { module AliasedSsaOperands {
import Shared import Shared
class TPhiOperand = Internal::TAliasedPhiOperand or Internal::TUnaliasedPhiOperand; class TPhiOperand = Internal::TAliasedPhiOperand or Internal::TUnaliasedPhiOperand;
class TChiOperand = Internal::TAliasedChiOperand; class TChiOperand = Internal::TAliasedChiOperand;
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand; class TNonPhiMemoryOperand = TNonSsaMemoryOperand or TChiOperand;
/** /**
* Returns the Phi operand with the specified parameters. * Returns the Phi operand with the specified parameters.
@@ -202,7 +213,10 @@ module AliasedSSAOperands {
/** /**
* Returns the Chi operand with the specified parameters. * Returns the Chi operand with the specified parameters.
*/ */
TChiOperand chiOperand(TAliasedSSAChiInstruction useInstr, ChiOperandTag tag) { TChiOperand chiOperand(TAliasedSsaChiInstruction useInstr, ChiOperandTag tag) {
result = Internal::TAliasedChiOperand(useInstr, tag) result = Internal::TAliasedChiOperand(useInstr, tag)
} }
} }
/** DEPRECATED: Alias for AliasedSsaOperands */
deprecated module AliasedSSAOperands = AliasedSsaOperands;

View File

@@ -55,7 +55,10 @@ class IRVariable extends TIRVariable {
* Gets the AST node that declared this variable, or that introduced this * Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation. * variable as part of the AST-to-IR translation.
*/ */
Language::AST getAST() { none() } Language::AST getAst() { none() }
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = getAst() }
/** /**
* Gets an identifier string for the variable. This identifier is unique * Gets an identifier string for the variable. This identifier is unique
@@ -66,7 +69,7 @@ class IRVariable extends TIRVariable {
/** /**
* Gets the source location of this variable. * Gets the source location of this variable.
*/ */
final Language::Location getLocation() { result = getAST().getLocation() } final Language::Location getLocation() { result = getAst().getLocation() }
/** /**
* Gets the IR for the function that references this variable. * Gets the IR for the function that references this variable.
@@ -90,7 +93,10 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
final override string toString() { result = getVariable().toString() } final override string toString() { result = getVariable().toString() }
final override Language::AST getAST() { result = var } final override Language::AST getAst() { result = var }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = getAst() }
final override string getUniqueId() { final override string getUniqueId() {
result = getVariable().toString() + " " + getVariable().getLocation().toString() result = getVariable().toString() + " " + getVariable().getLocation().toString()
@@ -157,7 +163,10 @@ class IRGeneratedVariable extends IRVariable {
final override Language::LanguageType getLanguageType() { result = type } final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAST() { result = ast } final override Language::AST getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = getAst() }
override string toString() { result = getBaseString() + getLocationString() } override string toString() { result = getBaseString() + getLocationString() }

View File

@@ -41,7 +41,7 @@ class Instruction extends Construction::TStageInstruction {
} }
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */
final string toString() { result = this.getOpcode().toString() + ": " + this.getAST().toString() } final string toString() { result = this.getOpcode().toString() + ": " + this.getAst().toString() }
/** /**
* Gets a string showing the result, opcode, and operands of the instruction, equivalent to what * Gets a string showing the result, opcode, and operands of the instruction, equivalent to what
@@ -136,7 +136,7 @@ class Instruction extends Construction::TStageInstruction {
string getResultId() { string getResultId() {
this.shouldGenerateDumpStrings() and this.shouldGenerateDumpStrings() and
result = result =
this.getResultPrefix() + this.getAST().getLocation().getStartLine() + "_" + this.getLineRank() this.getResultPrefix() + this.getAst().getLocation().getStartLine() + "_" + this.getLineRank()
} }
/** /**
@@ -208,12 +208,15 @@ class Instruction extends Construction::TStageInstruction {
/** /**
* Gets the AST that caused this instruction to be generated. * Gets the AST that caused this instruction to be generated.
*/ */
final Language::AST getAST() { result = Construction::getInstructionAST(this) } final Language::AST getAst() { result = Construction::getInstructionAst(this) }
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
/** /**
* Gets the location of the source code for this instruction. * Gets the location of the source code for this instruction.
*/ */
final Language::Location getLocation() { result = this.getAST().getLocation() } final Language::Location getLocation() { result = this.getAst().getLocation() }
/** /**
* Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a * Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a
@@ -459,7 +462,10 @@ class VariableInstruction extends Instruction {
/** /**
* Gets the AST variable that this instruction's IR variable refers to, if one exists. * Gets the AST variable that this instruction's IR variable refers to, if one exists.
*/ */
final Language::Variable getASTVariable() { result = var.(IRUserVariable).getVariable() } final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
/** DEPRECATED: Alias for getAstVariable */
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
} }
/** /**

View File

@@ -18,7 +18,7 @@ private import internal.OperandInternal
* of `TOperand` that are used in this stage. * of `TOperand` that are used in this stage.
*/ */
private class TStageOperand = private class TStageOperand =
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand; TRegisterOperand or TNonSsaMemoryOperand or TPhiOperand or TChiOperand;
/** /**
* A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as * A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as
@@ -38,7 +38,7 @@ class Operand extends TStageOperand {
// Ensure that the operand does not refer to instructions from earlier stages that are unreachable here // Ensure that the operand does not refer to instructions from earlier stages that are unreachable here
exists(Instruction use, Instruction def | this = registerOperand(use, _, def)) exists(Instruction use, Instruction def | this = registerOperand(use, _, def))
or or
exists(Instruction use | this = nonSSAMemoryOperand(use, _)) exists(Instruction use | this = nonSsaMemoryOperand(use, _))
or or
exists(Instruction use, Instruction def, IRBlock predecessorBlock | exists(Instruction use, Instruction def, IRBlock predecessorBlock |
this = phiOperand(use, def, predecessorBlock, _) or this = phiOperand(use, def, predecessorBlock, _) or
@@ -209,7 +209,7 @@ class Operand extends TStageOperand {
class MemoryOperand extends Operand { class MemoryOperand extends Operand {
cached cached
MemoryOperand() { MemoryOperand() {
this instanceof TNonSSAMemoryOperand or this instanceof TNonSsaMemoryOperand or
this instanceof TPhiOperand or this instanceof TPhiOperand or
this instanceof TChiOperand this instanceof TChiOperand
} }
@@ -249,7 +249,7 @@ class NonPhiOperand extends Operand {
NonPhiOperand() { NonPhiOperand() {
this = registerOperand(useInstr, tag, _) or this = registerOperand(useInstr, tag, _) or
this = nonSSAMemoryOperand(useInstr, tag) or this = nonSsaMemoryOperand(useInstr, tag) or
this = chiOperand(useInstr, tag) this = chiOperand(useInstr, tag)
} }
@@ -299,7 +299,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
cached cached
NonPhiMemoryOperand() { NonPhiMemoryOperand() {
this = nonSSAMemoryOperand(useInstr, tag) this = nonSsaMemoryOperand(useInstr, tag)
or or
this = chiOperand(useInstr, tag) this = chiOperand(useInstr, tag)
} }

View File

@@ -99,7 +99,7 @@ private predicate filteredNumberableInstruction(Instruction instr) {
// count rather than strictcount to handle missing AST elements // count rather than strictcount to handle missing AST elements
// separate instanceof and inline casts to avoid failed casts with a count of 0 // separate instanceof and inline casts to avoid failed casts with a count of 0
instr instanceof VariableAddressInstruction and instr instanceof VariableAddressInstruction and
count(instr.(VariableAddressInstruction).getIRVariable().getAST()) != 1 count(instr.(VariableAddressInstruction).getIRVariable().getAst()) != 1
or or
instr instanceof ConstantInstruction and instr instanceof ConstantInstruction and
count(instr.getResultIRType()) != 1 count(instr.getResultIRType()) != 1
@@ -121,7 +121,7 @@ private predicate variableAddressValueNumber(
// The underlying AST element is used as value-numbering key instead of the // The underlying AST element is used as value-numbering key instead of the
// `IRVariable` to work around a problem where a variable or expression with // `IRVariable` to work around a problem where a variable or expression with
// multiple types gives rise to multiple `IRVariable`s. // multiple types gives rise to multiple `IRVariable`s.
unique( | | instr.getIRVariable().getAST()) = ast unique( | | instr.getIRVariable().getAst()) = ast
} }
private predicate initializeParameterValueNumber( private predicate initializeParameterValueNumber(
@@ -131,7 +131,7 @@ private predicate initializeParameterValueNumber(
// The underlying AST element is used as value-numbering key instead of the // The underlying AST element is used as value-numbering key instead of the
// `IRVariable` to work around a problem where a variable or expression with // `IRVariable` to work around a problem where a variable or expression with
// multiple types gives rise to multiple `IRVariable`s. // multiple types gives rise to multiple `IRVariable`s.
instr.getIRVariable().getAST() = var instr.getIRVariable().getAst() = var
} }
private predicate constantValueNumber( private predicate constantValueNumber(

View File

@@ -48,7 +48,7 @@ module Raw {
cached cached
predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, CppType type) { predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, CppType type) {
exists(TranslatedElement element | exists(TranslatedElement element |
element.getAST() = ast and element.getAst() = ast and
func = element.getFunction() and func = element.getFunction() and
element.hasTempVariable(tag, type) element.hasTempVariable(tag, type)
) )
@@ -75,7 +75,7 @@ module Raw {
tag = getInstructionTag(instruction) and tag = getInstructionTag(instruction) and
( (
result = element.getInstructionVariable(tag) or result = element.getInstructionVariable(tag) or
result.(IRStringLiteral).getAST() = element.getInstructionStringLiteral(tag) result.(IRStringLiteral).getAst() = element.getInstructionStringLiteral(tag)
) )
) )
} }
@@ -339,7 +339,7 @@ Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind ki
// such a `goto` creates a back edge. // such a `goto` creates a back edge.
exists(TranslatedElement s, GotoStmt goto | exists(TranslatedElement s, GotoStmt goto |
not isStrictlyForwardGoto(goto) and not isStrictlyForwardGoto(goto) and
goto = s.getAST() and goto = s.getAst() and
exists(InstructionTag tag | exists(InstructionTag tag |
result = s.getInstructionSuccessor(tag, kind) and result = s.getInstructionSuccessor(tag, kind) and
instruction = s.getInstruction(tag) instruction = s.getInstruction(tag)
@@ -352,8 +352,13 @@ private predicate isStrictlyForwardGoto(GotoStmt goto) {
goto.getLocation().isBefore(goto.getTarget().getLocation()) goto.getLocation().isBefore(goto.getTarget().getLocation())
} }
Locatable getInstructionAST(TStageInstruction instr) { Locatable getInstructionAst(TStageInstruction instr) {
result = getInstructionTranslatedElement(instr).getAST() result = getInstructionTranslatedElement(instr).getAst()
}
/** DEPRECATED: Alias for getInstructionAst */
deprecated Locatable getInstructionAST(TStageInstruction instr) {
result = getInstructionAst(instr)
} }
CppType getInstructionResultType(TStageInstruction instr) { CppType getInstructionResultType(TStageInstruction instr) {

View File

@@ -175,7 +175,10 @@ abstract class TranslatedSideEffects extends TranslatedElement {
/** Gets the expression whose side effects are being modeled. */ /** Gets the expression whose side effects are being modeled. */
abstract Expr getExpr(); abstract Expr getExpr();
final override Locatable getAST() { result = getExpr() } final override Locatable getAst() { result = getExpr() }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Function getFunction() { result = getExpr().getEnclosingFunction() } final override Function getFunction() { result = getExpr().getEnclosingFunction() }
@@ -522,7 +525,10 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
this = TTranslatedArgumentExprSideEffect(call, arg, index, sideEffectOpcode) this = TTranslatedArgumentExprSideEffect(call, arg, index, sideEffectOpcode)
} }
final override Locatable getAST() { result = arg } final override Locatable getAst() { result = arg }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Type getIndirectionType() { final override Type getIndirectionType() {
result = arg.getUnspecifiedType().(DerivedType).getBaseType() result = arg.getUnspecifiedType().(DerivedType).getBaseType()
@@ -553,7 +559,10 @@ class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect
index = -1 index = -1
} }
final override Locatable getAST() { result = call } final override Locatable getAst() { result = call }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Type getIndirectionType() { result = call.getTarget().getDeclaringType() } final override Type getIndirectionType() { result = call.getTarget().getDeclaringType() }
@@ -574,7 +583,10 @@ class TranslatedCallSideEffect extends TranslatedSideEffect, TTranslatedCallSide
TranslatedCallSideEffect() { this = TTranslatedCallSideEffect(expr, sideEffectOpcode) } TranslatedCallSideEffect() { this = TTranslatedCallSideEffect(expr, sideEffectOpcode) }
override Locatable getAST() { result = expr } override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Expr getPrimaryExpr() { result = expr } override Expr getPrimaryExpr() { result = expr }
@@ -612,7 +624,10 @@ class TranslatedAllocationSideEffect extends TranslatedSideEffect, TTranslatedAl
TranslatedAllocationSideEffect() { this = TTranslatedAllocationSideEffect(expr) } TranslatedAllocationSideEffect() { this = TTranslatedAllocationSideEffect(expr) }
override Locatable getAST() { result = expr } override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Expr getPrimaryExpr() { result = expr } override Expr getPrimaryExpr() { result = expr }

View File

@@ -19,7 +19,10 @@ abstract class TranslatedCondition extends TranslatedElement {
final override string toString() { result = expr.toString() } final override string toString() { result = expr.toString() }
final override Locatable getAST() { result = expr } final override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final ConditionContext getConditionContext() { result = getParent() } final ConditionContext getConditionContext() { result = getParent() }

View File

@@ -14,7 +14,7 @@ private import TranslatedInitialization
* `entry`. * `entry`.
*/ */
TranslatedDeclarationEntry getTranslatedDeclarationEntry(DeclarationEntry entry) { TranslatedDeclarationEntry getTranslatedDeclarationEntry(DeclarationEntry entry) {
result.getAST() = entry result.getAst() = entry
} }
/** /**
@@ -37,7 +37,10 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated
final override string toString() { result = entry.toString() } final override string toString() { result = entry.toString() }
final override Locatable getAST() { result = entry } final override Locatable getAst() { result = entry }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
} }
/** /**
@@ -223,7 +226,10 @@ class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
final override string toString() { result = "init: " + entry.toString() } final override string toString() { result = "init: " + entry.toString() }
final override Locatable getAST() { result = entry } final override Locatable getAst() { result = entry }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override LocalVariable getVariable() { result = var } final override LocalVariable getVariable() { result = var }
@@ -254,7 +260,10 @@ class TranslatedRangeBasedForVariableDeclaration extends TranslatedLocalVariable
override string toString() { result = var.toString() } override string toString() { result = var.toString() }
override Locatable getAST() { result = var } override Locatable getAst() { result = var }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Function getFunction() { result = forStmt.getEnclosingFunction() } override Function getFunction() { result = forStmt.getEnclosingFunction() }
@@ -262,7 +271,7 @@ class TranslatedRangeBasedForVariableDeclaration extends TranslatedLocalVariable
} }
TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) { TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) {
result.getAST() = expr result.getAst() = expr
} }
/** /**
@@ -280,7 +289,10 @@ class TranslatedConditionDecl extends TranslatedLocalVariableDeclaration, TTrans
override string toString() { result = "decl: " + conditionDeclExpr.toString() } override string toString() { result = "decl: " + conditionDeclExpr.toString() }
override Locatable getAST() { result = conditionDeclExpr } override Locatable getAst() { result = conditionDeclExpr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Function getFunction() { result = conditionDeclExpr.getEnclosingFunction() } override Function getFunction() { result = conditionDeclExpr.getEnclosingFunction() }

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