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/DataFlowImpl4.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/DataFlowImplForLibraries.qll"
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll"
],
"DataFlow Java/C++/C#/Python Common": [
"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/tainttracking3/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/tainttrackingforlibraries/TaintTrackingImpl.qll"
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTrackingImpl.qll"
],
"DataFlow Java/C++/C#/Python Consistency checks": [
"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",
"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#": [
"java/ql/lib/semmle/code/java/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",
"javascript/ql/lib/semmle/javascript/frameworks/data/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
### New Features
@@ -33,7 +6,6 @@
## 0.0.9
## 0.0.8
### Deprecated APIs

View File

@@ -54,13 +54,11 @@ class Options extends string {
*
* By default, this holds for `exit`, `_exit`, `abort`, `__assert_fail`,
* `longjmp`, `__builtin_unreachable` and any function with a
* `noreturn` attribute or specifier.
* `noreturn` attribute.
*/
predicate exits(Function f) {
f.getAnAttribute().hasName("noreturn")
or
f.getASpecifier().hasName("noreturn")
or
f.hasGlobalOrStdName([
"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`,
* `longjmp`, `error`, `__builtin_unreachable` and any function with a
* `noreturn` attribute or specifier.
* `noreturn` attribute.
*/
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
### Minor Analysis Improvements
---
category: minorAnalysis
---
* 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
version: 0.0.12
version: 0.0.11-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -251,16 +251,6 @@ class Class extends UserType {
not this.implicitCopyConstructorDeleted() and
forall(CopyConstructor cc | cc = this.getAMemberFunction() |
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
forall(CopyAssignmentOperator ca | ca = this.getAMemberFunction() |
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) {
not decl instanceof Function
or
not exists(PrintAstConfiguration c)
not exists(PrintASTConfiguration c)
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
* printed.
*/
class Cfg extends PrintAstConfiguration {
class Cfg extends PrintASTConfiguration {
/**
* TWEAK THIS PREDICATE AS NEEDED.
* Holds if the AST for `func` should be printed.

View File

@@ -9,12 +9,12 @@
import cpp
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.
*/
class PrintAstConfiguration extends TPrintAstConfiguration {
class PrintASTConfiguration extends TPrintASTConfiguration {
/**
* Gets a textual representation of this `PrintASTConfiguration`.
*/
@@ -27,11 +27,8 @@ class PrintAstConfiguration extends TPrintAstConfiguration {
predicate shouldPrintFunction(Function func) { any() }
}
/** DEPRECATED: Alias for PrintAstConfiguration */
deprecated class PrintASTConfiguration = PrintAstConfiguration;
private predicate shouldPrintFunction(Function func) {
exists(PrintAstConfiguration config | config.shouldPrintFunction(func))
exists(PrintASTConfiguration config | config.shouldPrintFunction(func))
}
bindingset[s]
@@ -88,8 +85,8 @@ private Function getEnclosingFunction(Locatable ast) {
* Most nodes are just a wrapper around `Locatable`, but we do synthesize new
* nodes for things like parameter lists and constructor init lists.
*/
private newtype TPrintAstNode =
TAstNode(Locatable ast) { shouldPrintFunction(getEnclosingFunction(ast)) } or
private newtype TPrintASTNode =
TASTNode(Locatable ast) { shouldPrintFunction(getEnclosingFunction(ast)) } or
TDeclarationEntryNode(DeclStmt stmt, DeclarationEntry entry) {
// 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.
@@ -109,7 +106,7 @@ private newtype TPrintAstNode =
/**
* 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.
*/
@@ -119,17 +116,17 @@ class PrintAstNode extends TPrintAstNode {
* Gets the child node at index `childIndex`. Child indices must be unique,
* but need not be contiguous.
*/
abstract PrintAstNode getChildInternal(int childIndex);
abstract PrintASTNode getChildInternal(int childIndex);
/**
* Gets the child node at index `childIndex`.
* Adds edges to fully converted expressions, that are not part of the
* 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.
result =
rank[childIndex](PrintAstNode child, int nonConvertedIndex, boolean isConverted |
rank[childIndex](PrintASTNode child, int nonConvertedIndex, boolean isConverted |
childAndAccessorPredicate(child, _, nonConvertedIndex, isConverted)
|
// 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
* `childIndex`, if that node has any conversions.
*/
private PrintAstNode getConvertedChild(int childIndex) {
private PrintASTNode getConvertedChild(int childIndex) {
exists(Expr expr |
expr = getChildInternal(childIndex).(AstNode).getAst() and
expr = getChildInternal(childIndex).(ASTNode).getAST() and
expr.getFullyConverted() instanceof Conversion and
result.(AstNode).getAst() = expr.getFullyConverted() and
result.(ASTNode).getAST() = expr.getFullyConverted() and
not expr instanceof Conversion
)
}
@@ -169,12 +166,12 @@ class PrintAstNode extends TPrintAstNode {
/**
* Gets the children of this node.
*/
final PrintAstNode getAChild() { result = getChild(_) }
final PrintASTNode getAChild() { result = getChild(_) }
/**
* 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.
@@ -199,7 +196,7 @@ class PrintAstNode extends TPrintAstNode {
* one result tuple, with `isConverted = false`.
*/
private predicate childAndAccessorPredicate(
PrintAstNode child, string childPredicate, int nonConvertedIndex, boolean isConverted
PrintASTNode child, string childPredicate, int nonConvertedIndex, boolean isConverted
) {
child = getChildInternal(nonConvertedIndex) and
childPredicate = getChildAccessorPredicateInternal(nonConvertedIndex) and
@@ -237,15 +234,12 @@ class PrintAstNode extends TPrintAstNode {
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.
*/
private class PrintableElement extends Element {
PrintableElement() {
exists(TAstNode(this))
exists(TASTNode(this))
or
exists(TDeclarationEntryNode(_, this))
or
@@ -268,7 +262,7 @@ private string qlClass(PrintableElement el) {
/**
* A node representing an AST node.
*/
abstract class BaseAstNode extends PrintAstNode {
abstract class BaseASTNode extends PrintASTNode {
Locatable ast;
override string toString() { result = qlClass(ast) + ast.toString() }
@@ -278,34 +272,25 @@ abstract class BaseAstNode extends PrintAstNode {
/**
* Gets the AST represented by this node.
*/
final Locatable getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated Locatable getAST() { result = getAst() }
final Locatable getAST() { result = ast }
}
/** DEPRECATED: Alias for BaseAstNode */
deprecated class BaseASTNode = BaseAstNode;
/**
* A node representing an AST node other than a `DeclarationEntry`.
*/
abstract class AstNode extends BaseAstNode, TAstNode {
AstNode() { this = TAstNode(ast) }
abstract class ASTNode extends BaseASTNode, TASTNode {
ASTNode() { this = TASTNode(ast) }
}
/** DEPRECATED: Alias for AstNode */
deprecated class ASTNode = AstNode;
/**
* A node representing an `Expr`.
*/
class ExprNode extends AstNode {
class ExprNode extends ASTNode {
Expr expr;
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) {
result = super.getProperty(key)
@@ -321,7 +306,7 @@ class ExprNode extends AstNode {
}
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 }
override AstNode getChildInternal(int childIndex) {
override ASTNode getChildInternal(int childIndex) {
childIndex = 0 and
result.getAst() = conv.getExpr() and
result.getAST() = conv.getExpr() and
conv.getExpr() instanceof Conversion
}
}
@@ -378,27 +363,27 @@ class CastNode extends ConversionNode {
class StmtExprNode extends ExprNode {
override StmtExpr expr;
override AstNode getChildInternal(int childIndex) {
override ASTNode getChildInternal(int childIndex) {
childIndex = 0 and
result.getAst() = expr.getStmt()
result.getAST() = expr.getStmt()
}
}
/**
* A node representing a `DeclarationEntry`.
*/
class DeclarationEntryNode extends BaseAstNode, TDeclarationEntryNode {
class DeclarationEntryNode extends BaseASTNode, TDeclarationEntryNode {
override DeclarationEntry ast;
DeclStmt declStmt;
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 getProperty(string key) {
result = BaseAstNode.super.getProperty(key)
result = BaseASTNode.super.getProperty(key)
or
key = "Type" and
result = qlClass(ast.getType()) + ast.getType().toString()
@@ -411,9 +396,9 @@ class DeclarationEntryNode extends BaseAstNode, TDeclarationEntryNode {
class VariableDeclarationEntryNode extends DeclarationEntryNode {
override VariableDeclarationEntry ast;
override AstNode getChildInternal(int childIndex) {
override ASTNode getChildInternal(int childIndex) {
childIndex = 0 and
result.getAst() = ast.getVariable().getInitializer()
result.getAST() = ast.getVariable().getInitializer()
}
override string getChildAccessorPredicateInternal(int childIndex) {
@@ -425,23 +410,23 @@ class VariableDeclarationEntryNode extends DeclarationEntryNode {
/**
* A node representing a `Stmt`.
*/
class StmtNode extends AstNode {
class StmtNode extends ASTNode {
Stmt stmt;
StmtNode() { stmt = ast }
override BaseAstNode getChildInternal(int childIndex) {
override BaseASTNode getChildInternal(int childIndex) {
exists(Locatable child |
child = stmt.getChild(childIndex) and
(
result.getAst() = child.(Expr) or
result.getAst() = child.(Stmt)
result.getAST() = child.(Expr) or
result.getAST() = child.(Stmt)
)
)
}
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`.
*/
class ParameterNode extends AstNode {
class ParameterNode extends ASTNode {
Parameter param;
ParameterNode() { param = ast }
final override PrintAstNode getChildInternal(int childIndex) { none() }
final override PrintASTNode getChildInternal(int childIndex) { none() }
final override string getChildAccessorPredicateInternal(int childIndex) { none() }
@@ -484,14 +469,14 @@ class ParameterNode extends AstNode {
/**
* A node representing an `Initializer`.
*/
class InitializerNode extends AstNode {
class InitializerNode extends ASTNode {
Initializer init;
InitializerNode() { init = ast }
override AstNode getChildInternal(int childIndex) {
override ASTNode getChildInternal(int childIndex) {
childIndex = 0 and
result.getAst() = init.getExpr()
result.getAST() = init.getExpr()
}
override string getChildAccessorPredicateInternal(int childIndex) {
@@ -503,7 +488,7 @@ class InitializerNode extends AstNode {
/**
* A node representing the parameters of a `Function`.
*/
class ParametersNode extends PrintAstNode, TParametersNode {
class ParametersNode extends PrintASTNode, TParametersNode {
Function func;
ParametersNode() { this = TParametersNode(func) }
@@ -512,8 +497,8 @@ class ParametersNode extends PrintAstNode, TParametersNode {
final override Location getLocation() { result = getRepresentativeLocation(func) }
override AstNode getChildInternal(int childIndex) {
result.getAst() = func.getParameter(childIndex)
override ASTNode getChildInternal(int childIndex) {
result.getAST() = func.getParameter(childIndex)
}
override string getChildAccessorPredicateInternal(int childIndex) {
@@ -530,7 +515,7 @@ class ParametersNode extends PrintAstNode, TParametersNode {
/**
* A node representing the initializer list of a `Constructor`.
*/
class ConstructorInitializersNode extends PrintAstNode, TConstructorInitializersNode {
class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializersNode {
Constructor ctor;
ConstructorInitializersNode() { this = TConstructorInitializersNode(ctor) }
@@ -539,8 +524,8 @@ class ConstructorInitializersNode extends PrintAstNode, TConstructorInitializers
final override Location getLocation() { result = getRepresentativeLocation(ctor) }
final override AstNode getChildInternal(int childIndex) {
result.getAst() = ctor.getInitializer(childIndex)
final override ASTNode getChildInternal(int childIndex) {
result.getAST() = ctor.getInitializer(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`.
*/
class DestructorDestructionsNode extends PrintAstNode, TDestructorDestructionsNode {
class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNode {
Destructor dtor;
DestructorDestructionsNode() { this = TDestructorDestructionsNode(dtor) }
@@ -566,8 +551,8 @@ class DestructorDestructionsNode extends PrintAstNode, TDestructorDestructionsNo
final override Location getLocation() { result = getRepresentativeLocation(dtor) }
final override AstNode getChildInternal(int childIndex) {
result.getAst() = dtor.getDestruction(childIndex)
final override ASTNode getChildInternal(int childIndex) {
result.getAST() = dtor.getDestruction(childIndex)
}
final override string getChildAccessorPredicateInternal(int childIndex) {
@@ -584,14 +569,14 @@ class DestructorDestructionsNode extends PrintAstNode, TDestructorDestructionsNo
/**
* A node representing a `Function`.
*/
class FunctionNode extends AstNode {
class FunctionNode extends ASTNode {
Function func;
FunctionNode() { func = ast }
override string toString() { result = qlClass(func) + getIdentityString(func) }
override PrintAstNode getChildInternal(int childIndex) {
override PrintASTNode getChildInternal(int childIndex) {
childIndex = 0 and
result.(ParametersNode).getFunction() = func
or
@@ -599,7 +584,7 @@ class FunctionNode extends AstNode {
result.(ConstructorInitializersNode).getConstructor() = func
or
childIndex = 2 and
result.(AstNode).getAst() = func.getEntryPoint()
result.(ASTNode).getAST() = func.getEntryPoint()
or
childIndex = 3 and
result.(DestructorDestructionsNode).getDestructor() = func
@@ -618,7 +603,7 @@ class FunctionNode extends AstNode {
private int getOrder() {
this =
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)
|
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`. */
query predicate nodes(PrintAstNode node, string key, string value) {
query predicate nodes(PrintASTNode node, string key, string value) {
node.shouldPrint() and
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
* 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 |
source.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`,
* or `mutable`.
* or `mutable".
*/
class StorageClassSpecifier extends Specifier {
StorageClassSpecifier() { this.hasName(["auto", "register", "static", "extern", "mutable"]) }

View File

@@ -4,11 +4,11 @@
import semmle.files.FileSystem
private class TXmlLocatable =
private class TXMLLocatable =
@xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters;
/** An XML element that has a location. */
class XMLLocatable extends @xmllocatable, TXmlLocatable {
class XMLLocatable extends @xmllocatable, TXMLLocatable {
/** Gets the source location for this element. */
Location getLocation() { xmllocations(this, result) }

View File

@@ -65,7 +65,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
* taken when this expression is true.
*/
ControlFlowNode getATrueSuccessor() {
qlCfgTrueSuccessor(this, result) and
qlCFGTrueSuccessor(this, result) and
result = this.getASuccessor()
}
@@ -74,7 +74,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
* taken when this expression is false.
*/
ControlFlowNode getAFalseSuccessor() {
qlCfgFalseSuccessor(this, result) and
qlCFGFalseSuccessor(this, result) and
result = this.getASuccessor()
}
@@ -121,7 +121,7 @@ abstract class AdditionalControlFlowEdge extends ControlFlowNodeBase {
* `AdditionalControlFlowEdge`. Use this relation instead of `qlCFGSuccessor`.
*/
predicate successors_extended(ControlFlowNodeBase source, ControlFlowNodeBase target) {
qlCfgSuccessor(source, target)
qlCFGSuccessor(source, target)
or
source.(AdditionalControlFlowEdge).getAnEdgeTarget() = target
}

View File

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

View File

@@ -10,13 +10,10 @@ import SSAUtils
* The SSA logic comes in two versions: the standard SSA and range-analysis RangeSSA.
* This class provides the standard SSA logic.
*/
library class StandardSsa extends SsaHelper {
StandardSsa() { this = 0 }
library class StandardSSA extends SSAHelper {
StandardSSA() { this = 0 }
}
/** DEPRECATED: Alias for StandardSsa */
deprecated class StandardSSA = StandardSsa;
/**
* 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
@@ -30,22 +27,22 @@ deprecated class StandardSSA = StandardSsa;
* statically seen to be unreachable.
*/
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
* 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
* `(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)`. */
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
@@ -65,7 +62,7 @@ class SsaDefinition extends ControlFlowNodeBase {
BasicBlock getBasicBlock() { result.contains(this.getDefinition()) }
/** 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. */
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`. */
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. */
cached
library class SsaHelper extends int {
library class SSAHelper extends int {
/* 0 = StandardSSA, 1 = RangeSSA */
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
@@ -311,6 +311,3 @@ library class SsaHelper extends int {
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
* contiguous, and the first index is 0.
@@ -1359,7 +1379,7 @@ private module Cached {
* true-successors and false-successors.
*/
cached
predicate qlCfgSuccessor(Node n1, Node n2) {
predicate qlCFGSuccessor(Node n1, Node n2) {
exists(Node memberNode, Pos memberPos |
subEdgeIncludingDestructors(any(Pos at | at.isAt()), n1, memberNode, memberPos) and
normalGroupMember(memberNode, memberPos, n2)
@@ -1368,32 +1388,23 @@ private module Cached {
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
* edge `(n1, n2)` may be taken when `n1` is an expression that is true.
*/
cached
predicate qlCfgTrueSuccessor(Node n1, Node n2) {
predicate qlCFGTrueSuccessor(Node n1, Node n2) {
conditionalSuccessor(n1, true, n2) and
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
* edge `(n1, n2)` may be taken when `n1` is an expression that is false.
*/
cached
predicate qlCfgFalseSuccessor(Node n1, Node n2) {
predicate qlCFGFalseSuccessor(Node n1, Node n2) {
conditionalSuccessor(n1, false, n2) and
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) {
conditionAlwaysTrue(condition) and
qlCfgFalseSuccessor(condition, succ) and
not qlCfgTrueSuccessor(condition, succ)
qlCFGFalseSuccessor(condition, succ) and
not qlCFGTrueSuccessor(condition, succ)
}
/**
@@ -197,8 +197,8 @@ private predicate impossibleFalseEdge(Expr condition, Node succ) {
*/
private predicate impossibleTrueEdge(Expr condition, Node succ) {
conditionAlwaysFalse(condition) and
qlCfgTrueSuccessor(condition, succ) and
not qlCfgFalseSuccessor(condition, succ)
qlCFGTrueSuccessor(condition, succ) and
not qlCFGFalseSuccessor(condition, succ)
}
/**
@@ -960,9 +960,9 @@ library class ConditionEvaluator extends ExprEvaluator {
ConditionEvaluator() { this = 0 }
override predicate interesting(Expr e) {
qlCfgFalseSuccessor(e, _)
qlCFGFalseSuccessor(e, _)
or
qlCfgTrueSuccessor(e, _)
qlCFGTrueSuccessor(e, _)
}
}

View File

@@ -20,4 +20,5 @@ import semmle.code.cpp.dataflow.DataFlow2
module TaintTracking {
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. */
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. */
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. */
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
* into account in the analysis.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
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]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -381,19 +345,9 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic]
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)
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`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -476,8 +430,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) 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(node2, s2, config)
)
@@ -519,8 +471,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) 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(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -920,8 +870,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1016,8 +966,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1038,8 +988,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
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
* 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
(
sourceNode(node, state, config)
or
jumpStep(_, node, config)
or
additionalJumpStep(_, node, config)
or
additionalJumpStateStep(_, _, node, state, config)
or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
sourceNode(node, state, config) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
additionalJumpStateStep(_, _, node, state, config) or
node instanceof ParamNodeEx or
node.asNode() instanceof OutNodeExt or
store(_, _, node, _, config) or
read(_, _, node, config) or
node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
)
}
@@ -1800,9 +1737,6 @@ private module LocalFlowBigStep {
or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
)
or
Stage2::revFlow(node, state, config) and
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/
pragma[nomagic]
private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
Configuration config, LocalCallContext cc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, Configuration config, LocalCallContext cc
) {
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
state1 = state2 and
preservesValue = true and
t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
t = node1.getDataFlowType() // irrelevant dummy value
or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
preservesValue = false and
t = node2.getDataFlowType()
) and
node1 != node2 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
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
localFlowStepNodeCand1(mid, node2, config) 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
exists(NodeEx mid |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode 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,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) {
localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
localFlowExit(node2, state1, config) and
state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
callContext) and
localFlowExit(node2, state2, config)
}
}
@@ -2769,10 +2695,10 @@ private module Stage4 {
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(

View File

@@ -87,30 +87,12 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
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. */
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. */
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
* into account in the analysis.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
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]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -381,19 +345,9 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic]
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)
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`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -476,8 +430,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) 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(node2, s2, config)
)
@@ -519,8 +471,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) 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(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -920,8 +870,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1016,8 +966,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1038,8 +988,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
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
* 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
(
sourceNode(node, state, config)
or
jumpStep(_, node, config)
or
additionalJumpStep(_, node, config)
or
additionalJumpStateStep(_, _, node, state, config)
or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
sourceNode(node, state, config) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
additionalJumpStateStep(_, _, node, state, config) or
node instanceof ParamNodeEx or
node.asNode() instanceof OutNodeExt or
store(_, _, node, _, config) or
read(_, _, node, config) or
node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
)
}
@@ -1800,9 +1737,6 @@ private module LocalFlowBigStep {
or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
)
or
Stage2::revFlow(node, state, config) and
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/
pragma[nomagic]
private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
Configuration config, LocalCallContext cc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, Configuration config, LocalCallContext cc
) {
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
state1 = state2 and
preservesValue = true and
t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
t = node1.getDataFlowType() // irrelevant dummy value
or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
preservesValue = false and
t = node2.getDataFlowType()
) and
node1 != node2 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
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
localFlowStepNodeCand1(mid, node2, config) 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
exists(NodeEx mid |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode 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,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) {
localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
localFlowExit(node2, state1, config) and
state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
callContext) and
localFlowExit(node2, state2, config)
}
}
@@ -2769,10 +2695,10 @@ private module Stage4 {
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(

View File

@@ -87,30 +87,12 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
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. */
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. */
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
* into account in the analysis.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
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]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -381,19 +345,9 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic]
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)
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`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -476,8 +430,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) 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(node2, s2, config)
)
@@ -519,8 +471,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) 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(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -920,8 +870,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1016,8 +966,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1038,8 +988,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
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
* 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
(
sourceNode(node, state, config)
or
jumpStep(_, node, config)
or
additionalJumpStep(_, node, config)
or
additionalJumpStateStep(_, _, node, state, config)
or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
sourceNode(node, state, config) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
additionalJumpStateStep(_, _, node, state, config) or
node instanceof ParamNodeEx or
node.asNode() instanceof OutNodeExt or
store(_, _, node, _, config) or
read(_, _, node, config) or
node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
)
}
@@ -1800,9 +1737,6 @@ private module LocalFlowBigStep {
or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
)
or
Stage2::revFlow(node, state, config) and
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/
pragma[nomagic]
private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
Configuration config, LocalCallContext cc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, Configuration config, LocalCallContext cc
) {
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
state1 = state2 and
preservesValue = true and
t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
t = node1.getDataFlowType() // irrelevant dummy value
or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
preservesValue = false and
t = node2.getDataFlowType()
) and
node1 != node2 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
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
localFlowStepNodeCand1(mid, node2, config) 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
exists(NodeEx mid |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode 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,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) {
localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
localFlowExit(node2, state1, config) and
state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
callContext) and
localFlowExit(node2, state2, config)
}
}
@@ -2769,10 +2695,10 @@ private module Stage4 {
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(

View File

@@ -87,30 +87,12 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
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. */
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. */
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
* into account in the analysis.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
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]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -381,19 +345,9 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic]
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)
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`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -476,8 +430,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) 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(node2, s2, config)
)
@@ -519,8 +471,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) 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(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -920,8 +870,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1016,8 +966,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1038,8 +988,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
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
* 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
(
sourceNode(node, state, config)
or
jumpStep(_, node, config)
or
additionalJumpStep(_, node, config)
or
additionalJumpStateStep(_, _, node, state, config)
or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
sourceNode(node, state, config) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
additionalJumpStateStep(_, _, node, state, config) or
node instanceof ParamNodeEx or
node.asNode() instanceof OutNodeExt or
store(_, _, node, _, config) or
read(_, _, node, config) or
node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
)
}
@@ -1800,9 +1737,6 @@ private module LocalFlowBigStep {
or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
)
or
Stage2::revFlow(node, state, config) and
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/
pragma[nomagic]
private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
Configuration config, LocalCallContext cc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, Configuration config, LocalCallContext cc
) {
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
state1 = state2 and
preservesValue = true and
t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
t = node1.getDataFlowType() // irrelevant dummy value
or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
preservesValue = false and
t = node2.getDataFlowType()
) and
node1 != node2 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
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
localFlowStepNodeCand1(mid, node2, config) 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
exists(NodeEx mid |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode 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,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) {
localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
localFlowExit(node2, state1, config) and
state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
callContext) and
localFlowExit(node2, state2, config)
}
}
@@ -2769,10 +2695,10 @@ private module Stage4 {
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(

View File

@@ -87,30 +87,12 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
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. */
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. */
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
* into account in the analysis.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
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]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -381,19 +345,9 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic]
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)
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`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -476,8 +430,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) 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(node2, s2, config)
)
@@ -519,8 +471,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) 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(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -920,8 +870,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1016,8 +966,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1038,8 +988,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
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
* 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
(
sourceNode(node, state, config)
or
jumpStep(_, node, config)
or
additionalJumpStep(_, node, config)
or
additionalJumpStateStep(_, _, node, state, config)
or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
sourceNode(node, state, config) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
additionalJumpStateStep(_, _, node, state, config) or
node instanceof ParamNodeEx or
node.asNode() instanceof OutNodeExt or
store(_, _, node, _, config) or
read(_, _, node, config) or
node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
)
}
@@ -1800,9 +1737,6 @@ private module LocalFlowBigStep {
or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
)
or
Stage2::revFlow(node, state, config) and
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/
pragma[nomagic]
private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
Configuration config, LocalCallContext cc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, Configuration config, LocalCallContext cc
) {
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
state1 = state2 and
preservesValue = true and
t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
t = node1.getDataFlowType() // irrelevant dummy value
or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
preservesValue = false and
t = node2.getDataFlowType()
) and
node1 != node2 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
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
localFlowStepNodeCand1(mid, node2, config) 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
exists(NodeEx mid |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode 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,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) {
localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
localFlowExit(node2, state1, config) and
state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
callContext) and
localFlowExit(node2, state2, config)
}
}
@@ -2769,10 +2695,10 @@ private module Stage4 {
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(

View File

@@ -64,30 +64,13 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() }
/**
* Holds if `source` is a relevant taint source with the given initial
* `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
/**
* Holds if `sink` is a relevant taint sink
* Holds if `sink` is a relevant taint sink.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
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. */
predicate isSanitizer(DataFlow::Node node) { none() }
@@ -96,29 +79,9 @@ abstract class Configuration extends DataFlow::Configuration {
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. */
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) }
/** 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) }
/**
* 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. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
@@ -143,16 +96,6 @@ abstract class Configuration extends DataFlow::Configuration {
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`
* must be taken into account in the analysis.
@@ -164,25 +107,6 @@ abstract class Configuration extends DataFlow::Configuration {
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) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
defaultImplicitTaintRead(node, c)

View File

@@ -64,30 +64,13 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() }
/**
* Holds if `source` is a relevant taint source with the given initial
* `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
/**
* Holds if `sink` is a relevant taint sink
* Holds if `sink` is a relevant taint sink.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
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. */
predicate isSanitizer(DataFlow::Node node) { none() }
@@ -96,29 +79,9 @@ abstract class Configuration extends DataFlow::Configuration {
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. */
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) }
/** 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) }
/**
* 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. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
@@ -143,16 +96,6 @@ abstract class Configuration extends DataFlow::Configuration {
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`
* must be taken into account in the analysis.
@@ -164,25 +107,6 @@ abstract class Configuration extends DataFlow::Configuration {
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) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
defaultImplicitTaintRead(node, c)

View File

@@ -129,11 +129,11 @@ private class FromGlobalVarTaintTrackingCfg extends TaintTracking2::Configuratio
}
private predicate readsVariable(LoadInstruction load, Variable var) {
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
load.getSourceAddress().(VariableAddressInstruction).getASTVariable() = 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. */
Element getElementFromPathNode(PathNode pathNode) {
exists(DataFlow::Node node | node = pathNode.(WrapPathNode).inner().getNode() |
result = node.asInstruction().getAst()
result = node.asInstruction().getAST()
or
result = node.asOperand().getDef().getAst()
result = node.asOperand().getDef().getAST()
)
or
result = pathNode.(EndpointPathNode).inner()

View File

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

View File

@@ -20,4 +20,5 @@ import semmle.code.cpp.ir.dataflow.DataFlow2
module TaintTracking {
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`. */
private predicate addressOfGlobal(Instruction addressInstr, GlobalOrNamespaceVariable var) {
// Access directly to the global variable
addressInstr.(VariableAddressInstruction).getAstVariable() = var
addressInstr.(VariableAddressInstruction).getASTVariable() = var
or
// Access to a field on a global union
exists(FieldAddressInstruction fa |
fa = addressInstr and
fa.getObjectAddress().(VariableAddressInstruction).getAstVariable() = var and
fa.getObjectAddress().(VariableAddressInstruction).getASTVariable() = var and
fa.getField().getDeclaringType() instanceof Union
)
}

View File

@@ -87,30 +87,12 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
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. */
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. */
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
* into account in the analysis.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
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]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -381,19 +345,9 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic]
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)
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`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -476,8 +430,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) 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(node2, s2, config)
)
@@ -519,8 +471,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) 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(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -920,8 +870,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1016,8 +966,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1038,8 +988,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
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
* 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
(
sourceNode(node, state, config)
or
jumpStep(_, node, config)
or
additionalJumpStep(_, node, config)
or
additionalJumpStateStep(_, _, node, state, config)
or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
sourceNode(node, state, config) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
additionalJumpStateStep(_, _, node, state, config) or
node instanceof ParamNodeEx or
node.asNode() instanceof OutNodeExt or
store(_, _, node, _, config) or
read(_, _, node, config) or
node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
)
}
@@ -1800,9 +1737,6 @@ private module LocalFlowBigStep {
or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
)
or
Stage2::revFlow(node, state, config) and
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/
pragma[nomagic]
private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
Configuration config, LocalCallContext cc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, Configuration config, LocalCallContext cc
) {
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
state1 = state2 and
preservesValue = true and
t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
t = node1.getDataFlowType() // irrelevant dummy value
or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
preservesValue = false and
t = node2.getDataFlowType()
) and
node1 != node2 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
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
localFlowStepNodeCand1(mid, node2, config) 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
exists(NodeEx mid |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode 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,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) {
localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
localFlowExit(node2, state1, config) and
state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
callContext) and
localFlowExit(node2, state2, config)
}
}
@@ -2769,10 +2695,10 @@ private module Stage4 {
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(

View File

@@ -87,30 +87,12 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
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. */
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. */
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
* into account in the analysis.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
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]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -381,19 +345,9 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic]
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)
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`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -476,8 +430,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) 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(node2, s2, config)
)
@@ -519,8 +471,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) 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(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -920,8 +870,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1016,8 +966,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1038,8 +988,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
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
* 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
(
sourceNode(node, state, config)
or
jumpStep(_, node, config)
or
additionalJumpStep(_, node, config)
or
additionalJumpStateStep(_, _, node, state, config)
or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
sourceNode(node, state, config) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
additionalJumpStateStep(_, _, node, state, config) or
node instanceof ParamNodeEx or
node.asNode() instanceof OutNodeExt or
store(_, _, node, _, config) or
read(_, _, node, config) or
node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
)
}
@@ -1800,9 +1737,6 @@ private module LocalFlowBigStep {
or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
)
or
Stage2::revFlow(node, state, config) and
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/
pragma[nomagic]
private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
Configuration config, LocalCallContext cc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, Configuration config, LocalCallContext cc
) {
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
state1 = state2 and
preservesValue = true and
t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
t = node1.getDataFlowType() // irrelevant dummy value
or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
preservesValue = false and
t = node2.getDataFlowType()
) and
node1 != node2 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
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
localFlowStepNodeCand1(mid, node2, config) 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
exists(NodeEx mid |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode 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,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) {
localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
localFlowExit(node2, state1, config) and
state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
callContext) and
localFlowExit(node2, state2, config)
}
}
@@ -2769,10 +2695,10 @@ private module Stage4 {
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(

View File

@@ -87,30 +87,12 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
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. */
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. */
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
* into account in the analysis.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
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]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -381,19 +345,9 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic]
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)
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`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -476,8 +430,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) 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(node2, s2, config)
)
@@ -519,8 +471,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) 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(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -920,8 +870,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1016,8 +966,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1038,8 +988,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
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
* 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
(
sourceNode(node, state, config)
or
jumpStep(_, node, config)
or
additionalJumpStep(_, node, config)
or
additionalJumpStateStep(_, _, node, state, config)
or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
sourceNode(node, state, config) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
additionalJumpStateStep(_, _, node, state, config) or
node instanceof ParamNodeEx or
node.asNode() instanceof OutNodeExt or
store(_, _, node, _, config) or
read(_, _, node, config) or
node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
)
}
@@ -1800,9 +1737,6 @@ private module LocalFlowBigStep {
or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
)
or
Stage2::revFlow(node, state, config) and
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/
pragma[nomagic]
private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
Configuration config, LocalCallContext cc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, Configuration config, LocalCallContext cc
) {
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
state1 = state2 and
preservesValue = true and
t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
t = node1.getDataFlowType() // irrelevant dummy value
or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
preservesValue = false and
t = node2.getDataFlowType()
) and
node1 != node2 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
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
localFlowStepNodeCand1(mid, node2, config) 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
exists(NodeEx mid |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode 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,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) {
localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
localFlowExit(node2, state1, config) and
state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
callContext) and
localFlowExit(node2, state2, config)
}
}
@@ -2769,10 +2695,10 @@ private module Stage4 {
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(

View File

@@ -87,30 +87,12 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
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. */
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. */
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
* into account in the analysis.
@@ -323,7 +305,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -332,16 +314,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
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]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -381,19 +345,9 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
pragma[nomagic]
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)
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`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -476,8 +430,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) 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(node2, s2, config)
)
@@ -519,8 +471,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) 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(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -920,8 +870,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1016,8 +966,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1038,8 +988,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
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
* 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
(
sourceNode(node, state, config)
or
jumpStep(_, node, config)
or
additionalJumpStep(_, node, config)
or
additionalJumpStateStep(_, _, node, state, config)
or
node instanceof ParamNodeEx
or
node.asNode() instanceof OutNodeExt
or
store(_, _, node, _, config)
or
read(_, _, node, config)
or
sourceNode(node, state, config) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
additionalJumpStateStep(_, _, node, state, config) or
node instanceof ParamNodeEx or
node.asNode() instanceof OutNodeExt or
store(_, _, node, _, config) or
read(_, _, node, config) or
node instanceof FlowCheckNode
or
exists(FlowState s |
additionalLocalStateStep(_, s, node, state, config) and
s != state
)
)
}
@@ -1800,9 +1737,6 @@ private module LocalFlowBigStep {
or
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
additionalJumpStateStep(node, state, next, s, config)
or
additionalLocalStateStep(node, state, next, s, config) and
s != state
)
or
Stage2::revFlow(node, state, config) and
@@ -1836,40 +1770,42 @@ private module LocalFlowBigStep {
*/
pragma[nomagic]
private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
Configuration config, LocalCallContext cc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, Configuration config, LocalCallContext cc
) {
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
state1 = state2 and
preservesValue = true and
t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config))
t = node1.getDataFlowType() // irrelevant dummy value
or
additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
preservesValue = false and
t = node2.getDataFlowType()
) and
node1 != node2 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
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
localFlowStepNodeCand1(mid, node2, config) 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
exists(NodeEx mid |
localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and
exists(NodeEx mid, FlowState st |
localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode 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,
AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) {
localFlowStepPlus(node1, state1, node2, preservesValue, apf.getType(), config, callContext) and
localFlowExit(node2, state1, config) and
state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
state1 != state2 and
preservesValue = false and
apf = TFrontNil(node2.getDataFlowType()) and
callContext.relevantFor(node1.getEnclosingCallable()) and
not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() |
isUnreachableInCallCached(node1.asNode(), call) or
isUnreachableInCallCached(node2.asNode(), call)
)
localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
callContext) and
localFlowExit(node2, state2, config)
}
}
@@ -2769,10 +2695,10 @@ private module Stage4 {
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
localFlowEntry(node, _, config) and
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(

View File

@@ -431,7 +431,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
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 }
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`.
*/

View File

@@ -64,30 +64,13 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() }
/**
* Holds if `source` is a relevant taint source with the given initial
* `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
/**
* Holds if `sink` is a relevant taint sink
* Holds if `sink` is a relevant taint sink.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
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. */
predicate isSanitizer(DataFlow::Node node) { none() }
@@ -96,29 +79,9 @@ abstract class Configuration extends DataFlow::Configuration {
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. */
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) }
/** 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) }
/**
* 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. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
@@ -143,16 +96,6 @@ abstract class Configuration extends DataFlow::Configuration {
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`
* must be taken into account in the analysis.
@@ -164,25 +107,6 @@ abstract class Configuration extends DataFlow::Configuration {
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) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
defaultImplicitTaintRead(node, c)

View File

@@ -64,30 +64,13 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() }
/**
* Holds if `source` is a relevant taint source with the given initial
* `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
/**
* Holds if `sink` is a relevant taint sink
* Holds if `sink` is a relevant taint sink.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
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. */
predicate isSanitizer(DataFlow::Node node) { none() }
@@ -96,29 +79,9 @@ abstract class Configuration extends DataFlow::Configuration {
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. */
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) }
/** 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) }
/**
* 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. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
@@ -143,16 +96,6 @@ abstract class Configuration extends DataFlow::Configuration {
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`
* must be taken into account in the analysis.
@@ -164,25 +107,6 @@ abstract class Configuration extends DataFlow::Configuration {
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) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
defaultImplicitTaintRead(node, c)

View File

@@ -64,30 +64,13 @@ abstract class Configuration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node source) { none() }
/**
* Holds if `source` is a relevant taint source with the given initial
* `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
/**
* Holds if `sink` is a relevant taint sink
* Holds if `sink` is a relevant taint sink.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
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. */
predicate isSanitizer(DataFlow::Node node) { none() }
@@ -96,29 +79,9 @@ abstract class Configuration extends DataFlow::Configuration {
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. */
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) }
/** 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) }
/**
* 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. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
@@ -143,16 +96,6 @@ abstract class Configuration extends DataFlow::Configuration {
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`
* must be taken into account in the analysis.
@@ -164,25 +107,6 @@ abstract class Configuration extends DataFlow::Configuration {
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) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
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
* variable as part of the AST-to-IR translation.
*/
Language::AST getAst() { none() }
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = getAst() }
Language::AST getAST() { none() }
/**
* 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.
*/
final Language::Location getLocation() { result = getAst().getLocation() }
final Language::Location getLocation() { result = getAST().getLocation() }
/**
* 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 Language::AST getAst() { result = var }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = getAst() }
final override Language::AST getAST() { result = var }
final override string getUniqueId() {
result = getVariable().toString() + " " + getVariable().getLocation().toString()
@@ -163,10 +157,7 @@ class IRGeneratedVariable extends IRVariable {
final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = getAst() }
final override Language::AST getAST() { result = ast }
override string toString() { result = getBaseString() + getLocationString() }

View File

@@ -41,7 +41,7 @@ class Instruction extends Construction::TStageInstruction {
}
/** 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
@@ -136,7 +136,7 @@ class Instruction extends Construction::TStageInstruction {
string getResultId() {
this.shouldGenerateDumpStrings() and
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.
*/
final Language::AST getAst() { result = Construction::getInstructionAst(this) }
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
final Language::AST getAST() { result = Construction::getInstructionAST(this) }
/**
* 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
@@ -462,10 +459,7 @@ class VariableInstruction extends Instruction {
/**
* Gets the AST variable that this instruction's IR variable refers to, if one exists.
*/
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
/** DEPRECATED: Alias for getAstVariable */
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
final Language::Variable getASTVariable() { result = var.(IRUserVariable).getVariable() }
}
/**

View File

@@ -18,7 +18,7 @@ private import internal.OperandInternal
* of `TOperand` that are used in this stage.
*/
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
@@ -38,7 +38,7 @@ class Operand extends TStageOperand {
// 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))
or
exists(Instruction use | this = nonSsaMemoryOperand(use, _))
exists(Instruction use | this = nonSSAMemoryOperand(use, _))
or
exists(Instruction use, Instruction def, IRBlock predecessorBlock |
this = phiOperand(use, def, predecessorBlock, _) or
@@ -209,7 +209,7 @@ class Operand extends TStageOperand {
class MemoryOperand extends Operand {
cached
MemoryOperand() {
this instanceof TNonSsaMemoryOperand or
this instanceof TNonSSAMemoryOperand or
this instanceof TPhiOperand or
this instanceof TChiOperand
}
@@ -249,7 +249,7 @@ class NonPhiOperand extends Operand {
NonPhiOperand() {
this = registerOperand(useInstr, tag, _) or
this = nonSsaMemoryOperand(useInstr, tag) or
this = nonSSAMemoryOperand(useInstr, tag) or
this = chiOperand(useInstr, tag)
}
@@ -299,7 +299,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
cached
NonPhiMemoryOperand() {
this = nonSsaMemoryOperand(useInstr, tag)
this = nonSSAMemoryOperand(useInstr, tag)
or
this = chiOperand(useInstr, tag)
}

View File

@@ -99,7 +99,7 @@ private predicate filteredNumberableInstruction(Instruction instr) {
// count rather than strictcount to handle missing AST elements
// separate instanceof and inline casts to avoid failed casts with a count of 0
instr instanceof VariableAddressInstruction and
count(instr.(VariableAddressInstruction).getIRVariable().getAst()) != 1
count(instr.(VariableAddressInstruction).getIRVariable().getAST()) != 1
or
instr instanceof ConstantInstruction and
count(instr.getResultIRType()) != 1
@@ -121,7 +121,7 @@ private predicate variableAddressValueNumber(
// 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
// multiple types gives rise to multiple `IRVariable`s.
unique( | | instr.getIRVariable().getAst()) = ast
unique( | | instr.getIRVariable().getAST()) = ast
}
private predicate initializeParameterValueNumber(
@@ -131,7 +131,7 @@ private predicate initializeParameterValueNumber(
// 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
// multiple types gives rise to multiple `IRVariable`s.
instr.getIRVariable().getAst() = var
instr.getIRVariable().getAST() = var
}
private predicate constantValueNumber(

View File

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

View File

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

View File

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

View File

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

View File

@@ -112,7 +112,7 @@ private module Cached {
exists(Alias::getResultMemoryLocation(oldInstruction))
or
// This result was already modeled by a previous iteration of SSA.
Alias::canReuseSsaForOldResult(oldInstruction)
Alias::canReuseSSAForOldResult(oldInstruction)
}
cached
@@ -182,7 +182,7 @@ private module Cached {
* unreachable, this predicate will recurse through any degenerate `Phi` instructions to find the
* true definition.
*/
private Instruction getNewDefinitionFromOldSsa(OldIR::MemoryOperand oldOperand, Overlap overlap) {
private Instruction getNewDefinitionFromOldSSA(OldIR::MemoryOperand oldOperand, Overlap overlap) {
exists(Overlap originalOverlap |
originalOverlap = oldOperand.getDefinitionOverlap() and
(
@@ -191,7 +191,7 @@ private module Cached {
or
exists(OldIR::PhiInputOperand phiOperand, Overlap phiOperandOverlap |
phiOperand = getDegeneratePhiOperand(oldOperand.getAnyDef()) and
result = getNewDefinitionFromOldSsa(phiOperand, phiOperandOverlap) and
result = getNewDefinitionFromOldSSA(phiOperand, phiOperandOverlap) and
overlap =
combineOverlap(pragma[only_bind_out](phiOperandOverlap),
pragma[only_bind_out](originalOverlap))
@@ -233,7 +233,7 @@ private module Cached {
)
or
exists(OldIR::NonPhiMemoryOperand oldOperand |
result = getNewDefinitionFromOldSsa(oldOperand, overlap) and
result = getNewDefinitionFromOldSSA(oldOperand, overlap) and
oldOperand.getUse() = instruction and
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
* `newPredecessorBlock`, based on that operand's definition in the old IR.
*/
private Instruction getNewPhiOperandDefinitionFromOldSsa(
private Instruction getNewPhiOperandDefinitionFromOldSSA(
Instruction instr, IRBlock newPredecessorBlock, Overlap overlap
) {
exists(OldIR::PhiInstruction oldPhi, OldIR::PhiInputOperand oldOperand |
oldPhi = getOldInstruction(instr) 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)
)
or
result = getNewPhiOperandDefinitionFromOldSsa(instr, newPredecessorBlock, overlap)
result = getNewPhiOperandDefinitionFromOldSSA(instr, newPredecessorBlock, overlap)
}
cached
@@ -412,17 +412,17 @@ private module Cached {
}
cached
Language::AST getInstructionAst(Instruction instr) {
result = getOldInstruction(instr).getAst()
Language::AST getInstructionAST(Instruction instr) {
result = getOldInstruction(instr).getAST()
or
exists(RawIR::Instruction blockStartInstr |
instr = phiInstruction(blockStartInstr, _) and
result = blockStartInstr.getAst()
result = blockStartInstr.getAST()
)
or
exists(RawIR::Instruction primaryInstr |
instr = chiInstruction(primaryInstr) and
result = primaryInstr.getAst()
result = primaryInstr.getAST()
)
or
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
Language::LanguageType getInstructionResultType(Instruction instr) {
result = instr.(RawIR::Instruction).getResultLanguageType()
@@ -981,41 +975,35 @@ module DefUse {
}
}
predicate canReuseSsaForMemoryResult(Instruction instruction) {
predicate canReuseSSAForMemoryResult(Instruction instruction) {
exists(OldInstruction oldInstruction |
oldInstruction = getOldInstruction(instruction) and
(
// The previous iteration said it was reusable, so we should mark it as reusable as well.
Alias::canReuseSsaForOldResult(oldInstruction)
Alias::canReuseSSAForOldResult(oldInstruction)
or
// The current alias analysis says it is reusable.
Alias::getResultMemoryLocation(oldInstruction).canReuseSsa()
Alias::getResultMemoryLocation(oldInstruction).canReuseSSA()
)
)
or
exists(Alias::MemoryLocation defLocation |
// This is a `Phi` for a reusable location, so the result of the `Phi` is reusable as well.
instruction = phiInstruction(_, defLocation) and
defLocation.canReuseSsa()
defLocation.canReuseSSA()
)
// 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
* `DebugSSA` module, which is then imported by PrintSSA.
*/
module DebugSsa {
module DebugSSA {
import PhiInsertion
import DefUse
}
/** DEPRECATED: Alias for DebugSsa */
deprecated module DebugSSA = DebugSsa;
import CachedForDebugging
cached
@@ -1050,7 +1038,7 @@ private module CachedForDebugging {
private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) {
result.getEnclosingFunction() = var.getEnclosingFunction() and
result.getAst() = var.getAst() and
result.getAST() = var.getAST() and
result.getTag() = var.getTag()
}
@@ -1073,7 +1061,7 @@ private module CachedForDebugging {
int maxValue() { result = 2147483647 }
}
module SsaConsistency {
module SSAConsistency {
/**
* 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
* 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.Dominance as Dominance
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 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)
} or
TUnaliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation
TUnaliasedSSAPhiInstruction(
TRawInstruction blockStartInstr, UnaliasedSSA::SSA::MemoryLocation memoryLocation
) {
UnaliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
UnaliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
} or
TUnaliasedSsaChiInstruction(TRawInstruction primaryInstruction) { none() } or
TUnaliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
UnaliasedSsa::SSA::hasUnreachedInstruction(irFunc)
TUnaliasedSSAChiInstruction(TRawInstruction primaryInstruction) { none() } or
TUnaliasedSSAUnreachedInstruction(IRFunctionBase irFunc) {
UnaliasedSSA::SSA::hasUnreachedInstruction(irFunc)
} or
TAliasedSsaPhiInstruction(
TAliasedSSAPhiInstruction(
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
) {
AliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
} or
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
TAliasedSSAChiInstruction(TRawInstruction primaryInstruction) {
AliasedSSA::SSA::hasChiInstruction(primaryInstruction)
} or
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
TAliasedSSAUnreachedInstruction(IRFunctionBase 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
* a class alias.
*/
module UnaliasedSsaInstructions {
class TPhiInstruction = TUnaliasedSsaPhiInstruction;
module UnaliasedSSAInstructions {
class TPhiInstruction = TUnaliasedSSAPhiInstruction;
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() }
class TChiInstruction = TUnaliasedSsaChiInstruction;
class TChiInstruction = TUnaliasedSSAChiInstruction;
TChiInstruction chiInstruction(TRawInstruction primaryInstruction) {
result = TUnaliasedSsaChiInstruction(primaryInstruction)
result = TUnaliasedSSAChiInstruction(primaryInstruction)
}
class TUnreachedInstruction = TUnaliasedSsaUnreachedInstruction;
class TUnreachedInstruction = TUnaliasedSSAUnreachedInstruction;
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
* aliased SSA stage.
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
* a class alias.
*/
module AliasedSsaInstructions {
class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction;
module AliasedSSAInstructions {
class TPhiInstruction = TAliasedSSAPhiInstruction or TUnaliasedSSAPhiInstruction;
TPhiInstruction phiInstruction(
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
) {
result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
result = TAliasedSSAPhiInstruction(blockStartInstr, memoryLocation)
}
TPhiInstruction reusedPhiInstruction(TRawInstruction blockStartInstr) {
result = TUnaliasedSsaPhiInstruction(blockStartInstr, _)
result = TUnaliasedSSAPhiInstruction(blockStartInstr, _)
}
class TChiInstruction = TAliasedSsaChiInstruction;
class TChiInstruction = TAliasedSSAChiInstruction;
TChiInstruction chiInstruction(TRawInstruction primaryInstruction) {
result = TAliasedSsaChiInstruction(primaryInstruction)
result = TAliasedSSAChiInstruction(primaryInstruction)
}
class TUnreachedInstruction = TAliasedSsaUnreachedInstruction;
class TUnreachedInstruction = TAliasedSSAUnreachedInstruction;
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.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

View File

@@ -31,7 +31,7 @@ private module Internal {
TNoOperand() { none() } or
// Can be "removed" later when there's unreachable code
// 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
useInstr.getOpcode().hasOperand(tag)
} or
@@ -49,11 +49,11 @@ private module Internal {
// important that we use the same definition of "is variable aliased" across
// the phases.
TAliasedPhiOperand(
TAliasedSsaPhiInstruction useInstr, Aliased::IRBlock predecessorBlock, Overlap overlap
TAliasedSSAPhiInstruction useInstr, Aliased::IRBlock predecessorBlock, Overlap overlap
) {
exists(AliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap))
} 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)
}
class TNonSsaMemoryOperand = Internal::TNonSsaMemoryOperand;
/** DEPRECATED: Alias for TNonSsaMemoryOperand */
deprecated class TNonSSAMemoryOperand = TNonSsaMemoryOperand;
class TNonSSAMemoryOperand = Internal::TNonSSAMemoryOperand;
/**
* Returns the non-Phi memory operand with the specified parameters.
*/
TNonSsaMemoryOperand nonSsaMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) {
result = Internal::TNonSsaMemoryOperand(useInstr, tag)
}
/** DEPRECATED: Alias for nonSsaMemoryOperand */
deprecated TNonSSAMemoryOperand nonSSAMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) {
result = nonSsaMemoryOperand(useInstr, tag)
TNonSSAMemoryOperand nonSSAMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) {
result = Internal::TNonSSAMemoryOperand(useInstr, tag)
}
}
@@ -103,7 +95,7 @@ module RawOperands {
class TChiOperand = Internal::TNoOperand;
class TNonPhiMemoryOperand = TNonSsaMemoryOperand or TChiOperand;
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand;
/**
* 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
* a class alias.
*/
module UnaliasedSsaOperands {
module UnaliasedSSAOperands {
import Shared
class TPhiOperand = Internal::TUnaliasedPhiOperand;
class TChiOperand = Internal::TNoOperand;
class TNonPhiMemoryOperand = TNonSsaMemoryOperand or TChiOperand;
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand;
/**
* Returns the Phi operand with the specified parameters.
@@ -167,23 +159,20 @@ module UnaliasedSsaOperands {
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
* asliased SSA stage.
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
* a class alias.
*/
module AliasedSsaOperands {
module AliasedSSAOperands {
import Shared
class TPhiOperand = Internal::TAliasedPhiOperand or Internal::TUnaliasedPhiOperand;
class TChiOperand = Internal::TAliasedChiOperand;
class TNonPhiMemoryOperand = TNonSsaMemoryOperand or TChiOperand;
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand;
/**
* Returns the Phi operand with the specified parameters.
@@ -213,10 +202,7 @@ module AliasedSsaOperands {
/**
* 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)
}
}
/** 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
* variable as part of the AST-to-IR translation.
*/
Language::AST getAst() { none() }
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = getAst() }
Language::AST getAST() { none() }
/**
* 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.
*/
final Language::Location getLocation() { result = getAst().getLocation() }
final Language::Location getLocation() { result = getAST().getLocation() }
/**
* 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 Language::AST getAst() { result = var }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = getAst() }
final override Language::AST getAST() { result = var }
final override string getUniqueId() {
result = getVariable().toString() + " " + getVariable().getLocation().toString()
@@ -163,10 +157,7 @@ class IRGeneratedVariable extends IRVariable {
final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = getAst() }
final override Language::AST getAST() { result = ast }
override string toString() { result = getBaseString() + getLocationString() }

View File

@@ -41,7 +41,7 @@ class Instruction extends Construction::TStageInstruction {
}
/** 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
@@ -136,7 +136,7 @@ class Instruction extends Construction::TStageInstruction {
string getResultId() {
this.shouldGenerateDumpStrings() and
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.
*/
final Language::AST getAst() { result = Construction::getInstructionAst(this) }
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
final Language::AST getAST() { result = Construction::getInstructionAST(this) }
/**
* 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
@@ -462,10 +459,7 @@ class VariableInstruction extends Instruction {
/**
* Gets the AST variable that this instruction's IR variable refers to, if one exists.
*/
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
/** DEPRECATED: Alias for getAstVariable */
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
final Language::Variable getASTVariable() { result = var.(IRUserVariable).getVariable() }
}
/**

View File

@@ -18,7 +18,7 @@ private import internal.OperandInternal
* of `TOperand` that are used in this stage.
*/
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
@@ -38,7 +38,7 @@ class Operand extends TStageOperand {
// 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))
or
exists(Instruction use | this = nonSsaMemoryOperand(use, _))
exists(Instruction use | this = nonSSAMemoryOperand(use, _))
or
exists(Instruction use, Instruction def, IRBlock predecessorBlock |
this = phiOperand(use, def, predecessorBlock, _) or
@@ -209,7 +209,7 @@ class Operand extends TStageOperand {
class MemoryOperand extends Operand {
cached
MemoryOperand() {
this instanceof TNonSsaMemoryOperand or
this instanceof TNonSSAMemoryOperand or
this instanceof TPhiOperand or
this instanceof TChiOperand
}
@@ -249,7 +249,7 @@ class NonPhiOperand extends Operand {
NonPhiOperand() {
this = registerOperand(useInstr, tag, _) or
this = nonSsaMemoryOperand(useInstr, tag) or
this = nonSSAMemoryOperand(useInstr, tag) or
this = chiOperand(useInstr, tag)
}
@@ -299,7 +299,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
cached
NonPhiMemoryOperand() {
this = nonSsaMemoryOperand(useInstr, tag)
this = nonSSAMemoryOperand(useInstr, tag)
or
this = chiOperand(useInstr, tag)
}

View File

@@ -99,7 +99,7 @@ private predicate filteredNumberableInstruction(Instruction instr) {
// count rather than strictcount to handle missing AST elements
// separate instanceof and inline casts to avoid failed casts with a count of 0
instr instanceof VariableAddressInstruction and
count(instr.(VariableAddressInstruction).getIRVariable().getAst()) != 1
count(instr.(VariableAddressInstruction).getIRVariable().getAST()) != 1
or
instr instanceof ConstantInstruction and
count(instr.getResultIRType()) != 1
@@ -121,7 +121,7 @@ private predicate variableAddressValueNumber(
// 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
// multiple types gives rise to multiple `IRVariable`s.
unique( | | instr.getIRVariable().getAst()) = ast
unique( | | instr.getIRVariable().getAST()) = ast
}
private predicate initializeParameterValueNumber(
@@ -131,7 +131,7 @@ private predicate initializeParameterValueNumber(
// 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
// multiple types gives rise to multiple `IRVariable`s.
instr.getIRVariable().getAst() = var
instr.getIRVariable().getAST() = var
}
private predicate constantValueNumber(

View File

@@ -48,7 +48,7 @@ module Raw {
cached
predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, CppType type) {
exists(TranslatedElement element |
element.getAst() = ast and
element.getAST() = ast and
func = element.getFunction() and
element.hasTempVariable(tag, type)
)
@@ -75,7 +75,7 @@ module Raw {
tag = getInstructionTag(instruction) and
(
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.
exists(TranslatedElement s, GotoStmt goto |
not isStrictlyForwardGoto(goto) and
goto = s.getAst() and
goto = s.getAST() and
exists(InstructionTag tag |
result = s.getInstructionSuccessor(tag, kind) and
instruction = s.getInstruction(tag)
@@ -352,13 +352,8 @@ private predicate isStrictlyForwardGoto(GotoStmt goto) {
goto.getLocation().isBefore(goto.getTarget().getLocation())
}
Locatable getInstructionAst(TStageInstruction instr) {
result = getInstructionTranslatedElement(instr).getAst()
}
/** DEPRECATED: Alias for getInstructionAst */
deprecated Locatable getInstructionAST(TStageInstruction instr) {
result = getInstructionAst(instr)
Locatable getInstructionAST(TStageInstruction instr) {
result = getInstructionTranslatedElement(instr).getAST()
}
CppType getInstructionResultType(TStageInstruction instr) {

View File

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

View File

@@ -14,7 +14,7 @@ private import TranslatedInitialization
* `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 Locatable getAst() { result = entry }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Locatable getAST() { result = entry }
}
/**
@@ -226,10 +223,7 @@ class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
final override string toString() { result = "init: " + entry.toString() }
final override Locatable getAst() { result = entry }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Locatable getAST() { result = entry }
final override LocalVariable getVariable() { result = var }
@@ -260,10 +254,7 @@ class TranslatedRangeBasedForVariableDeclaration extends TranslatedLocalVariable
override string toString() { result = var.toString() }
override Locatable getAst() { result = var }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Locatable getAST() { result = var }
override Function getFunction() { result = forStmt.getEnclosingFunction() }
@@ -271,7 +262,7 @@ class TranslatedRangeBasedForVariableDeclaration extends TranslatedLocalVariable
}
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 Locatable getAst() { result = conditionDeclExpr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Locatable getAST() { result = conditionDeclExpr }
override Function getFunction() { result = conditionDeclExpr.getEnclosingFunction() }

View File

@@ -31,7 +31,7 @@ IRUserVariable getIRUserVariable(Function func, Variable var) {
}
IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
result.getAst() = ast and
result.getAST() = ast and
result.getTag() = tag
}
@@ -730,10 +730,7 @@ abstract class TranslatedElement extends TTranslatedElement {
/**
* Gets the AST node being translated.
*/
abstract Locatable getAst();
/** DEPRECATED: Alias for getAst */
deprecated Locatable getAST() { result = getAst() }
abstract Locatable getAST();
/**
* 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) {
exists(Locatable ast |
result.getAst() = ast and
result.getAST() = ast and
result.getTag() = tag and
hasTempVariableAndAst(tag, ast)
hasTempVariableAndAST(tag, ast)
)
}
pragma[noinline]
private predicate hasTempVariableAndAst(TempVariableTag tag, Locatable ast) {
private predicate hasTempVariableAndAST(TempVariableTag tag, Locatable ast) {
hasTempVariable(tag, _) and
ast = getAst()
ast = getAST()
}
/**

View File

@@ -74,10 +74,7 @@ abstract class TranslatedExpr extends TranslatedElement {
expr.isGLValueCategory()
}
final override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Locatable getAST() { result = expr }
final override Function getFunction() { result = expr.getEnclosingFunction() }
@@ -1712,7 +1709,7 @@ abstract class TranslatedAllocationSize extends TranslatedExpr, TTranslatedAlloc
}
TranslatedAllocationSize getTranslatedAllocationSize(NewOrNewArrayExpr newExpr) {
result.getAst() = newExpr
result.getAST() = newExpr
}
/**
@@ -1878,7 +1875,7 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect
}
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`.
*/
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
@@ -65,10 +65,7 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
final override string toString() { result = func.toString() }
final override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Locatable getAST() { result = func }
/**
* Gets the function being translated.
@@ -347,7 +344,7 @@ TranslatedThisParameter getTranslatedThisParameter(Function func) { result.getFu
/**
* 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.
@@ -460,10 +457,7 @@ class TranslatedThisParameter extends TranslatedParameter, TTranslatedThisParame
final override string toString() { result = "this" }
final override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Locatable getAST() { 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 Locatable getAst() { result = param }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Locatable getAST() { result = param }
final override Function getFunction() {
result = param.getFunction() or
@@ -535,10 +526,7 @@ class TranslatedEllipsisParameter extends TranslatedParameter, TTranslatedEllips
final override string toString() { result = "..." }
final override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Locatable getAST() { result = func }
final override Function getFunction() { result = func }
@@ -556,7 +544,7 @@ class TranslatedEllipsisParameter extends TranslatedParameter, TTranslatedEllips
}
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 Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Locatable getAST() { result = func }
override TranslatedElement getChild(int id) {
exists(ConstructorFieldInit fieldInit |
@@ -626,7 +611,7 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
}
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 Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Locatable getAST() { result = func }
override TranslatedElement getChild(int id) {
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 {
Function func;
TranslatedReadEffects() { this = TTranslatedReadEffects(func) }
override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Locatable getAST() { result = func }
override Function getFunction() { result = func }
@@ -739,11 +718,11 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
}
private TranslatedThisReadEffect getTranslatedThisReadEffect(Function func) {
result.getAst() = func
result.getAST() = func
}
private TranslatedParameterReadEffect getTranslatedParameterReadEffect(Parameter param) {
result.getAst() = param
result.getAST() = param
}
abstract class TranslatedReadEffect extends TranslatedElement {
@@ -779,10 +758,7 @@ class TranslatedThisReadEffect extends TranslatedReadEffect, TTranslatedThisRead
TranslatedThisReadEffect() { this = TTranslatedThisReadEffect(func) }
override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Locatable getAST() { result = func }
override Function getFunction() { result = func }
@@ -805,10 +781,7 @@ class TranslatedParameterReadEffect extends TranslatedReadEffect, TTranslatedPar
TranslatedParameterReadEffect() { this = TTranslatedParameterReadEffect(param) }
override Locatable getAst() { result = param }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Locatable getAST() { result = param }
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 Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Locatable getAST() { result = expr }
/**
* Gets the expression that is doing the initialization.
@@ -464,11 +461,11 @@ class TranslatedConstructorInitialization extends TranslatedDirectInitialization
TranslatedFieldInitialization getTranslatedFieldInitialization(
ClassAggregateLiteral initList, Field field
) {
result.getAst() = initList and result.getField() = field
result.getAST() = initList and result.getField() = field
}
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 Locatable getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Locatable getAST() { result = ast }
final override Function getFunction() { result = ast.getEnclosingFunction() }
@@ -628,10 +622,7 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
result = initList.toString() + "[" + getElementIndex().toString() + "]"
}
final override Locatable getAst() { result = initList }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Locatable getAST() { result = initList }
final override Function getFunction() { result = initList.getEnclosingFunction() }
@@ -811,10 +802,7 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
abstract class TranslatedStructorCallFromStructor extends TranslatedElement, StructorCallContext {
FunctionCall call;
final override Locatable getAst() { result = call }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
final override Locatable getAST() { result = call }
final override TranslatedElement getChild(int id) {
id = 0 and
@@ -876,7 +864,7 @@ abstract class TranslatedConstructorCallFromConstructor extends TranslatedStruct
}
TranslatedConstructorCallFromConstructor getTranslatedConstructorBaseInit(ConstructorBaseInit init) {
result.getAst() = init
result.getAST() = init
}
/**
@@ -916,7 +904,7 @@ class TranslatedConstructorBaseInit extends TranslatedConstructorCallFromConstru
TranslatedDestructorBaseDestruction getTranslatedDestructorBaseDestruction(
DestructorBaseDestruction destruction
) {
result.getAst() = destruction
result.getAST() = destruction
}
/**
@@ -940,10 +928,7 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
TranslatedConstructorBareInit() { this = TTranslatedConstructorBareInit(init) }
override Locatable getAst() { result = init }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = getAst() }
override Locatable getAST() { result = init }
final override string toString() { result = "construct base (no constructor)" }
@@ -963,5 +948,5 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
}
TranslatedConstructorBareInit getTranslatedConstructorBareInit(ConstructorInit init) {
result.getAst() = init
result.getAST() = init
}

View File

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

View File

@@ -1,5 +1,7 @@
private import ReachableBlock as Reachability
private module ReachabilityGraph = Reachability::Graph;
module 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
* variable as part of the AST-to-IR translation.
*/
Language::AST getAst() { none() }
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = getAst() }
Language::AST getAST() { none() }
/**
* 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.
*/
final Language::Location getLocation() { result = getAst().getLocation() }
final Language::Location getLocation() { result = getAST().getLocation() }
/**
* 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 Language::AST getAst() { result = var }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = getAst() }
final override Language::AST getAST() { result = var }
final override string getUniqueId() {
result = getVariable().toString() + " " + getVariable().getLocation().toString()
@@ -163,10 +157,7 @@ class IRGeneratedVariable extends IRVariable {
final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = getAst() }
final override Language::AST getAST() { result = ast }
override string toString() { result = getBaseString() + getLocationString() }

View File

@@ -41,7 +41,7 @@ class Instruction extends Construction::TStageInstruction {
}
/** 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
@@ -136,7 +136,7 @@ class Instruction extends Construction::TStageInstruction {
string getResultId() {
this.shouldGenerateDumpStrings() and
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.
*/
final Language::AST getAst() { result = Construction::getInstructionAst(this) }
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
final Language::AST getAST() { result = Construction::getInstructionAST(this) }
/**
* 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
@@ -462,10 +459,7 @@ class VariableInstruction extends Instruction {
/**
* Gets the AST variable that this instruction's IR variable refers to, if one exists.
*/
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
/** DEPRECATED: Alias for getAstVariable */
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
final Language::Variable getASTVariable() { result = var.(IRUserVariable).getVariable() }
}
/**

View File

@@ -18,7 +18,7 @@ private import internal.OperandInternal
* of `TOperand` that are used in this stage.
*/
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
@@ -38,7 +38,7 @@ class Operand extends TStageOperand {
// 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))
or
exists(Instruction use | this = nonSsaMemoryOperand(use, _))
exists(Instruction use | this = nonSSAMemoryOperand(use, _))
or
exists(Instruction use, Instruction def, IRBlock predecessorBlock |
this = phiOperand(use, def, predecessorBlock, _) or
@@ -209,7 +209,7 @@ class Operand extends TStageOperand {
class MemoryOperand extends Operand {
cached
MemoryOperand() {
this instanceof TNonSsaMemoryOperand or
this instanceof TNonSSAMemoryOperand or
this instanceof TPhiOperand or
this instanceof TChiOperand
}
@@ -249,7 +249,7 @@ class NonPhiOperand extends Operand {
NonPhiOperand() {
this = registerOperand(useInstr, tag, _) or
this = nonSsaMemoryOperand(useInstr, tag) or
this = nonSSAMemoryOperand(useInstr, tag) or
this = chiOperand(useInstr, tag)
}
@@ -299,7 +299,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
cached
NonPhiMemoryOperand() {
this = nonSsaMemoryOperand(useInstr, tag)
this = nonSSAMemoryOperand(useInstr, tag)
or
this = chiOperand(useInstr, tag)
}

View File

@@ -99,7 +99,7 @@ private predicate filteredNumberableInstruction(Instruction instr) {
// count rather than strictcount to handle missing AST elements
// separate instanceof and inline casts to avoid failed casts with a count of 0
instr instanceof VariableAddressInstruction and
count(instr.(VariableAddressInstruction).getIRVariable().getAst()) != 1
count(instr.(VariableAddressInstruction).getIRVariable().getAST()) != 1
or
instr instanceof ConstantInstruction and
count(instr.getResultIRType()) != 1
@@ -121,7 +121,7 @@ private predicate variableAddressValueNumber(
// 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
// multiple types gives rise to multiple `IRVariable`s.
unique( | | instr.getIRVariable().getAst()) = ast
unique( | | instr.getIRVariable().getAST()) = ast
}
private predicate initializeParameterValueNumber(
@@ -131,7 +131,7 @@ private predicate initializeParameterValueNumber(
// 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
// multiple types gives rise to multiple `IRVariable`s.
instr.getIRVariable().getAst() = var
instr.getIRVariable().getAST() = var
}
private predicate constantValueNumber(

View File

@@ -1,2 +1,2 @@
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 Alias
private import SSAConstruction
private import DebugSsa
private import DebugSSA
bindingset[offset]
private string getKeySuffixForOffset(int offset) {

View File

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

View File

@@ -112,7 +112,7 @@ private module Cached {
exists(Alias::getResultMemoryLocation(oldInstruction))
or
// This result was already modeled by a previous iteration of SSA.
Alias::canReuseSsaForOldResult(oldInstruction)
Alias::canReuseSSAForOldResult(oldInstruction)
}
cached
@@ -182,7 +182,7 @@ private module Cached {
* unreachable, this predicate will recurse through any degenerate `Phi` instructions to find the
* true definition.
*/
private Instruction getNewDefinitionFromOldSsa(OldIR::MemoryOperand oldOperand, Overlap overlap) {
private Instruction getNewDefinitionFromOldSSA(OldIR::MemoryOperand oldOperand, Overlap overlap) {
exists(Overlap originalOverlap |
originalOverlap = oldOperand.getDefinitionOverlap() and
(
@@ -191,7 +191,7 @@ private module Cached {
or
exists(OldIR::PhiInputOperand phiOperand, Overlap phiOperandOverlap |
phiOperand = getDegeneratePhiOperand(oldOperand.getAnyDef()) and
result = getNewDefinitionFromOldSsa(phiOperand, phiOperandOverlap) and
result = getNewDefinitionFromOldSSA(phiOperand, phiOperandOverlap) and
overlap =
combineOverlap(pragma[only_bind_out](phiOperandOverlap),
pragma[only_bind_out](originalOverlap))
@@ -233,7 +233,7 @@ private module Cached {
)
or
exists(OldIR::NonPhiMemoryOperand oldOperand |
result = getNewDefinitionFromOldSsa(oldOperand, overlap) and
result = getNewDefinitionFromOldSSA(oldOperand, overlap) and
oldOperand.getUse() = instruction and
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
* `newPredecessorBlock`, based on that operand's definition in the old IR.
*/
private Instruction getNewPhiOperandDefinitionFromOldSsa(
private Instruction getNewPhiOperandDefinitionFromOldSSA(
Instruction instr, IRBlock newPredecessorBlock, Overlap overlap
) {
exists(OldIR::PhiInstruction oldPhi, OldIR::PhiInputOperand oldOperand |
oldPhi = getOldInstruction(instr) 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)
)
or
result = getNewPhiOperandDefinitionFromOldSsa(instr, newPredecessorBlock, overlap)
result = getNewPhiOperandDefinitionFromOldSSA(instr, newPredecessorBlock, overlap)
}
cached
@@ -412,17 +412,17 @@ private module Cached {
}
cached
Language::AST getInstructionAst(Instruction instr) {
result = getOldInstruction(instr).getAst()
Language::AST getInstructionAST(Instruction instr) {
result = getOldInstruction(instr).getAST()
or
exists(RawIR::Instruction blockStartInstr |
instr = phiInstruction(blockStartInstr, _) and
result = blockStartInstr.getAst()
result = blockStartInstr.getAST()
)
or
exists(RawIR::Instruction primaryInstr |
instr = chiInstruction(primaryInstr) and
result = primaryInstr.getAst()
result = primaryInstr.getAST()
)
or
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
Language::LanguageType getInstructionResultType(Instruction instr) {
result = instr.(RawIR::Instruction).getResultLanguageType()
@@ -981,41 +975,35 @@ module DefUse {
}
}
predicate canReuseSsaForMemoryResult(Instruction instruction) {
predicate canReuseSSAForMemoryResult(Instruction instruction) {
exists(OldInstruction oldInstruction |
oldInstruction = getOldInstruction(instruction) and
(
// The previous iteration said it was reusable, so we should mark it as reusable as well.
Alias::canReuseSsaForOldResult(oldInstruction)
Alias::canReuseSSAForOldResult(oldInstruction)
or
// The current alias analysis says it is reusable.
Alias::getResultMemoryLocation(oldInstruction).canReuseSsa()
Alias::getResultMemoryLocation(oldInstruction).canReuseSSA()
)
)
or
exists(Alias::MemoryLocation defLocation |
// This is a `Phi` for a reusable location, so the result of the `Phi` is reusable as well.
instruction = phiInstruction(_, defLocation) and
defLocation.canReuseSsa()
defLocation.canReuseSSA()
)
// 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
* `DebugSSA` module, which is then imported by PrintSSA.
*/
module DebugSsa {
module DebugSSA {
import PhiInsertion
import DefUse
}
/** DEPRECATED: Alias for DebugSsa */
deprecated module DebugSSA = DebugSsa;
import CachedForDebugging
cached
@@ -1050,7 +1038,7 @@ private module CachedForDebugging {
private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) {
result.getEnclosingFunction() = var.getEnclosingFunction() and
result.getAst() = var.getAst() and
result.getAST() = var.getAST() and
result.getTag() = var.getTag()
}
@@ -1073,7 +1061,7 @@ private module CachedForDebugging {
int maxValue() { result = 2147483647 }
}
module SsaConsistency {
module SSAConsistency {
/**
* 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
* 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.unaliased_ssa.IR as NewIR
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 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
* actually would have escaped if we had used a sound escape analysis.
*/
predicate canReuseSsaForVariable(IRAutomaticVariable var) {
predicate canReuseSSAForVariable(IRAutomaticVariable var) {
isVariableModeled(var) and
not allocationEscapes(var)
}
/** DEPRECATED: Alias for canReuseSsaForVariable */
deprecated predicate canReuseSSAForVariable = canReuseSsaForVariable/1;
private newtype TMemoryLocation = MkMemoryLocation(Allocation var) { isVariableModeled(var) }
private MemoryLocation getMemoryLocation(Allocation var) { result.getAllocation() = var }
@@ -72,16 +69,10 @@ class MemoryLocation extends TMemoryLocation {
final string getUniqueId() { result = var.getUniqueId() }
final predicate canReuseSsa() { canReuseSsaForVariable(var) }
/** DEPRECATED: Alias for canReuseSsa */
deprecated predicate canReuseSSA() { canReuseSsa() }
final predicate canReuseSSA() { canReuseSSAForVariable(var) }
}
predicate canReuseSsaForOldResult(Instruction instr) { none() }
/** DEPRECATED: Alias for canReuseSsaForOldResult */
deprecated predicate canReuseSSAForOldResult = canReuseSsaForOldResult/1;
predicate canReuseSSAForOldResult(Instruction instr) { none() }
/**
* Represents a set of `MemoryLocation`s that cannot overlap with

View File

@@ -1,5 +1,7 @@
private import ReachableBlock as Reachability
private module ReachabilityGraph = Reachability::Graph;
module 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.
* This class provides the range-analysis SSA logic.
*/
library class RangeSsa extends SsaHelper {
RangeSsa() { this = 1 }
library class RangeSSA extends SSAHelper {
RangeSSA() { this = 1 }
/**
* 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) {
guardCondition(guard, v, branch) and
guardSuccessor(guard, branch, b)
@@ -70,22 +67,22 @@ private predicate guardSuccessor(Expr guard, boolean branch, BasicBlock succ) {
* nodes.
*/
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
* 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
* `(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)`. */
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. */
ControlFlowNode getDefinition() { result = this }
@@ -94,7 +91,7 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
BasicBlock getBasicBlock() { result.contains(this.getDefinition()) }
/** 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
@@ -175,6 +172,6 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
* Holds if this definition of the variable `v` reached the end of the basic block `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
* side-effect.
*/
private predicate sideEffectCfg(ControlFlowNode src, ControlFlowNode dst) {
private predicate sideEffectCFG(ControlFlowNode src, ControlFlowNode dst) {
src.getASuccessor() = dst
or
// 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.
*/
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

View File

@@ -703,7 +703,7 @@ usertype_final(unique int id: @usertype ref);
usertype_uuid(
unique int id: @usertype ref,
string uuid: string ref
unique string uuid: string ref
);
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
### Deprecated Classes

View File

@@ -2,7 +2,7 @@
* @name Copy function using source size
* @description Calling a copy operation with a size derived from the source
* buffer instead of the destination buffer may result in a buffer overflow.
* @kind path-problem
* @kind problem
* @id cpp/overflow-destination
* @problem.severity warning
* @security-severity 9.3
@@ -14,10 +14,7 @@
*/
import cpp
import semmle.code.cpp.ir.dataflow.TaintTracking
import semmle.code.cpp.controlflow.IRGuards
import semmle.code.cpp.security.FlowSources
import DataFlow::PathGraph
import semmle.code.cpp.security.TaintTracking
/**
* 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
exists(Expr dest, Expr size, Variable v |
fc.getArgument(0) = dest and
fc.getArgument(1).getFullyConverted() = src and
fc.getArgument(1) = src and
fc.getArgument(2) = size and
src = v.getAnAccess().getFullyConverted() and
src = v.getAnAccess() and
size.getAChild+() = v.getAnAccess() and
// exception: `dest` is also referenced in the size argument
not exists(Variable other |
@@ -48,49 +45,9 @@ predicate sourceSized(FunctionCall fc, Expr src) {
)
}
predicate readsVariable(LoadInstruction load, Variable var) {
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
from FunctionCall fc, Expr vuln, Expr taintSource
where
conf.hasFlowPath(source, sink) and
sourceSized(fc, sink.getNode().asConvertedExpr())
select fc, source, sink,
sourceSized(fc, vuln) and
tainted(taintSource, vuln)
select fc,
"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 |
var = source.asInstruction() 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.
not var.getResultType() instanceof PointerToMemberType and
// Rule out FPs caused by extraction errors.
@@ -77,13 +77,12 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
from
MustFlowPathNode source, MustFlowPathNode sink, VariableAddressInstruction var,
ReturnStackAllocatedMemoryConfig conf, Function f
ReturnStackAllocatedMemoryConfig conf
where
conf.hasFlowPath(source, sink) and
source.getNode().asInstruction() = var and
// Only raise an alert if we're returning from the _same_ callable as the on that
// declared the stack variable.
var.getEnclosingFunction() = pragma[only_bind_into](f) and
sink.getNode().getEnclosingCallable() = pragma[only_bind_into](f)
select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAst(),
var.getAst().toString()
var.getEnclosingFunction() = sink.getNode().getEnclosingCallable()
select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAST(),
var.getAST().toString()

View File

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

View File

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

View File

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

View File

@@ -9,31 +9,28 @@ private import semmle.code.cpp.models.interfaces.Taint
import ExternalAPIsSpecific
/** A node representing untrusted data being passed to an external API. */
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
UntrustedExternalApiDataNode() { any(UntrustedDataToExternalApiConfig c).hasFlow(_, this) }
class UntrustedExternalAPIDataNode extends ExternalAPIDataNode {
UntrustedExternalAPIDataNode() { any(UntrustedDataToExternalAPIConfig c).hasFlow(_, this) }
/** Gets a source of untrusted data which is passed to this external API data node. */
DataFlow::Node getAnUntrustedSource() {
any(UntrustedDataToExternalApiConfig c).hasFlow(result, this)
any(UntrustedDataToExternalAPIConfig c).hasFlow(result, this)
}
}
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode;
private newtype TExternalApi =
TExternalApiParameter(Function f, int index) {
exists(UntrustedExternalApiDataNode n |
private newtype TExternalAPI =
TExternalAPIParameter(Function f, int index) {
exists(UntrustedExternalAPIDataNode n |
f = n.getExternalFunction() and
index = n.getIndex()
)
}
/** 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. */
UntrustedExternalApiDataNode getUntrustedDataNode() {
this = TExternalApiParameter(result.getExternalFunction(), result.getIndex())
UntrustedExternalAPIDataNode getUntrustedDataNode() {
this = TExternalAPIParameter(result.getExternalFunction(), result.getIndex())
}
/** 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 |
if index = -1 then indexString = "qualifier" else indexString = "param " + index
|
this = TExternalApiParameter(f, index) and
this = TExternalAPIParameter(f, index) and
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
/** A node representing untrusted data being passed to an external API. */
class ExternalApiDataNode extends DataFlow::Node {
class ExternalAPIDataNode extends DataFlow::Node {
Call call;
int i;
ExternalApiDataNode() {
ExternalAPIDataNode() {
// Argument to call to a function
(
this.asExpr() = call.getArgument(i)
@@ -27,7 +27,7 @@ class ExternalApiDataNode extends DataFlow::Node {
not f instanceof DataFlowFunction and
not f instanceof TaintFunction and
// 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() }
}
/** DEPRECATED: Alias for ExternalApiDataNode */
deprecated class ExternalAPIDataNode = ExternalApiDataNode;
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
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) {
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 ir.ExternalAPIs
from ExternalApiUsedWithUntrustedData externalApi
select externalApi, count(externalApi.getUntrustedDataNode()) as numberOfUses,
externalApi.getNumberOfUntrustedSources() as numberOfUntrustedSources order by
from ExternalAPIUsedWithUntrustedData externalAPI
select externalAPI, count(externalAPI.getUntrustedDataNode()) as numberOfUses,
externalAPI.getNumberOfUntrustedSources() as numberOfUntrustedSources order by
numberOfUntrustedSources desc

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