Compare commits

..

1 Commits

Author SHA1 Message Date
Chris Smowton
0a7d27a976 Update 2022-03-07-get-stringified-value.md 2022-03-11 10:36:57 +00:00
987 changed files with 8368 additions and 40268 deletions

View File

@@ -1,50 +0,0 @@
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

@@ -27,8 +27,7 @@
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll"
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForLibraries.qll"
], ],
"DataFlow Java/C++/C#/Python Common": [ "DataFlow Java/C++/C#/Python Common": [
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll",
@@ -55,8 +54,7 @@
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll", "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll", "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll", "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTrackingImpl.qll"
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforlibraries/TaintTrackingImpl.qll"
], ],
"DataFlow Java/C++/C#/Python Consistency checks": [ "DataFlow Java/C++/C#/Python Consistency checks": [
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll",
@@ -75,14 +73,6 @@
"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"
@@ -517,13 +507,5 @@
"java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll", "java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll",
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll", "javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll" "ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.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"
] ]
} }

View File

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

View File

@@ -1,30 +1,3 @@
## 0.0.12
### Breaking Changes
* 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.
### Deprecated APIs
* 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.
### New Features
* 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.
### Minor Analysis Improvements
* `DefaultOptions::exits` now holds for C11 functions with the `_Noreturn` or `noreturn` specifier.
* `hasImplicitCopyConstructor` and `hasImplicitCopyAssignmentOperator` now correctly handle implicitly-deleted operators in templates.
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
## 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
@@ -33,7 +6,6 @@
## 0.0.9 ## 0.0.9
## 0.0.8 ## 0.0.8
### Deprecated APIs ### Deprecated APIs

View File

@@ -54,13 +54,11 @@ 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 or specifier. * `noreturn` attribute.
*/ */
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 or specifier. * `noreturn` attribute.
*/ */
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

@@ -1,5 +1,4 @@
## 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,20 +0,0 @@
## 0.0.12
### Breaking Changes
* 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.
### Deprecated APIs
* 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.
### New Features
* 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.
### Minor Analysis Improvements
* `DefaultOptions::exits` now holds for C11 functions with the `_Noreturn` or `noreturn` specifier.
* `hasImplicitCopyConstructor` and `hasImplicitCopyAssignmentOperator` now correctly handle implicitly-deleted operators in templates.
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.

View File

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

View File

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

View File

@@ -251,16 +251,6 @@ 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()
) )
} }
@@ -276,18 +266,6 @@ 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()
) )
} }

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,11 +27,8 @@ 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]
@@ -88,8 +85,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.
@@ -109,7 +106,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.
*/ */
@@ -119,17 +116,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.
@@ -141,11 +138,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
) )
} }
@@ -169,12 +166,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.
@@ -199,7 +196,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
@@ -237,15 +234,12 @@ 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
@@ -268,7 +262,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() }
@@ -278,34 +272,25 @@ 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)
@@ -321,7 +306,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())
} }
/** /**
@@ -349,9 +334,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
} }
} }
@@ -378,27 +363,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()
@@ -411,9 +396,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) {
@@ -425,23 +410,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())
} }
} }
@@ -464,12 +449,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() }
@@ -484,14 +469,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) {
@@ -503,7 +488,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) }
@@ -512,8 +497,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) {
@@ -530,7 +515,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) }
@@ -539,8 +524,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) {
@@ -557,7 +542,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) }
@@ -566,8 +551,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) {
@@ -584,14 +569,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
@@ -599,7 +584,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
@@ -618,7 +603,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)
@@ -871,7 +856,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)
} }
@@ -880,7 +865,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

@@ -4,11 +4,11 @@
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) }

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()
} }
@@ -121,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

@@ -10,13 +10,10 @@ 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
@@ -30,22 +27,22 @@ deprecated class StandardSSA = StandardSsa;
* 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
@@ -65,7 +62,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() }
@@ -127,7 +124,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))
} }
/** /**

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,6 +311,3 @@ library class SsaHelper extends int {
ssa_use(v, result, _, _) ssa_use(v, result, _, _)
} }
} }
/** DEPRECATED: Alias for SsaHelper */
deprecated class SSAHelper = SsaHelper;

View File

@@ -447,6 +447,26 @@ 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.
@@ -1359,7 +1379,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)
@@ -1368,32 +1388,23 @@ 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,4 +20,5 @@ 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
} }

View File

@@ -87,30 +87,12 @@ 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.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate fullInBarrier(NodeEx node, Configuration config) { private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) { private predicate outBarrier(NodeEx node, 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)
@@ -350,15 +323,6 @@ private predicate fullOutBarrier(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 |
@@ -381,19 +345,9 @@ 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 | node.asNode() = n | exists(Node 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()
)
) )
} }
@@ -422,8 +376,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 fullOutBarrier(node1, config) and not outBarrier(node1, config) and
not fullInBarrier(node2, config) and not inBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -476,8 +430,6 @@ 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)
) )
@@ -519,8 +471,6 @@ 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
@@ -920,8 +870,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 fullInBarrier(node, config) and not inBarrier(node, config) and
not fullOutBarrier(node, config) not outBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -1016,8 +966,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 fullOutBarrier(ret, config) and not outBarrier(ret, config) and
not fullInBarrier(out, config) not inBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -1038,8 +988,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 fullOutBarrier(arg, config) and not outBarrier(arg, config) and
not fullInBarrier(p, config) not inBarrier(p, config)
} }
/** /**
@@ -1756,31 +1706,18 @@ 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.
*/ */
private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) sourceNode(node, state, config) or
or jumpStep(_, node, config) or
jumpStep(_, node, config) additionalJumpStep(_, node, config) or
or additionalJumpStateStep(_, _, node, state, config) or
additionalJumpStep(_, node, config) node instanceof ParamNodeEx or
or node.asNode() instanceof OutNodeExt or
additionalJumpStateStep(_, _, node, state, config) store(_, _, node, _, config) or
or read(_, _, node, config) 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
)
) )
} }
@@ -1800,9 +1737,6 @@ 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
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
Configuration config, LocalCallContext cc DataFlowType t, 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](state), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state1), 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() and // irrelevant dummy value t = node1.getDataFlowType() // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, 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()) not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), 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](state), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid | exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType() and
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1883,19 +1819,9 @@ 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, preservesValue, apf.getType(), config, callContext) and localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
localFlowExit(node2, state1, config) and callContext) and
state1 = state2 localFlowExit(node2, state2, config)
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)
)
} }
} }
@@ -2769,10 +2695,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()) and node.getEnclosingCallable())
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,30 +87,12 @@ 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.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate fullInBarrier(NodeEx node, Configuration config) { private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) { private predicate outBarrier(NodeEx node, 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)
@@ -350,15 +323,6 @@ private predicate fullOutBarrier(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 |
@@ -381,19 +345,9 @@ 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 | node.asNode() = n | exists(Node 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()
)
) )
} }
@@ -422,8 +376,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 fullOutBarrier(node1, config) and not outBarrier(node1, config) and
not fullInBarrier(node2, config) and not inBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -476,8 +430,6 @@ 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)
) )
@@ -519,8 +471,6 @@ 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
@@ -920,8 +870,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 fullInBarrier(node, config) and not inBarrier(node, config) and
not fullOutBarrier(node, config) not outBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -1016,8 +966,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 fullOutBarrier(ret, config) and not outBarrier(ret, config) and
not fullInBarrier(out, config) not inBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -1038,8 +988,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 fullOutBarrier(arg, config) and not outBarrier(arg, config) and
not fullInBarrier(p, config) not inBarrier(p, config)
} }
/** /**
@@ -1756,31 +1706,18 @@ 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.
*/ */
private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) sourceNode(node, state, config) or
or jumpStep(_, node, config) or
jumpStep(_, node, config) additionalJumpStep(_, node, config) or
or additionalJumpStateStep(_, _, node, state, config) or
additionalJumpStep(_, node, config) node instanceof ParamNodeEx or
or node.asNode() instanceof OutNodeExt or
additionalJumpStateStep(_, _, node, state, config) store(_, _, node, _, config) or
or read(_, _, node, config) 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
)
) )
} }
@@ -1800,9 +1737,6 @@ 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
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
Configuration config, LocalCallContext cc DataFlowType t, 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](state), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state1), 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() and // irrelevant dummy value t = node1.getDataFlowType() // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, 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()) not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), 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](state), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid | exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType() and
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1883,19 +1819,9 @@ 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, preservesValue, apf.getType(), config, callContext) and localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
localFlowExit(node2, state1, config) and callContext) and
state1 = state2 localFlowExit(node2, state2, config)
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)
)
} }
} }
@@ -2769,10 +2695,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()) and node.getEnclosingCallable())
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,30 +87,12 @@ 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.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate fullInBarrier(NodeEx node, Configuration config) { private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) { private predicate outBarrier(NodeEx node, 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)
@@ -350,15 +323,6 @@ private predicate fullOutBarrier(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 |
@@ -381,19 +345,9 @@ 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 | node.asNode() = n | exists(Node 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()
)
) )
} }
@@ -422,8 +376,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 fullOutBarrier(node1, config) and not outBarrier(node1, config) and
not fullInBarrier(node2, config) and not inBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -476,8 +430,6 @@ 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)
) )
@@ -519,8 +471,6 @@ 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
@@ -920,8 +870,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 fullInBarrier(node, config) and not inBarrier(node, config) and
not fullOutBarrier(node, config) not outBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -1016,8 +966,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 fullOutBarrier(ret, config) and not outBarrier(ret, config) and
not fullInBarrier(out, config) not inBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -1038,8 +988,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 fullOutBarrier(arg, config) and not outBarrier(arg, config) and
not fullInBarrier(p, config) not inBarrier(p, config)
} }
/** /**
@@ -1756,31 +1706,18 @@ 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.
*/ */
private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) sourceNode(node, state, config) or
or jumpStep(_, node, config) or
jumpStep(_, node, config) additionalJumpStep(_, node, config) or
or additionalJumpStateStep(_, _, node, state, config) or
additionalJumpStep(_, node, config) node instanceof ParamNodeEx or
or node.asNode() instanceof OutNodeExt or
additionalJumpStateStep(_, _, node, state, config) store(_, _, node, _, config) or
or read(_, _, node, config) 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
)
) )
} }
@@ -1800,9 +1737,6 @@ 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
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
Configuration config, LocalCallContext cc DataFlowType t, 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](state), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state1), 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() and // irrelevant dummy value t = node1.getDataFlowType() // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, 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()) not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), 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](state), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid | exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType() and
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1883,19 +1819,9 @@ 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, preservesValue, apf.getType(), config, callContext) and localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
localFlowExit(node2, state1, config) and callContext) and
state1 = state2 localFlowExit(node2, state2, config)
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)
)
} }
} }
@@ -2769,10 +2695,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()) and node.getEnclosingCallable())
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,30 +87,12 @@ 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.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate fullInBarrier(NodeEx node, Configuration config) { private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) { private predicate outBarrier(NodeEx node, 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)
@@ -350,15 +323,6 @@ private predicate fullOutBarrier(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 |
@@ -381,19 +345,9 @@ 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 | node.asNode() = n | exists(Node 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()
)
) )
} }
@@ -422,8 +376,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 fullOutBarrier(node1, config) and not outBarrier(node1, config) and
not fullInBarrier(node2, config) and not inBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -476,8 +430,6 @@ 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)
) )
@@ -519,8 +471,6 @@ 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
@@ -920,8 +870,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 fullInBarrier(node, config) and not inBarrier(node, config) and
not fullOutBarrier(node, config) not outBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -1016,8 +966,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 fullOutBarrier(ret, config) and not outBarrier(ret, config) and
not fullInBarrier(out, config) not inBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -1038,8 +988,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 fullOutBarrier(arg, config) and not outBarrier(arg, config) and
not fullInBarrier(p, config) not inBarrier(p, config)
} }
/** /**
@@ -1756,31 +1706,18 @@ 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.
*/ */
private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) sourceNode(node, state, config) or
or jumpStep(_, node, config) or
jumpStep(_, node, config) additionalJumpStep(_, node, config) or
or additionalJumpStateStep(_, _, node, state, config) or
additionalJumpStep(_, node, config) node instanceof ParamNodeEx or
or node.asNode() instanceof OutNodeExt or
additionalJumpStateStep(_, _, node, state, config) store(_, _, node, _, config) or
or read(_, _, node, config) 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
)
) )
} }
@@ -1800,9 +1737,6 @@ 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
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
Configuration config, LocalCallContext cc DataFlowType t, 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](state), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state1), 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() and // irrelevant dummy value t = node1.getDataFlowType() // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, 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()) not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), 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](state), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid | exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType() and
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1883,19 +1819,9 @@ 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, preservesValue, apf.getType(), config, callContext) and localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
localFlowExit(node2, state1, config) and callContext) and
state1 = state2 localFlowExit(node2, state2, config)
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)
)
} }
} }
@@ -2769,10 +2695,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()) and node.getEnclosingCallable())
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,30 +87,12 @@ 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.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate fullInBarrier(NodeEx node, Configuration config) { private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) { private predicate outBarrier(NodeEx node, 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)
@@ -350,15 +323,6 @@ private predicate fullOutBarrier(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 |
@@ -381,19 +345,9 @@ 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 | node.asNode() = n | exists(Node 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()
)
) )
} }
@@ -422,8 +376,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 fullOutBarrier(node1, config) and not outBarrier(node1, config) and
not fullInBarrier(node2, config) and not inBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -476,8 +430,6 @@ 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)
) )
@@ -519,8 +471,6 @@ 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
@@ -920,8 +870,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 fullInBarrier(node, config) and not inBarrier(node, config) and
not fullOutBarrier(node, config) not outBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -1016,8 +966,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 fullOutBarrier(ret, config) and not outBarrier(ret, config) and
not fullInBarrier(out, config) not inBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -1038,8 +988,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 fullOutBarrier(arg, config) and not outBarrier(arg, config) and
not fullInBarrier(p, config) not inBarrier(p, config)
} }
/** /**
@@ -1756,31 +1706,18 @@ 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.
*/ */
private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) sourceNode(node, state, config) or
or jumpStep(_, node, config) or
jumpStep(_, node, config) additionalJumpStep(_, node, config) or
or additionalJumpStateStep(_, _, node, state, config) or
additionalJumpStep(_, node, config) node instanceof ParamNodeEx or
or node.asNode() instanceof OutNodeExt or
additionalJumpStateStep(_, _, node, state, config) store(_, _, node, _, config) or
or read(_, _, node, config) 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
)
) )
} }
@@ -1800,9 +1737,6 @@ 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
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
Configuration config, LocalCallContext cc DataFlowType t, 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](state), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state1), 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() and // irrelevant dummy value t = node1.getDataFlowType() // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, 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()) not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), 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](state), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid | exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType() and
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1883,19 +1819,9 @@ 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, preservesValue, apf.getType(), config, callContext) and localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
localFlowExit(node2, state1, config) and callContext) and
state1 = state2 localFlowExit(node2, state2, config)
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)
)
} }
} }
@@ -2769,10 +2695,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()) and node.getEnclosingCallable())
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -64,30 +64,13 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() } override predicate isSource(DataFlow::Node source) { none() }
/** /**
* Holds if `source` is a relevant taint source with the given initial * Holds if `sink` is a relevant taint sink.
* `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() }
@@ -96,29 +79,9 @@ 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. */
@@ -126,16 +89,6 @@ 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() }
@@ -143,16 +96,6 @@ 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.
@@ -164,25 +107,6 @@ 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,30 +64,13 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() } override predicate isSource(DataFlow::Node source) { none() }
/** /**
* Holds if `source` is a relevant taint source with the given initial * Holds if `sink` is a relevant taint sink.
* `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() }
@@ -96,29 +79,9 @@ 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. */
@@ -126,16 +89,6 @@ 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() }
@@ -143,16 +96,6 @@ 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.
@@ -164,25 +107,6 @@ 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

@@ -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

@@ -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,4 +20,5 @@ 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
} }

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,30 +87,12 @@ 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.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate fullInBarrier(NodeEx node, Configuration config) { private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) { private predicate outBarrier(NodeEx node, 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)
@@ -350,15 +323,6 @@ private predicate fullOutBarrier(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 |
@@ -381,19 +345,9 @@ 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 | node.asNode() = n | exists(Node 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()
)
) )
} }
@@ -422,8 +376,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 fullOutBarrier(node1, config) and not outBarrier(node1, config) and
not fullInBarrier(node2, config) and not inBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -476,8 +430,6 @@ 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)
) )
@@ -519,8 +471,6 @@ 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
@@ -920,8 +870,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 fullInBarrier(node, config) and not inBarrier(node, config) and
not fullOutBarrier(node, config) not outBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -1016,8 +966,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 fullOutBarrier(ret, config) and not outBarrier(ret, config) and
not fullInBarrier(out, config) not inBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -1038,8 +988,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 fullOutBarrier(arg, config) and not outBarrier(arg, config) and
not fullInBarrier(p, config) not inBarrier(p, config)
} }
/** /**
@@ -1756,31 +1706,18 @@ 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.
*/ */
private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) sourceNode(node, state, config) or
or jumpStep(_, node, config) or
jumpStep(_, node, config) additionalJumpStep(_, node, config) or
or additionalJumpStateStep(_, _, node, state, config) or
additionalJumpStep(_, node, config) node instanceof ParamNodeEx or
or node.asNode() instanceof OutNodeExt or
additionalJumpStateStep(_, _, node, state, config) store(_, _, node, _, config) or
or read(_, _, node, config) 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
)
) )
} }
@@ -1800,9 +1737,6 @@ 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
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
Configuration config, LocalCallContext cc DataFlowType t, 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](state), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state1), 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() and // irrelevant dummy value t = node1.getDataFlowType() // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, 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()) not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), 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](state), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid | exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType() and
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1883,19 +1819,9 @@ 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, preservesValue, apf.getType(), config, callContext) and localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
localFlowExit(node2, state1, config) and callContext) and
state1 = state2 localFlowExit(node2, state2, config)
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)
)
} }
} }
@@ -2769,10 +2695,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()) and node.getEnclosingCallable())
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,30 +87,12 @@ 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.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate fullInBarrier(NodeEx node, Configuration config) { private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) { private predicate outBarrier(NodeEx node, 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)
@@ -350,15 +323,6 @@ private predicate fullOutBarrier(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 |
@@ -381,19 +345,9 @@ 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 | node.asNode() = n | exists(Node 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()
)
) )
} }
@@ -422,8 +376,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 fullOutBarrier(node1, config) and not outBarrier(node1, config) and
not fullInBarrier(node2, config) and not inBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -476,8 +430,6 @@ 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)
) )
@@ -519,8 +471,6 @@ 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
@@ -920,8 +870,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 fullInBarrier(node, config) and not inBarrier(node, config) and
not fullOutBarrier(node, config) not outBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -1016,8 +966,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 fullOutBarrier(ret, config) and not outBarrier(ret, config) and
not fullInBarrier(out, config) not inBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -1038,8 +988,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 fullOutBarrier(arg, config) and not outBarrier(arg, config) and
not fullInBarrier(p, config) not inBarrier(p, config)
} }
/** /**
@@ -1756,31 +1706,18 @@ 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.
*/ */
private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) sourceNode(node, state, config) or
or jumpStep(_, node, config) or
jumpStep(_, node, config) additionalJumpStep(_, node, config) or
or additionalJumpStateStep(_, _, node, state, config) or
additionalJumpStep(_, node, config) node instanceof ParamNodeEx or
or node.asNode() instanceof OutNodeExt or
additionalJumpStateStep(_, _, node, state, config) store(_, _, node, _, config) or
or read(_, _, node, config) 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
)
) )
} }
@@ -1800,9 +1737,6 @@ 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
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
Configuration config, LocalCallContext cc DataFlowType t, 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](state), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state1), 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() and // irrelevant dummy value t = node1.getDataFlowType() // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, 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()) not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), 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](state), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid | exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType() and
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1883,19 +1819,9 @@ 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, preservesValue, apf.getType(), config, callContext) and localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
localFlowExit(node2, state1, config) and callContext) and
state1 = state2 localFlowExit(node2, state2, config)
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)
)
} }
} }
@@ -2769,10 +2695,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()) and node.getEnclosingCallable())
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,30 +87,12 @@ 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.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate fullInBarrier(NodeEx node, Configuration config) { private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) { private predicate outBarrier(NodeEx node, 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)
@@ -350,15 +323,6 @@ private predicate fullOutBarrier(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 |
@@ -381,19 +345,9 @@ 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 | node.asNode() = n | exists(Node 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()
)
) )
} }
@@ -422,8 +376,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 fullOutBarrier(node1, config) and not outBarrier(node1, config) and
not fullInBarrier(node2, config) and not inBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -476,8 +430,6 @@ 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)
) )
@@ -519,8 +471,6 @@ 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
@@ -920,8 +870,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 fullInBarrier(node, config) and not inBarrier(node, config) and
not fullOutBarrier(node, config) not outBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -1016,8 +966,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 fullOutBarrier(ret, config) and not outBarrier(ret, config) and
not fullInBarrier(out, config) not inBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -1038,8 +988,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 fullOutBarrier(arg, config) and not outBarrier(arg, config) and
not fullInBarrier(p, config) not inBarrier(p, config)
} }
/** /**
@@ -1756,31 +1706,18 @@ 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.
*/ */
private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) sourceNode(node, state, config) or
or jumpStep(_, node, config) or
jumpStep(_, node, config) additionalJumpStep(_, node, config) or
or additionalJumpStateStep(_, _, node, state, config) or
additionalJumpStep(_, node, config) node instanceof ParamNodeEx or
or node.asNode() instanceof OutNodeExt or
additionalJumpStateStep(_, _, node, state, config) store(_, _, node, _, config) or
or read(_, _, node, config) 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
)
) )
} }
@@ -1800,9 +1737,6 @@ 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
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
Configuration config, LocalCallContext cc DataFlowType t, 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](state), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state1), 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() and // irrelevant dummy value t = node1.getDataFlowType() // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, 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()) not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), 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](state), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid | exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType() and
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1883,19 +1819,9 @@ 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, preservesValue, apf.getType(), config, callContext) and localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
localFlowExit(node2, state1, config) and callContext) and
state1 = state2 localFlowExit(node2, state2, config)
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)
)
} }
} }
@@ -2769,10 +2695,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()) and node.getEnclosingCallable())
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -87,30 +87,12 @@ 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.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
} }
private predicate fullInBarrier(NodeEx node, Configuration config) { private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n | exists(Node n |
node.asNode() = n and node.asNode() = n and
config.isBarrierIn(n) config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
) )
} }
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) { private predicate outBarrier(NodeEx node, 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)
@@ -350,15 +323,6 @@ private predicate fullOutBarrier(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 |
@@ -381,19 +345,9 @@ 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 | node.asNode() = n | exists(Node 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()
)
) )
} }
@@ -422,8 +376,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 fullOutBarrier(node1, config) and not outBarrier(node1, config) and
not fullInBarrier(node2, config) and not inBarrier(node2, config) and
not fullBarrier(node1, config) and not fullBarrier(node1, config) and
not fullBarrier(node2, config) not fullBarrier(node2, config)
} }
@@ -476,8 +430,6 @@ 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)
) )
@@ -519,8 +471,6 @@ 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
@@ -920,8 +870,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 fullInBarrier(node, config) and not inBarrier(node, config) and
not fullOutBarrier(node, config) not outBarrier(node, config)
} }
/** Holds if flow may return from `callable`. */ /** Holds if flow may return from `callable`. */
@@ -1016,8 +966,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 fullOutBarrier(ret, config) and not outBarrier(ret, config) and
not fullInBarrier(out, config) not inBarrier(out, config)
} }
pragma[nomagic] pragma[nomagic]
@@ -1038,8 +988,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 fullOutBarrier(arg, config) and not outBarrier(arg, config) and
not fullInBarrier(p, config) not inBarrier(p, config)
} }
/** /**
@@ -1756,31 +1706,18 @@ 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.
*/ */
private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
Stage2::revFlow(node, state, config) and Stage2::revFlow(node, state, config) and
( (
sourceNode(node, state, config) sourceNode(node, state, config) or
or jumpStep(_, node, config) or
jumpStep(_, node, config) additionalJumpStep(_, node, config) or
or additionalJumpStateStep(_, _, node, state, config) or
additionalJumpStep(_, node, config) node instanceof ParamNodeEx or
or node.asNode() instanceof OutNodeExt or
additionalJumpStateStep(_, _, node, state, config) store(_, _, node, _, config) or
or read(_, _, node, config) 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
)
) )
} }
@@ -1800,9 +1737,6 @@ 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
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/ */
pragma[nomagic] pragma[nomagic]
private predicate localFlowStepPlus( private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
Configuration config, LocalCallContext cc DataFlowType t, 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](state), pragma[only_bind_into](config)) and localFlowEntry(node1, pragma[only_bind_into](state1), 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() and // irrelevant dummy value t = node1.getDataFlowType() // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
or or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, 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()) not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or or
exists(NodeEx mid | exists(NodeEx mid |
localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), 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](state), pragma[only_bind_into](config)) Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
) )
or or
exists(NodeEx mid | exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode and not mid instanceof FlowCheckNode and
preservesValue = false and preservesValue = false and
t = node2.getDataFlowType() t = node2.getDataFlowType() and
Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
) )
) )
} }
@@ -1883,19 +1819,9 @@ 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, preservesValue, apf.getType(), config, callContext) and localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
localFlowExit(node2, state1, config) and callContext) and
state1 = state2 localFlowExit(node2, state2, config)
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)
)
} }
} }
@@ -2769,10 +2695,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()) and node.getEnclosingCallable())
exists(config)
} }
private predicate localStep( private predicate localStep(

View File

@@ -431,7 +431,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
SsaPhiNode() { this = TSsaPhiNode(phi) } SsaPhiNode() { this = TSsaPhiNode(phi) }
/** Gets the phi node associated with this node. */ /* Get 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() }

View File

@@ -287,6 +287,20 @@ 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,30 +64,13 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() } override predicate isSource(DataFlow::Node source) { none() }
/** /**
* Holds if `source` is a relevant taint source with the given initial * Holds if `sink` is a relevant taint sink.
* `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() }
@@ -96,29 +79,9 @@ 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. */
@@ -126,16 +89,6 @@ 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() }
@@ -143,16 +96,6 @@ 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.
@@ -164,25 +107,6 @@ 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,30 +64,13 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() } override predicate isSource(DataFlow::Node source) { none() }
/** /**
* Holds if `source` is a relevant taint source with the given initial * Holds if `sink` is a relevant taint sink.
* `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() }
@@ -96,29 +79,9 @@ 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. */
@@ -126,16 +89,6 @@ 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() }
@@ -143,16 +96,6 @@ 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.
@@ -164,25 +107,6 @@ 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,30 +64,13 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() } override predicate isSource(DataFlow::Node source) { none() }
/** /**
* Holds if `source` is a relevant taint source with the given initial * Holds if `sink` is a relevant taint sink.
* `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() }
@@ -96,29 +79,9 @@ 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. */
@@ -126,16 +89,6 @@ 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() }
@@ -143,16 +96,6 @@ 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.
@@ -164,25 +107,6 @@ 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,10 +55,7 @@ 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
@@ -69,7 +66,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.
@@ -93,10 +90,7 @@ 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()
@@ -163,10 +157,7 @@ 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,15 +208,12 @@ 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
@@ -462,10 +459,7 @@ 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,10 +133,7 @@ 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() }
} }
/** /**
@@ -572,16 +569,13 @@ 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
@@ -614,7 +608,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,12 +430,6 @@ 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()
@@ -981,41 +975,35 @@ 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
@@ -1050,7 +1038,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()
} }
@@ -1073,7 +1061,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.
*/ */
@@ -1126,9 +1114,6 @@ 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,64 +46,58 @@ 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,21 +72,13 @@ 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)
} }
} }
@@ -103,7 +95,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.
@@ -134,14 +126,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.
@@ -167,23 +159,20 @@ 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.
@@ -213,10 +202,7 @@ 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,10 +55,7 @@ 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
@@ -69,7 +66,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.
@@ -93,10 +90,7 @@ 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()
@@ -163,10 +157,7 @@ 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,15 +208,12 @@ 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
@@ -462,10 +459,7 @@ 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,13 +352,8 @@ 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,10 +175,7 @@ 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() }
@@ -525,10 +522,7 @@ 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()
@@ -559,10 +553,7 @@ 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() }
@@ -583,10 +574,7 @@ 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 }
@@ -624,10 +612,7 @@ 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,10 +19,7 @@ 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,10 +37,7 @@ 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() }
} }
/** /**
@@ -226,10 +223,7 @@ 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 }
@@ -260,10 +254,7 @@ 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() }
@@ -271,7 +262,7 @@ class TranslatedRangeBasedForVariableDeclaration extends TranslatedLocalVariable
} }
TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) { TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) {
result.getAst() = expr result.getAST() = expr
} }
/** /**
@@ -289,10 +280,7 @@ 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() }

View File

@@ -31,7 +31,7 @@ IRUserVariable getIRUserVariable(Function func, Variable var) {
} }
IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) { IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
result.getAst() = ast and result.getAST() = ast and
result.getTag() = tag result.getTag() = tag
} }
@@ -730,10 +730,7 @@ abstract class TranslatedElement extends TTranslatedElement {
/** /**
* Gets the AST node being translated. * Gets the AST node being translated.
*/ */
abstract Locatable getAst(); abstract Locatable getAST();
/** DEPRECATED: Alias for getAst */
deprecated Locatable getAST() { result = getAst() }
/** /**
* Get the first instruction to be executed in the evaluation of this element. * Get the first instruction to be executed in the evaluation of this element.
@@ -932,16 +929,16 @@ abstract class TranslatedElement extends TTranslatedElement {
*/ */
final IRTempVariable getTempVariable(TempVariableTag tag) { final IRTempVariable getTempVariable(TempVariableTag tag) {
exists(Locatable ast | exists(Locatable ast |
result.getAst() = ast and result.getAST() = ast and
result.getTag() = tag and result.getTag() = tag and
hasTempVariableAndAst(tag, ast) hasTempVariableAndAST(tag, ast)
) )
} }
pragma[noinline] pragma[noinline]
private predicate hasTempVariableAndAst(TempVariableTag tag, Locatable ast) { private predicate hasTempVariableAndAST(TempVariableTag tag, Locatable ast) {
hasTempVariable(tag, _) and hasTempVariable(tag, _) and
ast = getAst() ast = getAST()
} }
/** /**

View File

@@ -74,10 +74,7 @@ abstract class TranslatedExpr extends TranslatedElement {
expr.isGLValueCategory() expr.isGLValueCategory()
} }
final override Locatable getAst() { result = expr } final override Locatable getAST() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Function getFunction() { result = expr.getEnclosingFunction() } final override Function getFunction() { result = expr.getEnclosingFunction() }
@@ -1712,7 +1709,7 @@ abstract class TranslatedAllocationSize extends TranslatedExpr, TTranslatedAlloc
} }
TranslatedAllocationSize getTranslatedAllocationSize(NewOrNewArrayExpr newExpr) { TranslatedAllocationSize getTranslatedAllocationSize(NewOrNewArrayExpr newExpr) {
result.getAst() = newExpr result.getAST() = newExpr
} }
/** /**
@@ -1878,7 +1875,7 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect
} }
TranslatedAllocatorCall getTranslatedAllocatorCall(NewOrNewArrayExpr newExpr) { TranslatedAllocatorCall getTranslatedAllocatorCall(NewOrNewArrayExpr newExpr) {
result.getAst() = newExpr result.getAST() = newExpr
} }
/** /**

View File

@@ -15,7 +15,7 @@ private import VarArgs
/** /**
* Gets the `TranslatedFunction` that represents function `func`. * Gets the `TranslatedFunction` that represents function `func`.
*/ */
TranslatedFunction getTranslatedFunction(Function func) { result.getAst() = func } TranslatedFunction getTranslatedFunction(Function func) { result.getAST() = func }
/** /**
* Gets the size, in bytes, of the variable used to represent the `...` parameter in a varargs * Gets the size, in bytes, of the variable used to represent the `...` parameter in a varargs
@@ -65,10 +65,7 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
final override string toString() { result = func.toString() } final override string toString() { result = func.toString() }
final override Locatable getAst() { result = func } final override Locatable getAST() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
/** /**
* Gets the function being translated. * Gets the function being translated.
@@ -347,7 +344,7 @@ TranslatedThisParameter getTranslatedThisParameter(Function func) { result.getFu
/** /**
* Gets the `TranslatedPositionalParameter` that represents parameter `param`. * Gets the `TranslatedPositionalParameter` that represents parameter `param`.
*/ */
TranslatedPositionalParameter getTranslatedParameter(Parameter param) { result.getAst() = param } TranslatedPositionalParameter getTranslatedParameter(Parameter param) { result.getAST() = param }
/** /**
* Gets the `TranslatedEllipsisParameter` for function `func`, if one exists. * Gets the `TranslatedEllipsisParameter` for function `func`, if one exists.
@@ -460,10 +457,7 @@ class TranslatedThisParameter extends TranslatedParameter, TTranslatedThisParame
final override string toString() { result = "this" } final override string toString() { result = "this" }
final override Locatable getAst() { result = func } final override Locatable getAST() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Function getFunction() { result = func } final override Function getFunction() { result = func }
@@ -495,10 +489,7 @@ class TranslatedPositionalParameter extends TranslatedParameter, TTranslatedPara
final override string toString() { result = param.toString() } final override string toString() { result = param.toString() }
final override Locatable getAst() { result = param } final override Locatable getAST() { result = param }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Function getFunction() { final override Function getFunction() {
result = param.getFunction() or result = param.getFunction() or
@@ -535,10 +526,7 @@ class TranslatedEllipsisParameter extends TranslatedParameter, TTranslatedEllips
final override string toString() { result = "..." } final override string toString() { result = "..." }
final override Locatable getAst() { result = func } final override Locatable getAST() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Function getFunction() { result = func } final override Function getFunction() { result = func }
@@ -556,7 +544,7 @@ class TranslatedEllipsisParameter extends TranslatedParameter, TTranslatedEllips
} }
private TranslatedConstructorInitList getTranslatedConstructorInitList(Function func) { private TranslatedConstructorInitList getTranslatedConstructorInitList(Function func) {
result.getAst() = func result.getAST() = func
} }
/** /**
@@ -573,10 +561,7 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
override string toString() { result = "ctor init: " + func.toString() } override string toString() { result = "ctor init: " + func.toString() }
override Locatable getAst() { result = func } override Locatable getAST() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override TranslatedElement getChild(int id) { override TranslatedElement getChild(int id) {
exists(ConstructorFieldInit fieldInit | exists(ConstructorFieldInit fieldInit |
@@ -626,7 +611,7 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
} }
private TranslatedDestructorDestructionList getTranslatedDestructorDestructionList(Function func) { private TranslatedDestructorDestructionList getTranslatedDestructorDestructionList(Function func) {
result.getAst() = func result.getAST() = func
} }
/** /**
@@ -644,10 +629,7 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
override string toString() { result = "dtor destruction: " + func.toString() } override string toString() { result = "dtor destruction: " + func.toString() }
override Locatable getAst() { result = func } override Locatable getAST() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override TranslatedElement getChild(int id) { override TranslatedElement getChild(int id) {
exists(DestructorFieldDestruction fieldDestruction | exists(DestructorFieldDestruction fieldDestruction |
@@ -685,17 +667,14 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
} }
} }
TranslatedReadEffects getTranslatedReadEffects(Function func) { result.getAst() = func } TranslatedReadEffects getTranslatedReadEffects(Function func) { result.getAST() = func }
class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects { class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
Function func; Function func;
TranslatedReadEffects() { this = TTranslatedReadEffects(func) } TranslatedReadEffects() { this = TTranslatedReadEffects(func) }
override Locatable getAst() { result = func } override Locatable getAST() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Function getFunction() { result = func } override Function getFunction() { result = func }
@@ -739,11 +718,11 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
} }
private TranslatedThisReadEffect getTranslatedThisReadEffect(Function func) { private TranslatedThisReadEffect getTranslatedThisReadEffect(Function func) {
result.getAst() = func result.getAST() = func
} }
private TranslatedParameterReadEffect getTranslatedParameterReadEffect(Parameter param) { private TranslatedParameterReadEffect getTranslatedParameterReadEffect(Parameter param) {
result.getAst() = param result.getAST() = param
} }
abstract class TranslatedReadEffect extends TranslatedElement { abstract class TranslatedReadEffect extends TranslatedElement {
@@ -779,10 +758,7 @@ class TranslatedThisReadEffect extends TranslatedReadEffect, TTranslatedThisRead
TranslatedThisReadEffect() { this = TTranslatedThisReadEffect(func) } TranslatedThisReadEffect() { this = TTranslatedThisReadEffect(func) }
override Locatable getAst() { result = func } override Locatable getAST() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Function getFunction() { result = func } override Function getFunction() { result = func }
@@ -805,10 +781,7 @@ class TranslatedParameterReadEffect extends TranslatedReadEffect, TTranslatedPar
TranslatedParameterReadEffect() { this = TTranslatedParameterReadEffect(param) } TranslatedParameterReadEffect() { this = TTranslatedParameterReadEffect(param) }
override Locatable getAst() { result = param } override Locatable getAST() { result = param }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override string toString() { result = "read effect: " + param.toString() } override string toString() { result = "read effect: " + param.toString() }

View File

@@ -139,10 +139,7 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
final override Function getFunction() { result = expr.getEnclosingFunction() } final override Function getFunction() { result = expr.getEnclosingFunction() }
final override Locatable getAst() { result = expr } final override Locatable getAST() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
/** /**
* Gets the expression that is doing the initialization. * Gets the expression that is doing the initialization.
@@ -464,11 +461,11 @@ class TranslatedConstructorInitialization extends TranslatedDirectInitialization
TranslatedFieldInitialization getTranslatedFieldInitialization( TranslatedFieldInitialization getTranslatedFieldInitialization(
ClassAggregateLiteral initList, Field field ClassAggregateLiteral initList, Field field
) { ) {
result.getAst() = initList and result.getField() = field result.getAST() = initList and result.getField() = field
} }
TranslatedFieldInitialization getTranslatedConstructorFieldInitialization(ConstructorFieldInit init) { TranslatedFieldInitialization getTranslatedConstructorFieldInitialization(ConstructorFieldInit init) {
result.getAst() = init result.getAST() = init
} }
/** /**
@@ -481,10 +478,7 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
final override string toString() { result = ast.toString() + "." + field.toString() } final override string toString() { result = ast.toString() + "." + field.toString() }
final override Locatable getAst() { result = ast } final override Locatable getAST() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Function getFunction() { result = ast.getEnclosingFunction() } final override Function getFunction() { result = ast.getEnclosingFunction() }
@@ -628,10 +622,7 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
result = initList.toString() + "[" + getElementIndex().toString() + "]" result = initList.toString() + "[" + getElementIndex().toString() + "]"
} }
final override Locatable getAst() { result = initList } final override Locatable getAST() { result = initList }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Function getFunction() { result = initList.getEnclosingFunction() } final override Function getFunction() { result = initList.getEnclosingFunction() }
@@ -811,10 +802,7 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
abstract class TranslatedStructorCallFromStructor extends TranslatedElement, StructorCallContext { abstract class TranslatedStructorCallFromStructor extends TranslatedElement, StructorCallContext {
FunctionCall call; FunctionCall call;
final override Locatable getAst() { result = call } final override Locatable getAST() { result = call }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override TranslatedElement getChild(int id) { final override TranslatedElement getChild(int id) {
id = 0 and id = 0 and
@@ -876,7 +864,7 @@ abstract class TranslatedConstructorCallFromConstructor extends TranslatedStruct
} }
TranslatedConstructorCallFromConstructor getTranslatedConstructorBaseInit(ConstructorBaseInit init) { TranslatedConstructorCallFromConstructor getTranslatedConstructorBaseInit(ConstructorBaseInit init) {
result.getAst() = init result.getAST() = init
} }
/** /**
@@ -916,7 +904,7 @@ class TranslatedConstructorBaseInit extends TranslatedConstructorCallFromConstru
TranslatedDestructorBaseDestruction getTranslatedDestructorBaseDestruction( TranslatedDestructorBaseDestruction getTranslatedDestructorBaseDestruction(
DestructorBaseDestruction destruction DestructorBaseDestruction destruction
) { ) {
result.getAst() = destruction result.getAST() = destruction
} }
/** /**
@@ -940,10 +928,7 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
TranslatedConstructorBareInit() { this = TTranslatedConstructorBareInit(init) } TranslatedConstructorBareInit() { this = TTranslatedConstructorBareInit(init) }
override Locatable getAst() { result = init } override Locatable getAST() { result = init }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override string toString() { result = "construct base (no constructor)" } final override string toString() { result = "construct base (no constructor)" }
@@ -963,5 +948,5 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
} }
TranslatedConstructorBareInit getTranslatedConstructorBareInit(ConstructorInit init) { TranslatedConstructorBareInit getTranslatedConstructorBareInit(ConstructorInit init) {
result.getAst() = init result.getAST() = init
} }

View File

@@ -11,7 +11,7 @@ private import TranslatedExpr
private import TranslatedFunction private import TranslatedFunction
private import TranslatedInitialization private import TranslatedInitialization
TranslatedStmt getTranslatedStmt(Stmt stmt) { result.getAst() = stmt } TranslatedStmt getTranslatedStmt(Stmt stmt) { result.getAST() = stmt }
abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt { abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
Stmt stmt; Stmt stmt;
@@ -20,10 +20,7 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
final override string toString() { result = stmt.toString() } final override string toString() { result = stmt.toString() }
final override Locatable getAst() { result = stmt } final override Locatable getAST() { result = stmt }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Function getFunction() { result = stmt.getEnclosingFunction() } final override Function getFunction() { result = stmt.getEnclosingFunction() }
} }

View File

@@ -1,5 +1,7 @@
private import ReachableBlock as Reachability private import ReachableBlock as Reachability
private module ReachabilityGraph = Reachability::Graph;
module Graph { module Graph {
import Reachability::Graph import Reachability::Graph

View File

@@ -55,10 +55,7 @@ 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
@@ -69,7 +66,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.
@@ -93,10 +90,7 @@ 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()
@@ -163,10 +157,7 @@ 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,15 +208,12 @@ 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
@@ -462,10 +459,7 @@ 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

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

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,12 +430,6 @@ 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()
@@ -981,41 +975,35 @@ 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
@@ -1050,7 +1038,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()
} }
@@ -1073,7 +1061,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.
*/ */
@@ -1126,9 +1114,6 @@ 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

@@ -3,7 +3,7 @@ import semmle.code.cpp.ir.implementation.raw.internal.reachability.ReachableBloc
import semmle.code.cpp.ir.implementation.raw.internal.reachability.Dominance as Dominance import semmle.code.cpp.ir.implementation.raw.internal.reachability.Dominance as Dominance
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as NewIR import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as NewIR
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as RawStage import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as RawStage
import semmle.code.cpp.ir.implementation.internal.TInstruction::UnaliasedSsaInstructions as SSAInstructions import semmle.code.cpp.ir.implementation.internal.TInstruction::UnaliasedSSAInstructions as SSAInstructions
import semmle.code.cpp.ir.internal.IRCppLanguage as Language import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import SimpleSSA as Alias import SimpleSSA as Alias
import semmle.code.cpp.ir.implementation.internal.TOperand::UnaliasedSsaOperands as SSAOperands import semmle.code.cpp.ir.implementation.internal.TOperand::UnaliasedSSAOperands as SSAOperands

View File

@@ -41,14 +41,11 @@ predicate isVariableModeled(Allocation var) {
* subsequent iterations will recompute SSA for any variable that we assumed did not escape, but * subsequent iterations will recompute SSA for any variable that we assumed did not escape, but
* actually would have escaped if we had used a sound escape analysis. * actually would have escaped if we had used a sound escape analysis.
*/ */
predicate canReuseSsaForVariable(IRAutomaticVariable var) { predicate canReuseSSAForVariable(IRAutomaticVariable var) {
isVariableModeled(var) and isVariableModeled(var) and
not allocationEscapes(var) not allocationEscapes(var)
} }
/** DEPRECATED: Alias for canReuseSsaForVariable */
deprecated predicate canReuseSSAForVariable = canReuseSsaForVariable/1;
private newtype TMemoryLocation = MkMemoryLocation(Allocation var) { isVariableModeled(var) } private newtype TMemoryLocation = MkMemoryLocation(Allocation var) { isVariableModeled(var) }
private MemoryLocation getMemoryLocation(Allocation var) { result.getAllocation() = var } private MemoryLocation getMemoryLocation(Allocation var) { result.getAllocation() = var }
@@ -72,16 +69,10 @@ class MemoryLocation extends TMemoryLocation {
final string getUniqueId() { result = var.getUniqueId() } final string getUniqueId() { result = var.getUniqueId() }
final predicate canReuseSsa() { canReuseSsaForVariable(var) } final predicate canReuseSSA() { canReuseSSAForVariable(var) }
/** DEPRECATED: Alias for canReuseSsa */
deprecated predicate canReuseSSA() { canReuseSsa() }
} }
predicate canReuseSsaForOldResult(Instruction instr) { none() } predicate canReuseSSAForOldResult(Instruction instr) { none() }
/** DEPRECATED: Alias for canReuseSsaForOldResult */
deprecated predicate canReuseSSAForOldResult = canReuseSsaForOldResult/1;
/** /**
* Represents a set of `MemoryLocation`s that cannot overlap with * Represents a set of `MemoryLocation`s that cannot overlap with

View File

@@ -1,5 +1,7 @@
private import ReachableBlock as Reachability private import ReachableBlock as Reachability
private module ReachabilityGraph = Reachability::Graph;
module Graph { module Graph {
import Reachability::Graph import Reachability::Graph

View File

@@ -29,8 +29,8 @@ private import RangeAnalysisUtils
* 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 range-analysis SSA logic. * This class provides the range-analysis SSA logic.
*/ */
library class RangeSsa extends SsaHelper { library class RangeSSA extends SSAHelper {
RangeSsa() { this = 1 } RangeSSA() { this = 1 }
/** /**
* Add a phi node on the out-edge of a guard. * Add a phi node on the out-edge of a guard.
@@ -40,9 +40,6 @@ library class RangeSsa extends SsaHelper {
} }
} }
/** DEPRECATED: Alias for RangeSsa */
deprecated class RangeSSA = RangeSsa;
private predicate guard_defn(VariableAccess v, Expr guard, BasicBlock b, boolean branch) { private predicate guard_defn(VariableAccess v, Expr guard, BasicBlock b, boolean branch) {
guardCondition(guard, v, branch) and guardCondition(guard, v, branch) and
guardSuccessor(guard, branch, b) guardSuccessor(guard, branch, b)
@@ -70,22 +67,22 @@ private predicate guardSuccessor(Expr guard, boolean branch, BasicBlock succ) {
* nodes. * nodes.
*/ */
class RangeSsaDefinition extends ControlFlowNodeBase { class RangeSsaDefinition extends ControlFlowNodeBase {
RangeSsaDefinition() { exists(RangeSsa x | x.ssa_defn(_, this, _, _)) } RangeSsaDefinition() { exists(RangeSSA x | x.ssa_defn(_, this, _, _)) }
/** /**
* Gets a variable corresponding to a SSA StackVariable defined by * Gets a variable corresponding to a SSA StackVariable defined by
* this definition. * this definition.
*/ */
StackVariable getAVariable() { exists(RangeSsa x | x.ssa_defn(result, this, _, _)) } StackVariable getAVariable() { exists(RangeSSA x | x.ssa_defn(result, this, _, _)) }
/** /**
* A string representation of the SSA variable represented by the pair * A string representation of the SSA variable represented by the pair
* `(this, v)`. * `(this, v)`.
*/ */
string toString(StackVariable v) { exists(RangeSsa x | result = x.toString(this, v)) } string toString(StackVariable v) { exists(RangeSSA 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(RangeSsa x | result = x.getAUse(this, v)) } VariableAccess getAUse(StackVariable v) { exists(RangeSSA x | result = x.getAUse(this, v)) }
/** Gets the control flow node for this definition. */ /** Gets the control flow node for this definition. */
ControlFlowNode getDefinition() { result = this } ControlFlowNode getDefinition() { result = this }
@@ -94,7 +91,7 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
BasicBlock getBasicBlock() { result.contains(this.getDefinition()) } BasicBlock getBasicBlock() { result.contains(this.getDefinition()) }
/** Whether this definition is a phi node for variable `v`. */ /** Whether this definition is a phi node for variable `v`. */
predicate isPhiNode(StackVariable v) { exists(RangeSsa x | x.phi_node(v, this)) } predicate isPhiNode(StackVariable v) { exists(RangeSSA x | x.phi_node(v, this)) }
/** /**
* DEPRECATED: Use isGuardPhi/4 instead * DEPRECATED: Use isGuardPhi/4 instead
@@ -175,6 +172,6 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
* Holds if this definition of the variable `v` reached the end of the basic block `b`. * Holds if this definition of the variable `v` reached the end of the basic block `b`.
*/ */
predicate reachesEndOfBB(StackVariable v, BasicBlock b) { predicate reachesEndOfBB(StackVariable v, BasicBlock b) {
exists(RangeSsa x | x.ssaDefinitionReachesEndOfBB(v, this, b)) exists(RangeSSA x | x.ssaDefinitionReachesEndOfBB(v, this, b))
} }
} }

View File

@@ -89,7 +89,7 @@ private ControlFlowNode getControlFlowEntry(ControlFlowNode node) {
* graph so that we can use the dominator tree to find the most recent * graph so that we can use the dominator tree to find the most recent
* side-effect. * side-effect.
*/ */
private predicate sideEffectCfg(ControlFlowNode src, ControlFlowNode dst) { private predicate sideEffectCFG(ControlFlowNode src, ControlFlowNode dst) {
src.getASuccessor() = dst src.getASuccessor() = dst
or or
// Add an edge from the entry point to any node that might have a side // Add an edge from the entry point to any node that might have a side
@@ -103,7 +103,7 @@ private predicate sideEffectCfg(ControlFlowNode src, ControlFlowNode dst) {
* the side-effect CFG. * the side-effect CFG.
*/ */
private predicate iDomEffect(ControlFlowNode dominator, ControlFlowNode node) = private predicate iDomEffect(ControlFlowNode dominator, ControlFlowNode node) =
idominance(functionEntry/1, sideEffectCfg/2)(_, dominator, node) idominance(functionEntry/1, sideEffectCFG/2)(_, dominator, node)
/** /**
* Gets the most recent side effect. To be more precise, `result` is a * Gets the most recent side effect. To be more precise, `result` is a

View File

@@ -703,7 +703,7 @@ usertype_final(unique int id: @usertype ref);
usertype_uuid( usertype_uuid(
unique int id: @usertype ref, unique int id: @usertype ref,
string uuid: string ref unique string uuid: string ref
); );
mangled_name( mangled_name(

View File

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

View File

@@ -1,31 +1,3 @@
## 0.0.12
### Minor Analysis Improvements
* The `cpp/overflow-destination`, `cpp/unclear-array-index-validation`, and `cpp/uncontrolled-allocation-size` queries have been modernized and converted to `path-problem` queries and provide more true positive results.
* The `cpp/system-data-exposure` query has been increased from `medium` to `high` precision, following a number of improvements to the query logic.
## 0.0.11
### Breaking Changes
* The deprecated queries `cpp/duplicate-block`, `cpp/duplicate-function`, `cpp/duplicate-class`, `cpp/duplicate-file`, `cpp/mostly-duplicate-function`,`cpp/similar-file`, `cpp/duplicated-lines-in-files` have been removed.
### Deprecated Predicates and Classes
* The predicates and classes in the `CodeDuplication` library have been deprecated.
### New Queries
* A new query titled "Use of expired stack-address" (`cpp/using-expired-stack-address`) has been added.
This query finds accesses to expired stack-allocated memory that escaped via a global variable.
* A new `cpp/insufficient-key-size` query has been added to the default query suite for C/C++. The query finds uses of certain cryptographic algorithms where the key size is too small to provide adequate encryption strength.
### Minor Analysis Improvements
* The "Failure to use HTTPS URLs" (`cpp/non-https-url`) has been improved reducing false positive results, and its precision has been increased to 'high'.
* The `cpp/system-data-exposure` query has been modernized and has converted to a `path-problem` query. There are now fewer false positive results.
## 0.0.10 ## 0.0.10
### Deprecated Classes ### Deprecated Classes

View File

@@ -2,7 +2,7 @@
* @name Copy function using source size * @name Copy function using source size
* @description Calling a copy operation with a size derived from the source * @description Calling a copy operation with a size derived from the source
* buffer instead of the destination buffer may result in a buffer overflow. * buffer instead of the destination buffer may result in a buffer overflow.
* @kind path-problem * @kind problem
* @id cpp/overflow-destination * @id cpp/overflow-destination
* @problem.severity warning * @problem.severity warning
* @security-severity 9.3 * @security-severity 9.3
@@ -14,10 +14,7 @@
*/ */
import cpp import cpp
import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.security.TaintTracking
import semmle.code.cpp.controlflow.IRGuards
import semmle.code.cpp.security.FlowSources
import DataFlow::PathGraph
/** /**
* Holds if `fc` is a call to a copy operation where the size argument contains * Holds if `fc` is a call to a copy operation where the size argument contains
@@ -30,9 +27,9 @@ predicate sourceSized(FunctionCall fc, Expr src) {
fc.getTarget().hasGlobalOrStdName(["strncpy", "strncat", "memcpy", "memmove"]) and fc.getTarget().hasGlobalOrStdName(["strncpy", "strncat", "memcpy", "memmove"]) and
exists(Expr dest, Expr size, Variable v | exists(Expr dest, Expr size, Variable v |
fc.getArgument(0) = dest and fc.getArgument(0) = dest and
fc.getArgument(1).getFullyConverted() = src and fc.getArgument(1) = src and
fc.getArgument(2) = size and fc.getArgument(2) = size and
src = v.getAnAccess().getFullyConverted() and src = v.getAnAccess() and
size.getAChild+() = v.getAnAccess() and size.getAChild+() = v.getAnAccess() and
// exception: `dest` is also referenced in the size argument // exception: `dest` is also referenced in the size argument
not exists(Variable other | not exists(Variable other |
@@ -48,49 +45,9 @@ predicate sourceSized(FunctionCall fc, Expr src) {
) )
} }
predicate readsVariable(LoadInstruction load, Variable var) { from FunctionCall fc, Expr vuln, Expr taintSource
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
}
predicate hasUpperBoundsCheck(Variable var) {
exists(RelationalOperation oper, VariableAccess access |
oper.getAnOperand() = access and
access.getTarget() = var and
// Comparing to 0 is not an upper bound check
not oper.getAnOperand().getValue() = "0"
)
}
predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
readsVariable(node.asInstruction(), checkedVar) and
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
}
class OverflowDestinationConfig extends TaintTracking::Configuration {
OverflowDestinationConfig() { this = "OverflowDestinationConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
override predicate isSink(DataFlow::Node sink) { sourceSized(_, sink.asConvertedExpr()) }
override predicate isSanitizer(DataFlow::Node node) {
exists(Variable checkedVar |
readsVariable(node.asInstruction(), checkedVar) and
hasUpperBoundsCheck(checkedVar)
)
or
exists(Variable checkedVar, Operand access |
readsVariable(access.getDef(), checkedVar) and
nodeIsBarrierEqualityCandidate(node, access, checkedVar)
)
}
}
from
FunctionCall fc, OverflowDestinationConfig conf, DataFlow::PathNode source,
DataFlow::PathNode sink
where where
conf.hasFlowPath(source, sink) and sourceSized(fc, vuln) and
sourceSized(fc, sink.getNode().asConvertedExpr()) tainted(taintSource, vuln)
select fc, source, sink, select fc,
"To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size." "To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size."

View File

@@ -34,7 +34,7 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
exists(VariableAddressInstruction var, Function func | exists(VariableAddressInstruction var, Function func |
var = source.asInstruction() and var = source.asInstruction() and
func = var.getEnclosingFunction() and func = var.getEnclosingFunction() and
var.getAstVariable() instanceof StackVariable and var.getASTVariable() instanceof StackVariable and
// Pointer-to-member types aren't properly handled in the dbscheme. // Pointer-to-member types aren't properly handled in the dbscheme.
not var.getResultType() instanceof PointerToMemberType and not var.getResultType() instanceof PointerToMemberType and
// Rule out FPs caused by extraction errors. // Rule out FPs caused by extraction errors.
@@ -77,13 +77,12 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
from from
MustFlowPathNode source, MustFlowPathNode sink, VariableAddressInstruction var, MustFlowPathNode source, MustFlowPathNode sink, VariableAddressInstruction var,
ReturnStackAllocatedMemoryConfig conf, Function f ReturnStackAllocatedMemoryConfig conf
where where
conf.hasFlowPath(source, sink) and conf.hasFlowPath(source, sink) and
source.getNode().asInstruction() = var and source.getNode().asInstruction() = var and
// Only raise an alert if we're returning from the _same_ callable as the on that // Only raise an alert if we're returning from the _same_ callable as the on that
// declared the stack variable. // declared the stack variable.
var.getEnclosingFunction() = pragma[only_bind_into](f) and var.getEnclosingFunction() = sink.getNode().getEnclosingCallable()
sink.getNode().getEnclosingCallable() = pragma[only_bind_into](f) select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAST(),
select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAst(), var.getAST().toString()
var.getAst().toString()

View File

@@ -19,7 +19,7 @@ import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.IR
predicate instructionHasVariable(VariableAddressInstruction vai, StackVariable var, Function f) { predicate instructionHasVariable(VariableAddressInstruction vai, StackVariable var, Function f) {
var = vai.getAstVariable() and var = vai.getASTVariable() and
f = vai.getEnclosingFunction() and f = vai.getEnclosingFunction() and
// Pointer-to-member types aren't properly handled in the dbscheme. // Pointer-to-member types aren't properly handled in the dbscheme.
not vai.getResultType() instanceof PointerToMemberType and not vai.getResultType() instanceof PointerToMemberType and
@@ -108,7 +108,7 @@ predicate inheritanceConversionTypes(
/** Gets the HashCons value of an address computed by `instr`, if any. */ /** Gets the HashCons value of an address computed by `instr`, if any. */
TGlobalAddress globalAddress(Instruction instr) { TGlobalAddress globalAddress(Instruction instr) {
result = TGlobalVariable(instr.(VariableAddressInstruction).getAstVariable()) result = TGlobalVariable(instr.(VariableAddressInstruction).getASTVariable())
or or
not instr instanceof LoadInstruction and not instr instanceof LoadInstruction and
result = globalAddress(instr.(CopyInstruction).getSourceValue()) result = globalAddress(instr.(CopyInstruction).getSourceValue())

View File

@@ -52,7 +52,7 @@ predicate explicitNullTestOfInstruction(Instruction checked, Instruction bool) {
pragma[noinline] pragma[noinline]
predicate candidateResult(LoadInstruction checked, ValueNumber value, IRBlock dominator) { predicate candidateResult(LoadInstruction checked, ValueNumber value, IRBlock dominator) {
explicitNullTestOfInstruction(checked, _) and explicitNullTestOfInstruction(checked, _) and
not checked.getAst().isInMacroExpansion() and not checked.getAST().isInMacroExpansion() and
value.getAnInstruction() = checked and value.getAnInstruction() = checked and
dominator.dominates(checked.getBlock()) dominator.dominates(checked.getBlock())
} }

View File

@@ -11,7 +11,7 @@
import cpp import cpp
import ExternalAPIs import ExternalAPIs
from ExternalApiUsedWithUntrustedData externalApi from ExternalAPIUsedWithUntrustedData externalAPI
select externalApi, count(externalApi.getUntrustedDataNode()) as numberOfUses, select externalAPI, count(externalAPI.getUntrustedDataNode()) as numberOfUses,
externalApi.getNumberOfUntrustedSources() as numberOfUntrustedSources order by externalAPI.getNumberOfUntrustedSources() as numberOfUntrustedSources order by
numberOfUntrustedSources desc numberOfUntrustedSources desc

View File

@@ -9,31 +9,28 @@ private import semmle.code.cpp.models.interfaces.Taint
import ExternalAPIsSpecific import ExternalAPIsSpecific
/** A node representing untrusted data being passed to an external API. */ /** A node representing untrusted data being passed to an external API. */
class UntrustedExternalApiDataNode extends ExternalApiDataNode { class UntrustedExternalAPIDataNode extends ExternalAPIDataNode {
UntrustedExternalApiDataNode() { any(UntrustedDataToExternalApiConfig c).hasFlow(_, this) } UntrustedExternalAPIDataNode() { any(UntrustedDataToExternalAPIConfig c).hasFlow(_, this) }
/** Gets a source of untrusted data which is passed to this external API data node. */ /** Gets a source of untrusted data which is passed to this external API data node. */
DataFlow::Node getAnUntrustedSource() { DataFlow::Node getAnUntrustedSource() {
any(UntrustedDataToExternalApiConfig c).hasFlow(result, this) any(UntrustedDataToExternalAPIConfig c).hasFlow(result, this)
} }
} }
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */ private newtype TExternalAPI =
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode; TExternalAPIParameter(Function f, int index) {
exists(UntrustedExternalAPIDataNode n |
private newtype TExternalApi =
TExternalApiParameter(Function f, int index) {
exists(UntrustedExternalApiDataNode n |
f = n.getExternalFunction() and f = n.getExternalFunction() and
index = n.getIndex() index = n.getIndex()
) )
} }
/** An external API which is used with untrusted data. */ /** An external API which is used with untrusted data. */
class ExternalApiUsedWithUntrustedData extends TExternalApi { class ExternalAPIUsedWithUntrustedData extends TExternalAPI {
/** Gets a possibly untrusted use of this external API. */ /** Gets a possibly untrusted use of this external API. */
UntrustedExternalApiDataNode getUntrustedDataNode() { UntrustedExternalAPIDataNode getUntrustedDataNode() {
this = TExternalApiParameter(result.getExternalFunction(), result.getIndex()) this = TExternalAPIParameter(result.getExternalFunction(), result.getIndex())
} }
/** Gets the number of untrusted sources used with this external API. */ /** Gets the number of untrusted sources used with this external API. */
@@ -46,11 +43,8 @@ class ExternalApiUsedWithUntrustedData extends TExternalApi {
exists(Function f, int index, string indexString | exists(Function f, int index, string indexString |
if index = -1 then indexString = "qualifier" else indexString = "param " + index if index = -1 then indexString = "qualifier" else indexString = "param " + index
| |
this = TExternalApiParameter(f, index) and this = TExternalAPIParameter(f, index) and
result = f.toString() + " [" + indexString + "]" result = f.toString() + " [" + indexString + "]"
) )
} }
} }
/** DEPRECATED: Alias for ExternalApiUsedWithUntrustedData */
deprecated class ExternalAPIUsedWithUntrustedData = ExternalApiUsedWithUntrustedData;

View File

@@ -8,11 +8,11 @@ import semmle.code.cpp.models.interfaces.DataFlow
import SafeExternalAPIFunction import SafeExternalAPIFunction
/** A node representing untrusted data being passed to an external API. */ /** A node representing untrusted data being passed to an external API. */
class ExternalApiDataNode extends DataFlow::Node { class ExternalAPIDataNode extends DataFlow::Node {
Call call; Call call;
int i; int i;
ExternalApiDataNode() { ExternalAPIDataNode() {
// Argument to call to a function // Argument to call to a function
( (
this.asExpr() = call.getArgument(i) this.asExpr() = call.getArgument(i)
@@ -27,7 +27,7 @@ class ExternalApiDataNode extends DataFlow::Node {
not f instanceof DataFlowFunction and not f instanceof DataFlowFunction and
not f instanceof TaintFunction and not f instanceof TaintFunction and
// Not a call to a known safe external API // Not a call to a known safe external API
not f instanceof SafeExternalApiFunction not f instanceof SafeExternalAPIFunction
) )
} }
@@ -41,12 +41,9 @@ class ExternalApiDataNode extends DataFlow::Node {
string getFunctionDescription() { result = this.getExternalFunction().toString() } string getFunctionDescription() { result = this.getExternalFunction().toString() }
} }
/** DEPRECATED: Alias for ExternalApiDataNode */ /** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalAPIDataNode`s. */
deprecated class ExternalAPIDataNode = ExternalApiDataNode; class UntrustedDataToExternalAPIConfig extends TaintTracking::Configuration {
UntrustedDataToExternalAPIConfig() { this = "UntrustedDataToExternalAPIConfig" }
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" }
override predicate isSource(DataFlow::Node source) { override predicate isSource(DataFlow::Node source) {
exists(RemoteFlowSourceFunction remoteFlow | exists(RemoteFlowSourceFunction remoteFlow |
@@ -55,8 +52,5 @@ class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
) )
} }
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalAPIDataNode }
} }
/** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */
deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig;

View File

@@ -11,7 +11,7 @@
import cpp import cpp
import ir.ExternalAPIs import ir.ExternalAPIs
from ExternalApiUsedWithUntrustedData externalApi from ExternalAPIUsedWithUntrustedData externalAPI
select externalApi, count(externalApi.getUntrustedDataNode()) as numberOfUses, select externalAPI, count(externalAPI.getUntrustedDataNode()) as numberOfUses,
externalApi.getNumberOfUntrustedSources() as numberOfUntrustedSources order by externalAPI.getNumberOfUntrustedSources() as numberOfUntrustedSources order by
numberOfUntrustedSources desc numberOfUntrustedSources desc

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