From d920fc7d94bf418b54739f48af89b1fca571f6df Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Fri, 24 Aug 2018 11:58:58 -0700 Subject: [PATCH] Force LF line endings for .ql, .qll, and .qlref files --- .gitattributes | 13 + cpp/ql/src/semmle/code/cpp/PrintAST.ql | 18 +- cpp/ql/src/semmle/code/cpp/PrintAST.qll | 1092 ++++----- cpp/ql/src/semmle/code/cpp/ir/EdgeKind.qll | 282 +-- cpp/ql/src/semmle/code/cpp/ir/IR.qll | 2 +- .../semmle/code/cpp/ir/MemoryAccessKind.qll | 108 +- cpp/ql/src/semmle/code/cpp/ir/Opcode.qll | 2 +- cpp/ql/src/semmle/code/cpp/ir/PrintIR.ql | 16 +- cpp/ql/src/semmle/code/cpp/ir/PrintIR.qll | 2 +- .../semmle/code/cpp/ir/TempVariableTag.qll | 16 +- .../src/semmle/code/cpp/ir/ValueCategory.qll | 88 +- .../code/cpp/ir/internal/FunctionIR.qll | 194 +- .../code/cpp/ir/internal/IRConstruction.qll | 330 +-- .../code/cpp/ir/internal/IRInternal.qll | 2 +- .../code/cpp/ir/internal/IRSanityImpl.qll | 6 +- .../code/cpp/ir/internal/IRVariable.qll | 404 ++-- .../code/cpp/ir/internal/InstructionTag.qll | 304 +-- .../semmle/code/cpp/ir/internal/Opcode.qll | 308 +-- .../code/cpp/ir/internal/TempVariableTag.qll | 24 +- .../cpp/ir/internal/TranslatedCondition.qll | 526 ++-- .../internal/TranslatedDeclarationEntry.qll | 452 ++-- .../code/cpp/ir/internal/TranslatedExpr.qll | 8 +- .../cpp/ir/internal/TranslatedFunction.qll | 1070 ++++---- .../ir/internal/TranslatedInitialization.qll | 2148 ++++++++--------- .../code/cpp/ir/internal/TranslatedStmt.qll | 1506 ++++++------ cpp/ql/src/semmle/code/cpp/models/Models.qll | 14 +- .../src/semmle/code/cpp/ssa/AliasedSSAIR.qll | 2 +- .../semmle/code/cpp/ssa/PrintAliasedSSAIR.ql | 16 +- .../semmle/code/cpp/ssa/PrintAliasedSSAIR.qll | 2 +- cpp/ql/src/semmle/code/cpp/ssa/PrintSSAIR.ql | 16 +- cpp/ql/src/semmle/code/cpp/ssa/PrintSSAIR.qll | 2 +- cpp/ql/src/semmle/code/cpp/ssa/SSAIR.qll | 2 +- .../code/cpp/ssa/internal/IntegerConstant.qll | 222 +- .../semmle/code/cpp/ssa/internal/Overlap.qll | 56 +- .../internal/aliased_ssa/AliasAnalysis.qll | 428 ++-- .../aliased_ssa/AliasAnalysisInternal.qll | 2 +- .../ssa/internal/aliased_ssa/FunctionIR.qll | 194 +- .../ssa/internal/aliased_ssa/IRInternal.qll | 2 +- .../ssa/internal/aliased_ssa/IRSanityImpl.qll | 6 +- .../ssa/internal/aliased_ssa/IRVariable.qll | 404 ++-- .../internal/aliased_ssa/SSAConstruction.qll | 848 +++---- .../aliased_ssa/SSAConstructionInternal.qll | 6 +- .../ssa/internal/aliased_ssa/SimpleSSA.qll | 166 +- .../aliased_ssa/SimpleSSAInternal.qll | 6 +- .../cpp/ssa/internal/ssa/AliasAnalysis.qll | 428 ++-- .../internal/ssa/AliasAnalysisInternal.qll | 2 +- .../code/cpp/ssa/internal/ssa/FunctionIR.qll | 194 +- .../code/cpp/ssa/internal/ssa/IRInternal.qll | 2 +- .../cpp/ssa/internal/ssa/IRSanityImpl.qll | 6 +- .../code/cpp/ssa/internal/ssa/IRVariable.qll | 404 ++-- .../cpp/ssa/internal/ssa/SSAConstruction.qll | 848 +++---- .../internal/ssa/SSAConstructionInternal.qll | 6 +- .../code/cpp/ssa/internal/ssa/SimpleSSA.qll | 166 +- .../ssa/internal/ssa/SimpleSSAInternal.qll | 6 +- .../aliased_ssa/constants/constants.ql | 98 +- .../aliased_ssa/escape/escape.ql | 44 +- .../aliased_ssa/escape/points_to.ql | 22 +- .../aliased_ssa/escape/ssa_escape.ql | 42 +- .../library-tests/allocators/allocators.ql | 178 +- .../controlflow/guards/Guards.ql | 8 +- .../library-tests/conversions/conversions.ql | 30 +- .../library-tests/conversions/sanity.qlref | 2 +- .../DependsAddressable1.ql | 10 +- .../InitializerAccesses.ql | 2 +- .../derived_types/DerivedTypesBaseType.ql | 12 +- .../comparison_operation.ql | 52 +- .../exprs/unary_operation/unary_operation.ql | 74 +- .../exprs/unevaluated/unevaluated.ql | 10 +- .../exprs/value_categories/loads.ql | 10 +- .../value_categories/value_categories.ql | 14 +- .../library-tests/fields/fields/EnumConst.ql | 22 +- .../library-tests/fields/fields/Fields.ql | 80 +- .../ir/constant_func/constant_func.ql | 60 +- .../library-tests/ir/ir/ssa_block_count.ql | 10 +- .../literals/aggregate_literals/arrays.ql | 10 +- .../aggregate_literals/arrays_value_init.ql | 12 +- .../literals/aggregate_literals/classes.ql | 12 +- .../aggregate_literals/classes_value_init.ql | 12 +- .../parameters/parameters/Parameters3.ql | 8 +- cpp/ql/test/library-tests/stmt/break/break.ql | 10 +- .../structs/compatible_variables/test.ql | 8 +- .../incomplete_definition/pointerbasetype.ql | 10 +- .../synchronization/testoptions.qll | 58 +- .../Critical/MemoryFreed/MemoryFreed.ql | 8 +- .../NewFree/NewArrayDeleteMismatch.qlref | 2 +- .../NewFree/NewDeleteArrayMismatch.qlref | 2 +- .../Critical/NewFree/NewFreeMismatch.qlref | 2 +- .../parameterinitializer/controlflownode.ql | 10 +- .../CommentedOutCode/CommentedOutCode.qlref | 2 +- .../Comments/TodoComments/TodoComments.qlref | 2 +- .../ConfusingMethodNames.qlref | 2 +- .../Documentation/XmldocExtraParam.qlref | 2 +- .../XmldocMissingException.qlref | 2 +- .../Documentation/XmldocMissingParam.qlref | 2 +- .../Documentation/XmldocMissingReturn.qlref | 2 +- .../Documentation/XmldocMissingSummary.qlref | 2 +- .../XmldocMissingTypeParam.qlref | 2 +- .../query-tests/EmptyBlock/EmptyBlock.qlref | 2 +- .../Language Abuse/ChainedIs/ChainedIs.qlref | 2 +- .../ForeachCapture/ForeachCapture.qlref | 2 +- .../MissedReadonlyOpportunity.qlref | 2 +- .../MissedTernaryOpportunity.qlref | 2 +- .../UselessIsBeforeAs/UselessIsBeforeAs.qlref | 2 +- .../query-tests/UseBraces/UseBraces.qlref | 2 +- .../PointlessForwardingMethod.qlref | 2 +- .../frameworks/Electron/RemoteFlowSources.ql | 8 +- .../frameworks/Electron/WebPreferences.ql | 6 +- .../frameworks/NodeJSLib/RemoteFlowSources.ql | 8 +- 108 files changed, 7195 insertions(+), 7182 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..29ba55ea1f6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ +# The following file types will be normalized to LF line endings in the Git +# database, and will keep those LF line endings in the working tree even on +# Windows. Any other files will have whatever line endings they had when they +# were committed. If you add new entires below, you should renormalize the +# affected files by running the following from the root of this repo (requires +# Git 2.16 or greater): +# +# git add --renormalize . +# git status [just to show what files were renormalized] +# git commit -m "Normalize line endings" +*.ql eol=lf +*.qll eol=lf +*.qlref eol=lf diff --git a/cpp/ql/src/semmle/code/cpp/PrintAST.ql b/cpp/ql/src/semmle/code/cpp/PrintAST.ql index 2ae0bfb96cc..e6347917945 100644 --- a/cpp/ql/src/semmle/code/cpp/PrintAST.ql +++ b/cpp/ql/src/semmle/code/cpp/PrintAST.ql @@ -1,9 +1,9 @@ -/** - * @name Print AST - * @description Outputs a representation of the Abstract Syntax Tree. - * @id cpp/print-ast - * @kind graph - */ - -import cpp -import PrintAST +/** + * @name Print AST + * @description Outputs a representation of the Abstract Syntax Tree. + * @id cpp/print-ast + * @kind graph + */ + +import cpp +import PrintAST diff --git a/cpp/ql/src/semmle/code/cpp/PrintAST.qll b/cpp/ql/src/semmle/code/cpp/PrintAST.qll index 062ad9e1573..4ef98893673 100644 --- a/cpp/ql/src/semmle/code/cpp/PrintAST.qll +++ b/cpp/ql/src/semmle/code/cpp/PrintAST.qll @@ -1,546 +1,546 @@ -import cpp - -private newtype TPrintASTConfiguration = MkPrintASTConfiguration() - -/** - * The query can extend this class to control which functions are printed. - */ -class PrintASTConfiguration extends TPrintASTConfiguration { - string toString() { - result = "PrintASTConfiguration" - } - - /** - * Holds if the AST for `func` should be printed. By default, holds for all - * functions. - */ - predicate shouldPrintFunction(Function func) { - any() - } -} - -private predicate shouldPrintFunction(Function func) { - exists(PrintASTConfiguration config | - config.shouldPrintFunction(func) - ) -} - -bindingset[s] -private string escapeString(string s) { - result = s.replaceAll("\\", "\\\\").replaceAll("\n", "\\n").replaceAll("\r", "\\r").replaceAll("\t", "\\t") -} - -/** - * Due to extractor issues with ODR violations, a given AST may wind up with - * multiple locations. This predicate returns a single location - the one whose - * string representation comes first in lexicographical order. - */ -private Location getRepresentativeLocation(Locatable ast) { - result = rank[1](Location loc | loc = ast.getLocation() | loc order by loc.toString()) -} - -/** - * Computes the sort keys to sort the given AST node by location. An AST without - * a location gets an empty file name and a zero line and column number. - */ -private predicate locationSortKeys(Locatable ast, string file, int line, - int column) { - if exists(getRepresentativeLocation(ast)) then ( - exists(Location loc | - loc = getRepresentativeLocation(ast) and - file = loc.getFile().toString() and - line = loc.getStartLine() and - column = loc.getStartColumn() - ) - ) else ( - file = "" and - line = 0 and - column = 0 - ) -} - -/** - * 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) or - TParametersNode(Function func) or - TConstructorInitializersNode(Constructor ctor) { - ctor.hasEntryPoint() - } or - TDestructorDestructionsNode(Destructor dtor) { - dtor.hasEntryPoint() - } - -/** - * A node in the output tree. - */ -class PrintASTNode extends TPrintASTNode { - abstract string toString(); - - /** - * Gets the child node at index `childIndex`. Child indices must be unique, - * but need not be contiguous (but see `getChildByRank`). - */ - abstract PrintASTNode getChild(int childIndex); - - /** - * Holds if this node should be printed in the output. By default, all nodes - * within a function are printed, but the query can override - * `PrintASTConfiguration.shouldPrintFunction` to filter the output. - */ - final predicate shouldPrint() { - shouldPrintFunction(getEnclosingFunction()) - } - - /** - * Gets the children of this node. - */ - final PrintASTNode getAChild() { - result = getChild(_) - } - - /** - * Gets the parent of this node, if any. - */ - final PrintASTNode getParent() { - result.getAChild() = this - } - - /** - * Gets the location of this node in the source code. - */ - abstract Location getLocation(); - - /** - * Gets the value of the property of this node, where the name of the property - * is `key`. - */ - string getProperty(string key) { - key = "semmle.label" and - result = toString() - } - - /** - * Gets the label for the edge from this node to the specified child. By - * default, this is just the index of the child, but subclasses can override - * this. - */ - string getChildEdgeLabel(int childIndex) { - exists(getChild(childIndex)) and - result = childIndex.toString() - } - - /** - * Gets the `Function` that contains this node. - */ - private Function getEnclosingFunction() { - result = getParent*().(FunctionNode).getFunction() - } -} - -/** - * A node representing an AST node. - */ -abstract class ASTNode extends PrintASTNode, TASTNode { - Locatable ast; - - ASTNode() { - this = TASTNode(ast) - } - - override string toString() { - result = ast.toString() - } - - override final Location getLocation() { - result = getRepresentativeLocation(ast) - } - - /** - * Gets the AST represented by this node. - */ - final Locatable getAST() { - result = ast - } -} - -/** - * A node representing an `Expr`. - */ -class ExprNode extends ASTNode { - Expr expr; - - ExprNode() { - expr = ast - } - - override ASTNode getChild(int childIndex) { - result.getAST() = expr.getChild(childIndex).getFullyConverted() - } - - override string getProperty(string key) { - result = super.getProperty(key) or - ( - key = "Value" and - result = getValue() - ) or - ( - key = "Type" and - result = expr.getType().toString() - ) or - ( - key = "ValueCategory" and - result = expr.getValueCategoryString() - ) - } - - string getValue() { - result = expr.getValue() - } -} - -/** - * A node representing a `StringLiteral`. - */ -class StringLiteralNode extends ExprNode { - StringLiteralNode() { - expr instanceof StringLiteral - } - - override string toString() { - result = escapeString(expr.getValue()) - } - - override string getValue() { - result = "\"" + escapeString(expr.getValue()) + "\"" - } -} - -/** - * A node representing a `Conversion`. - */ -class ConversionNode extends ExprNode { - Conversion conv; - - ConversionNode() { - conv = expr - } - - override ASTNode getChild(int childIndex) { - childIndex = 0 and - result.getAST() = conv.getExpr() - } - - override string getChildEdgeLabel(int childIndex) { - childIndex = 0 and result = "expr" - } -} - -/** - * A node representing a `Cast`. - */ -class CastNode extends ConversionNode { - Cast cast; - - CastNode() { - cast = conv - } - - override string getProperty(string key) { - result = super.getProperty(key) or - ( - key = "Conversion" and - result = cast.getSemanticConversionString() - ) - } -} - -/** - * A node representing a `DeclarationEntry`. - */ -class DeclarationEntryNode extends ASTNode { - DeclarationEntry entry; - - DeclarationEntryNode() { - entry = ast - } - - override PrintASTNode getChild(int childIndex) { - none() - } - - override string getProperty(string key) { - result = super.getProperty(key) or - ( - key = "Type" and - result = entry.getType().toString() - ) - } -} - -/** - * A node representing a `VariableDeclarationEntry`. - */ -class VariableDeclarationEntryNode extends DeclarationEntryNode { - VariableDeclarationEntry varEntry; - - VariableDeclarationEntryNode() { - varEntry = entry - } - - override ASTNode getChild(int childIndex) { - childIndex = 0 and - result.getAST() = varEntry.getVariable().getInitializer() - } - - override string getChildEdgeLabel(int childIndex) { - childIndex = 0 and result = "init" - } -} - -/** - * A node representing a `Stmt`. - */ -class StmtNode extends ASTNode { - Stmt stmt; - - StmtNode() { - stmt = ast - } - - override ASTNode getChild(int childIndex) { - exists(Locatable child | - child = stmt.getChild(childIndex) and - ( - result.getAST() = child.(Expr).getFullyConverted() or - result.getAST() = child.(Stmt) - ) - ) - } -} - -/** - * A node representing a `DeclStmt`. - */ -class DeclStmtNode extends StmtNode { - DeclStmt declStmt; - - DeclStmtNode() { - declStmt = stmt - } - - override ASTNode getChild(int childIndex) { - result.getAST() = declStmt.getDeclarationEntry(childIndex) - } -} - -/** - * A node representing a `Parameter`. - */ -class ParameterNode extends ASTNode { - Parameter param; - - ParameterNode() { - param = ast - } - - override final PrintASTNode getChild(int childIndex) { - none() - } - - override final string getProperty(string key) { - result = super.getProperty(key) or - ( - key = "Type" and - result = param.getType().toString() - ) - } -} - -/** - * A node representing an `Initializer`. - */ -class InitializerNode extends ASTNode { - Initializer init; - - InitializerNode() { - init = ast - } - - override ASTNode getChild(int childIndex) { - childIndex = 0 and - result.getAST() = init.getExpr().getFullyConverted() - } - - override string getChildEdgeLabel(int childIndex) { - childIndex = 0 and - result = "expr" - } -} - -/** - * A node representing the parameters of a `Function`. - */ -class ParametersNode extends PrintASTNode, TParametersNode { - Function func; - - ParametersNode() { - this = TParametersNode(func) - } - - override final string toString() { - result = "" - } - - override final Location getLocation() { - result = getRepresentativeLocation(func) - } - - override ASTNode getChild(int childIndex) { - result.getAST() = func.getParameter(childIndex) - } - - final Function getFunction() { - result = func - } -} - -/** - * A node representing the initializer list of a `Constructor`. - */ -class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializersNode { - Constructor ctor; - - ConstructorInitializersNode() { - this = TConstructorInitializersNode(ctor) - } - - override final string toString() { - result = "" - } - - override final Location getLocation() { - result = getRepresentativeLocation(ctor) - } - - override final ASTNode getChild(int childIndex) { - result.getAST() = ctor.getInitializer(childIndex) - } - - final Constructor getConstructor() { - result = ctor - } -} - -/** - * A node representing the destruction list of a `Destructor`. - */ -class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNode { - Destructor dtor; - - DestructorDestructionsNode() { - this = TDestructorDestructionsNode(dtor) - } - - override final string toString() { - result = "" - } - - override final Location getLocation() { - result = getRepresentativeLocation(dtor) - } - - override final ASTNode getChild(int childIndex) { - result.getAST() = dtor.getDestruction(childIndex) - } - - final Destructor getDestructor() { - result = dtor - } -} - -/** - * A node representing a `Function`. - */ -class FunctionNode extends ASTNode { - Function func; - - FunctionNode() { - func = ast - } - - override string toString() { - result = func.getFullSignature() - } - - override PrintASTNode getChild(int childIndex) { - ( - childIndex = 0 and - result.(ParametersNode).getFunction() = func - ) or - ( - childIndex = 1 and - result.(ConstructorInitializersNode).getConstructor() = func - ) or - ( - childIndex = 2 and - result.(ASTNode).getAST() = func.getEntryPoint() - ) or - ( - childIndex = 3 and - result.(DestructorDestructionsNode).getDestructor() = func - ) - } - - override string getChildEdgeLabel(int childIndex) { - childIndex = 0 and result = "params" or - childIndex = 1 and result = "initializations" or - childIndex = 2 and result = "body" or - childIndex = 3 and result = "destructions" - } - - private int getOrder() { - this = rank[result](FunctionNode node, Function function, string file, - int line, int column | - node.getAST() = function and - locationSortKeys(function, file, line, column) | - node order by - file, - line, - column, - function.getFullSignature() - ) - } - - override string getProperty(string key) { - result = super.getProperty(key) or - key = "semmle.order" and result = getOrder().toString() - } - - final Function getFunction() { - result = func - } -} - -query predicate nodes(PrintASTNode node, string key, string value) { - node.shouldPrint() and - value = node.getProperty(key) -} - -query predicate edges(PrintASTNode source, PrintASTNode target, string key, string value) { - exists(int childIndex | - source.shouldPrint() and - target.shouldPrint() and - target = source.getChild(childIndex) and - ( - key = "semmle.label" and value = source.getChildEdgeLabel(childIndex) or - key = "semmle.order" and value = childIndex.toString() - ) - ) -} - -query predicate graphProperties(string key, string value) { - key = "semmle.graphKind" and value = "tree" -} +import cpp + +private newtype TPrintASTConfiguration = MkPrintASTConfiguration() + +/** + * The query can extend this class to control which functions are printed. + */ +class PrintASTConfiguration extends TPrintASTConfiguration { + string toString() { + result = "PrintASTConfiguration" + } + + /** + * Holds if the AST for `func` should be printed. By default, holds for all + * functions. + */ + predicate shouldPrintFunction(Function func) { + any() + } +} + +private predicate shouldPrintFunction(Function func) { + exists(PrintASTConfiguration config | + config.shouldPrintFunction(func) + ) +} + +bindingset[s] +private string escapeString(string s) { + result = s.replaceAll("\\", "\\\\").replaceAll("\n", "\\n").replaceAll("\r", "\\r").replaceAll("\t", "\\t") +} + +/** + * Due to extractor issues with ODR violations, a given AST may wind up with + * multiple locations. This predicate returns a single location - the one whose + * string representation comes first in lexicographical order. + */ +private Location getRepresentativeLocation(Locatable ast) { + result = rank[1](Location loc | loc = ast.getLocation() | loc order by loc.toString()) +} + +/** + * Computes the sort keys to sort the given AST node by location. An AST without + * a location gets an empty file name and a zero line and column number. + */ +private predicate locationSortKeys(Locatable ast, string file, int line, + int column) { + if exists(getRepresentativeLocation(ast)) then ( + exists(Location loc | + loc = getRepresentativeLocation(ast) and + file = loc.getFile().toString() and + line = loc.getStartLine() and + column = loc.getStartColumn() + ) + ) else ( + file = "" and + line = 0 and + column = 0 + ) +} + +/** + * 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) or + TParametersNode(Function func) or + TConstructorInitializersNode(Constructor ctor) { + ctor.hasEntryPoint() + } or + TDestructorDestructionsNode(Destructor dtor) { + dtor.hasEntryPoint() + } + +/** + * A node in the output tree. + */ +class PrintASTNode extends TPrintASTNode { + abstract string toString(); + + /** + * Gets the child node at index `childIndex`. Child indices must be unique, + * but need not be contiguous (but see `getChildByRank`). + */ + abstract PrintASTNode getChild(int childIndex); + + /** + * Holds if this node should be printed in the output. By default, all nodes + * within a function are printed, but the query can override + * `PrintASTConfiguration.shouldPrintFunction` to filter the output. + */ + final predicate shouldPrint() { + shouldPrintFunction(getEnclosingFunction()) + } + + /** + * Gets the children of this node. + */ + final PrintASTNode getAChild() { + result = getChild(_) + } + + /** + * Gets the parent of this node, if any. + */ + final PrintASTNode getParent() { + result.getAChild() = this + } + + /** + * Gets the location of this node in the source code. + */ + abstract Location getLocation(); + + /** + * Gets the value of the property of this node, where the name of the property + * is `key`. + */ + string getProperty(string key) { + key = "semmle.label" and + result = toString() + } + + /** + * Gets the label for the edge from this node to the specified child. By + * default, this is just the index of the child, but subclasses can override + * this. + */ + string getChildEdgeLabel(int childIndex) { + exists(getChild(childIndex)) and + result = childIndex.toString() + } + + /** + * Gets the `Function` that contains this node. + */ + private Function getEnclosingFunction() { + result = getParent*().(FunctionNode).getFunction() + } +} + +/** + * A node representing an AST node. + */ +abstract class ASTNode extends PrintASTNode, TASTNode { + Locatable ast; + + ASTNode() { + this = TASTNode(ast) + } + + override string toString() { + result = ast.toString() + } + + override final Location getLocation() { + result = getRepresentativeLocation(ast) + } + + /** + * Gets the AST represented by this node. + */ + final Locatable getAST() { + result = ast + } +} + +/** + * A node representing an `Expr`. + */ +class ExprNode extends ASTNode { + Expr expr; + + ExprNode() { + expr = ast + } + + override ASTNode getChild(int childIndex) { + result.getAST() = expr.getChild(childIndex).getFullyConverted() + } + + override string getProperty(string key) { + result = super.getProperty(key) or + ( + key = "Value" and + result = getValue() + ) or + ( + key = "Type" and + result = expr.getType().toString() + ) or + ( + key = "ValueCategory" and + result = expr.getValueCategoryString() + ) + } + + string getValue() { + result = expr.getValue() + } +} + +/** + * A node representing a `StringLiteral`. + */ +class StringLiteralNode extends ExprNode { + StringLiteralNode() { + expr instanceof StringLiteral + } + + override string toString() { + result = escapeString(expr.getValue()) + } + + override string getValue() { + result = "\"" + escapeString(expr.getValue()) + "\"" + } +} + +/** + * A node representing a `Conversion`. + */ +class ConversionNode extends ExprNode { + Conversion conv; + + ConversionNode() { + conv = expr + } + + override ASTNode getChild(int childIndex) { + childIndex = 0 and + result.getAST() = conv.getExpr() + } + + override string getChildEdgeLabel(int childIndex) { + childIndex = 0 and result = "expr" + } +} + +/** + * A node representing a `Cast`. + */ +class CastNode extends ConversionNode { + Cast cast; + + CastNode() { + cast = conv + } + + override string getProperty(string key) { + result = super.getProperty(key) or + ( + key = "Conversion" and + result = cast.getSemanticConversionString() + ) + } +} + +/** + * A node representing a `DeclarationEntry`. + */ +class DeclarationEntryNode extends ASTNode { + DeclarationEntry entry; + + DeclarationEntryNode() { + entry = ast + } + + override PrintASTNode getChild(int childIndex) { + none() + } + + override string getProperty(string key) { + result = super.getProperty(key) or + ( + key = "Type" and + result = entry.getType().toString() + ) + } +} + +/** + * A node representing a `VariableDeclarationEntry`. + */ +class VariableDeclarationEntryNode extends DeclarationEntryNode { + VariableDeclarationEntry varEntry; + + VariableDeclarationEntryNode() { + varEntry = entry + } + + override ASTNode getChild(int childIndex) { + childIndex = 0 and + result.getAST() = varEntry.getVariable().getInitializer() + } + + override string getChildEdgeLabel(int childIndex) { + childIndex = 0 and result = "init" + } +} + +/** + * A node representing a `Stmt`. + */ +class StmtNode extends ASTNode { + Stmt stmt; + + StmtNode() { + stmt = ast + } + + override ASTNode getChild(int childIndex) { + exists(Locatable child | + child = stmt.getChild(childIndex) and + ( + result.getAST() = child.(Expr).getFullyConverted() or + result.getAST() = child.(Stmt) + ) + ) + } +} + +/** + * A node representing a `DeclStmt`. + */ +class DeclStmtNode extends StmtNode { + DeclStmt declStmt; + + DeclStmtNode() { + declStmt = stmt + } + + override ASTNode getChild(int childIndex) { + result.getAST() = declStmt.getDeclarationEntry(childIndex) + } +} + +/** + * A node representing a `Parameter`. + */ +class ParameterNode extends ASTNode { + Parameter param; + + ParameterNode() { + param = ast + } + + override final PrintASTNode getChild(int childIndex) { + none() + } + + override final string getProperty(string key) { + result = super.getProperty(key) or + ( + key = "Type" and + result = param.getType().toString() + ) + } +} + +/** + * A node representing an `Initializer`. + */ +class InitializerNode extends ASTNode { + Initializer init; + + InitializerNode() { + init = ast + } + + override ASTNode getChild(int childIndex) { + childIndex = 0 and + result.getAST() = init.getExpr().getFullyConverted() + } + + override string getChildEdgeLabel(int childIndex) { + childIndex = 0 and + result = "expr" + } +} + +/** + * A node representing the parameters of a `Function`. + */ +class ParametersNode extends PrintASTNode, TParametersNode { + Function func; + + ParametersNode() { + this = TParametersNode(func) + } + + override final string toString() { + result = "" + } + + override final Location getLocation() { + result = getRepresentativeLocation(func) + } + + override ASTNode getChild(int childIndex) { + result.getAST() = func.getParameter(childIndex) + } + + final Function getFunction() { + result = func + } +} + +/** + * A node representing the initializer list of a `Constructor`. + */ +class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializersNode { + Constructor ctor; + + ConstructorInitializersNode() { + this = TConstructorInitializersNode(ctor) + } + + override final string toString() { + result = "" + } + + override final Location getLocation() { + result = getRepresentativeLocation(ctor) + } + + override final ASTNode getChild(int childIndex) { + result.getAST() = ctor.getInitializer(childIndex) + } + + final Constructor getConstructor() { + result = ctor + } +} + +/** + * A node representing the destruction list of a `Destructor`. + */ +class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNode { + Destructor dtor; + + DestructorDestructionsNode() { + this = TDestructorDestructionsNode(dtor) + } + + override final string toString() { + result = "" + } + + override final Location getLocation() { + result = getRepresentativeLocation(dtor) + } + + override final ASTNode getChild(int childIndex) { + result.getAST() = dtor.getDestruction(childIndex) + } + + final Destructor getDestructor() { + result = dtor + } +} + +/** + * A node representing a `Function`. + */ +class FunctionNode extends ASTNode { + Function func; + + FunctionNode() { + func = ast + } + + override string toString() { + result = func.getFullSignature() + } + + override PrintASTNode getChild(int childIndex) { + ( + childIndex = 0 and + result.(ParametersNode).getFunction() = func + ) or + ( + childIndex = 1 and + result.(ConstructorInitializersNode).getConstructor() = func + ) or + ( + childIndex = 2 and + result.(ASTNode).getAST() = func.getEntryPoint() + ) or + ( + childIndex = 3 and + result.(DestructorDestructionsNode).getDestructor() = func + ) + } + + override string getChildEdgeLabel(int childIndex) { + childIndex = 0 and result = "params" or + childIndex = 1 and result = "initializations" or + childIndex = 2 and result = "body" or + childIndex = 3 and result = "destructions" + } + + private int getOrder() { + this = rank[result](FunctionNode node, Function function, string file, + int line, int column | + node.getAST() = function and + locationSortKeys(function, file, line, column) | + node order by + file, + line, + column, + function.getFullSignature() + ) + } + + override string getProperty(string key) { + result = super.getProperty(key) or + key = "semmle.order" and result = getOrder().toString() + } + + final Function getFunction() { + result = func + } +} + +query predicate nodes(PrintASTNode node, string key, string value) { + node.shouldPrint() and + value = node.getProperty(key) +} + +query predicate edges(PrintASTNode source, PrintASTNode target, string key, string value) { + exists(int childIndex | + source.shouldPrint() and + target.shouldPrint() and + target = source.getChild(childIndex) and + ( + key = "semmle.label" and value = source.getChildEdgeLabel(childIndex) or + key = "semmle.order" and value = childIndex.toString() + ) + ) +} + +query predicate graphProperties(string key, string value) { + key = "semmle.graphKind" and value = "tree" +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/EdgeKind.qll b/cpp/ql/src/semmle/code/cpp/ir/EdgeKind.qll index 172a879c664..bea41c5ceb4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/EdgeKind.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/EdgeKind.qll @@ -1,141 +1,141 @@ -import cpp - -private newtype TEdgeKind = - TGotoEdge() or // Single successor (including fall-through) - TTrueEdge() or // 'true' edge of conditional branch - TFalseEdge() or // 'false' edge of conditional branch - TExceptionEdge() or // Thrown exception - TDefaultEdge() or // 'default' label of switch - TCaseEdge(string minValue, string maxValue) { // Case label of switch - exists(SwitchCase switchCase | - hasCaseEdge(switchCase, minValue, maxValue) - ) - } - -/** - * Represents the kind of an edge in the IR control flow graph. Each - * `Instruction` or `IRBlock` has at most one successor of any single - * `EdgeKind`. - */ -abstract class EdgeKind extends TEdgeKind { - abstract string toString(); -} - -/** - * A "goto" edge, representing the unconditional successor of an `Instruction` - * or `IRBlock`. - */ -class GotoEdge extends EdgeKind, TGotoEdge { - override final string toString() { - result = "Goto" - } -} - -GotoEdge gotoEdge() { - result = TGotoEdge() -} - -/** - * A "true" edge, representing the successor of a conditional branch when the - * condition is non-zero. - */ -class TrueEdge extends EdgeKind, TTrueEdge { - override final string toString() { - result = "True" - } -} - -TrueEdge trueEdge() { - result = TTrueEdge() -} - -/** - * A "false" edge, representing the successor of a conditional branch when the - * condition is zero. - */ -class FalseEdge extends EdgeKind, TFalseEdge { - override final string toString() { - result = "False" - } -} - -FalseEdge falseEdge() { - result = TFalseEdge() -} - -/** - * An "exception" edge, representing the successor of an instruction when that - * instruction's evaluation throws an exception. - */ -class ExceptionEdge extends EdgeKind, TExceptionEdge { - override final string toString() { - result = "Exception" - } -} - -ExceptionEdge exceptionEdge() { - result = TExceptionEdge() -} - -/** - * A "default" edge, representing the successor of a `Switch` instruction when - * none of the case values matches the condition value. - */ -class DefaultEdge extends EdgeKind, TDefaultEdge { - override final string toString() { - result = "Default" - } -} - -DefaultEdge defaultEdge() { - result = TDefaultEdge() -} - -/** - * A "case" edge, representing the successor of a `Switch` instruction when the - * the condition value matches a correponding `case` label. - */ -class CaseEdge extends EdgeKind, TCaseEdge { - string minValue; - string maxValue; - - CaseEdge() { - this = TCaseEdge(minValue, maxValue) - } - - override final string toString() { - if minValue = maxValue then - result = "Case[" + minValue + "]" - else - result = "Case[" + minValue + ".." + maxValue + "]" - } - - string getMinValue() { - result = minValue - } - - string getMaxValue() { - result = maxValue - } -} - -CaseEdge caseEdge(string minValue, string maxValue) { - result = TCaseEdge(minValue, maxValue) -} - -private predicate hasCaseEdge(SwitchCase switchCase, string minValue, - string maxValue) { - minValue = switchCase.getExpr().getFullyConverted().getValue() and - if exists(switchCase.getEndExpr()) then - maxValue = switchCase.getEndExpr().getFullyConverted().getValue() - else - maxValue = minValue -} - -EdgeKind getCaseEdge(SwitchCase switchCase) { - exists(CaseEdge edge | - result = edge and - hasCaseEdge(switchCase, edge.getMinValue(), edge.getMaxValue()) - ) or - (switchCase instanceof DefaultCase and result instanceof DefaultEdge) -} +import cpp + +private newtype TEdgeKind = + TGotoEdge() or // Single successor (including fall-through) + TTrueEdge() or // 'true' edge of conditional branch + TFalseEdge() or // 'false' edge of conditional branch + TExceptionEdge() or // Thrown exception + TDefaultEdge() or // 'default' label of switch + TCaseEdge(string minValue, string maxValue) { // Case label of switch + exists(SwitchCase switchCase | + hasCaseEdge(switchCase, minValue, maxValue) + ) + } + +/** + * Represents the kind of an edge in the IR control flow graph. Each + * `Instruction` or `IRBlock` has at most one successor of any single + * `EdgeKind`. + */ +abstract class EdgeKind extends TEdgeKind { + abstract string toString(); +} + +/** + * A "goto" edge, representing the unconditional successor of an `Instruction` + * or `IRBlock`. + */ +class GotoEdge extends EdgeKind, TGotoEdge { + override final string toString() { + result = "Goto" + } +} + +GotoEdge gotoEdge() { + result = TGotoEdge() +} + +/** + * A "true" edge, representing the successor of a conditional branch when the + * condition is non-zero. + */ +class TrueEdge extends EdgeKind, TTrueEdge { + override final string toString() { + result = "True" + } +} + +TrueEdge trueEdge() { + result = TTrueEdge() +} + +/** + * A "false" edge, representing the successor of a conditional branch when the + * condition is zero. + */ +class FalseEdge extends EdgeKind, TFalseEdge { + override final string toString() { + result = "False" + } +} + +FalseEdge falseEdge() { + result = TFalseEdge() +} + +/** + * An "exception" edge, representing the successor of an instruction when that + * instruction's evaluation throws an exception. + */ +class ExceptionEdge extends EdgeKind, TExceptionEdge { + override final string toString() { + result = "Exception" + } +} + +ExceptionEdge exceptionEdge() { + result = TExceptionEdge() +} + +/** + * A "default" edge, representing the successor of a `Switch` instruction when + * none of the case values matches the condition value. + */ +class DefaultEdge extends EdgeKind, TDefaultEdge { + override final string toString() { + result = "Default" + } +} + +DefaultEdge defaultEdge() { + result = TDefaultEdge() +} + +/** + * A "case" edge, representing the successor of a `Switch` instruction when the + * the condition value matches a correponding `case` label. + */ +class CaseEdge extends EdgeKind, TCaseEdge { + string minValue; + string maxValue; + + CaseEdge() { + this = TCaseEdge(minValue, maxValue) + } + + override final string toString() { + if minValue = maxValue then + result = "Case[" + minValue + "]" + else + result = "Case[" + minValue + ".." + maxValue + "]" + } + + string getMinValue() { + result = minValue + } + + string getMaxValue() { + result = maxValue + } +} + +CaseEdge caseEdge(string minValue, string maxValue) { + result = TCaseEdge(minValue, maxValue) +} + +private predicate hasCaseEdge(SwitchCase switchCase, string minValue, + string maxValue) { + minValue = switchCase.getExpr().getFullyConverted().getValue() and + if exists(switchCase.getEndExpr()) then + maxValue = switchCase.getEndExpr().getFullyConverted().getValue() + else + maxValue = minValue +} + +EdgeKind getCaseEdge(SwitchCase switchCase) { + exists(CaseEdge edge | + result = edge and + hasCaseEdge(switchCase, edge.getMinValue(), edge.getMaxValue()) + ) or + (switchCase instanceof DefaultCase and result instanceof DefaultEdge) +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/IR.qll b/cpp/ql/src/semmle/code/cpp/ir/IR.qll index 07c19ae8fba..45c72e0dbb1 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/IR.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/IR.qll @@ -1 +1 @@ -import internal.IRImpl +import internal.IRImpl diff --git a/cpp/ql/src/semmle/code/cpp/ir/MemoryAccessKind.qll b/cpp/ql/src/semmle/code/cpp/ir/MemoryAccessKind.qll index a71da214a7c..2fdc6050ae4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/MemoryAccessKind.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/MemoryAccessKind.qll @@ -1,54 +1,54 @@ -import cpp - -newtype TMemoryAccessKind = - TIndirectMemoryAccess() or - TEscapedMemoryAccess() or - TPhiMemoryAccess() or - TUnmodeledMemoryAccess() - -/** - * Describes the set of memory locations memory accessed by a memory operand or - * memory result. - */ -class MemoryAccessKind extends TMemoryAccessKind { - abstract string toString(); -} - -/** - * The operand or result accesses memory at the address specified by the - * `LoadStoreAddressOperand` on the same instruction. - */ -class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess { - override string toString() { - result = "indirect" - } -} - -/** - * The operand or result accesses all memory whose address has escaped. - */ -class EscapedMemoryAccess extends MemoryAccessKind, TEscapedMemoryAccess { - override string toString() { - result = "escaped" - } -} - -/** - * The operand is a Phi operand, which accesses the same memory as its - * definition. - */ -class PhiMemoryAccess extends MemoryAccessKind, TPhiMemoryAccess { - override string toString() { - result = "phi" - } -} - -/** - * The operand accesses memory not modeled in SSA. Used only on the result of - * `UnmodeledDefinition` and on the operands of `UnmodeledUse`. - */ -class UnmodeledMemoryAccess extends MemoryAccessKind, TUnmodeledMemoryAccess { - override string toString() { - result = "unmodeled" - } -} +import cpp + +newtype TMemoryAccessKind = + TIndirectMemoryAccess() or + TEscapedMemoryAccess() or + TPhiMemoryAccess() or + TUnmodeledMemoryAccess() + +/** + * Describes the set of memory locations memory accessed by a memory operand or + * memory result. + */ +class MemoryAccessKind extends TMemoryAccessKind { + abstract string toString(); +} + +/** + * The operand or result accesses memory at the address specified by the + * `LoadStoreAddressOperand` on the same instruction. + */ +class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess { + override string toString() { + result = "indirect" + } +} + +/** + * The operand or result accesses all memory whose address has escaped. + */ +class EscapedMemoryAccess extends MemoryAccessKind, TEscapedMemoryAccess { + override string toString() { + result = "escaped" + } +} + +/** + * The operand is a Phi operand, which accesses the same memory as its + * definition. + */ +class PhiMemoryAccess extends MemoryAccessKind, TPhiMemoryAccess { + override string toString() { + result = "phi" + } +} + +/** + * The operand accesses memory not modeled in SSA. Used only on the result of + * `UnmodeledDefinition` and on the operands of `UnmodeledUse`. + */ +class UnmodeledMemoryAccess extends MemoryAccessKind, TUnmodeledMemoryAccess { + override string toString() { + result = "unmodeled" + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/Opcode.qll b/cpp/ql/src/semmle/code/cpp/ir/Opcode.qll index 4104c6a104e..3798f1d1791 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/Opcode.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/Opcode.qll @@ -1 +1 @@ -import internal.Opcode +import internal.Opcode diff --git a/cpp/ql/src/semmle/code/cpp/ir/PrintIR.ql b/cpp/ql/src/semmle/code/cpp/ir/PrintIR.ql index debaa647f44..38d2539a113 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/PrintIR.ql +++ b/cpp/ql/src/semmle/code/cpp/ir/PrintIR.ql @@ -1,8 +1,8 @@ -/** - * @name Print IR - * @description Outputs a representation of the IR graph - * @id cpp/print-ir - * @kind graph - */ - -import PrintIR +/** + * @name Print IR + * @description Outputs a representation of the IR graph + * @id cpp/print-ir + * @kind graph + */ + +import PrintIR diff --git a/cpp/ql/src/semmle/code/cpp/ir/PrintIR.qll b/cpp/ql/src/semmle/code/cpp/ir/PrintIR.qll index 2a8ffdf6169..2c4bf124a52 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/PrintIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/PrintIR.qll @@ -1 +1 @@ -import internal.PrintIRImpl +import internal.PrintIRImpl diff --git a/cpp/ql/src/semmle/code/cpp/ir/TempVariableTag.qll b/cpp/ql/src/semmle/code/cpp/ir/TempVariableTag.qll index b19d20503c8..d40c2c9bcfe 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/TempVariableTag.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/TempVariableTag.qll @@ -1,8 +1,8 @@ -import cpp -private import internal.TempVariableTag - -class TempVariableTag extends TTempVariableTag { - string toString() { - result = "Tag" - } -} +import cpp +private import internal.TempVariableTag + +class TempVariableTag extends TTempVariableTag { + string toString() { + result = "Tag" + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/ValueCategory.qll b/cpp/ql/src/semmle/code/cpp/ir/ValueCategory.qll index 02f3883a810..c736b0b07e6 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/ValueCategory.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/ValueCategory.qll @@ -1,44 +1,44 @@ -import cpp - -private newtype TValueCategory = - TLValue() or - TXValue() or - TPRValue() - -abstract class ValueCategory extends TValueCategory { - abstract string toString(); -} - -abstract class GLValue extends ValueCategory { -} - -abstract class RValue extends ValueCategory { -} - -class LValue extends GLValue, TLValue { - override string toString() { - result = "lvalue" - } -} - -class XValue extends GLValue, RValue, TXValue { - override string toString() { - result = "xvalue" - } -} - -class PRValue extends RValue, TPRValue { - override string toString() { - result = "prvalue" - } -} - -ValueCategory getExprValueCategory(Expr expr) { - ( - expr.isLValueCategory() and result instanceof LValue - ) or ( - expr.isXValueCategory() and result instanceof XValue - ) or ( - expr.isPRValueCategory() and result instanceof PRValue - ) -} +import cpp + +private newtype TValueCategory = + TLValue() or + TXValue() or + TPRValue() + +abstract class ValueCategory extends TValueCategory { + abstract string toString(); +} + +abstract class GLValue extends ValueCategory { +} + +abstract class RValue extends ValueCategory { +} + +class LValue extends GLValue, TLValue { + override string toString() { + result = "lvalue" + } +} + +class XValue extends GLValue, RValue, TXValue { + override string toString() { + result = "xvalue" + } +} + +class PRValue extends RValue, TPRValue { + override string toString() { + result = "prvalue" + } +} + +ValueCategory getExprValueCategory(Expr expr) { + ( + expr.isLValueCategory() and result instanceof LValue + ) or ( + expr.isXValueCategory() and result instanceof XValue + ) or ( + expr.isPRValueCategory() and result instanceof PRValue + ) +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/FunctionIR.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/FunctionIR.qll index 4568ae7ceb2..3e918fd3b49 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/FunctionIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/FunctionIR.qll @@ -1,97 +1,97 @@ -private import IRInternal -import Instruction -import cpp - -private newtype TFunctionIR = - MkFunctionIR(Function func) { - Construction::functionHasIR(func) - } - -/** - * Represents the IR for a function. - */ -class FunctionIR extends TFunctionIR { - Function func; - - FunctionIR() { - this = MkFunctionIR(func) - } - - final string toString() { - result = "IR: " + func.toString() - } - - /** - * Gets the function whose IR is represented. - */ - final Function getFunction() { - result = func - } - - /** - * Gets the location of the function. - */ - final Location getLocation() { - result = func.getLocation() - } - - /** - * Gets the entry point for this function. - */ - pragma[noinline] - final EnterFunctionInstruction getEnterFunctionInstruction() { - result.getFunctionIR() = this - } - - /** - * Gets the exit point for this function. - */ - pragma[noinline] - final ExitFunctionInstruction getExitFunctionInstruction() { - result.getFunctionIR() = this - } - - pragma[noinline] - final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() { - result.getFunctionIR() = this - } - - /** - * Gets the single return instruction for this function. - */ - pragma[noinline] - final ReturnInstruction getReturnInstruction() { - result.getFunctionIR() = this - } - - /** - * Gets the variable used to hold the return value of this function. If this - * function does not return a value, this predicate does not hold. - */ - pragma[noinline] - final IRReturnVariable getReturnVariable() { - result.getFunctionIR() = this - } - - /** - * Gets the block containing the entry point of this function. - */ - pragma[noinline] - final IRBlock getEntryBlock() { - result.getFirstInstruction() = getEnterFunctionInstruction() - } - - /** - * Gets all instructions in this function. - */ - final Instruction getAnInstruction() { - result.getFunctionIR() = this - } - - /** - * Gets all blocks in this function. - */ - final IRBlock getABlock() { - result.getFunctionIR() = this - } -} +private import IRInternal +import Instruction +import cpp + +private newtype TFunctionIR = + MkFunctionIR(Function func) { + Construction::functionHasIR(func) + } + +/** + * Represents the IR for a function. + */ +class FunctionIR extends TFunctionIR { + Function func; + + FunctionIR() { + this = MkFunctionIR(func) + } + + final string toString() { + result = "IR: " + func.toString() + } + + /** + * Gets the function whose IR is represented. + */ + final Function getFunction() { + result = func + } + + /** + * Gets the location of the function. + */ + final Location getLocation() { + result = func.getLocation() + } + + /** + * Gets the entry point for this function. + */ + pragma[noinline] + final EnterFunctionInstruction getEnterFunctionInstruction() { + result.getFunctionIR() = this + } + + /** + * Gets the exit point for this function. + */ + pragma[noinline] + final ExitFunctionInstruction getExitFunctionInstruction() { + result.getFunctionIR() = this + } + + pragma[noinline] + final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() { + result.getFunctionIR() = this + } + + /** + * Gets the single return instruction for this function. + */ + pragma[noinline] + final ReturnInstruction getReturnInstruction() { + result.getFunctionIR() = this + } + + /** + * Gets the variable used to hold the return value of this function. If this + * function does not return a value, this predicate does not hold. + */ + pragma[noinline] + final IRReturnVariable getReturnVariable() { + result.getFunctionIR() = this + } + + /** + * Gets the block containing the entry point of this function. + */ + pragma[noinline] + final IRBlock getEntryBlock() { + result.getFirstInstruction() = getEnterFunctionInstruction() + } + + /** + * Gets all instructions in this function. + */ + final Instruction getAnInstruction() { + result.getFunctionIR() = this + } + + /** + * Gets all blocks in this function. + */ + final IRBlock getABlock() { + result.getFunctionIR() = this + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/IRConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/IRConstruction.qll index e72dede506e..3552c984957 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/IRConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/IRConstruction.qll @@ -1,165 +1,165 @@ -import cpp -import semmle.code.cpp.ir.IR -private import InstructionTag -private import TempVariableTag -private import TranslatedElement -private import TranslatedFunction - -class InstructionTagType extends TInstructionTag { - final string toString() { - result = "Tag" - } -} - -private TranslatedElement getInstructionTranslatedElement( - Instruction instruction) { - result = getInstructionTranslatedElementAndTag(instruction, _) -} - -private TranslatedElement getInstructionTranslatedElementAndTag( - Instruction instruction, InstructionTag tag) { - result.getAST() = instruction.getAST() and - tag = instruction.getTag() and - result.hasInstruction(_, tag, _, _) -} - -private TranslatedElement getTempVariableTranslatedElement( - IRTempVariable var) { - result.getAST() = var.getAST() and - result.hasTempVariable(var.getTag(), _) -} - -import Cached -cached private module Cached { - cached predicate functionHasIR(Function func) { - exists(getTranslatedFunction(func)) - } - - cached int getMaxCallArgIndex() { - result = max(int argIndex | - exists(FunctionCall call | - exists(call.getArgument(argIndex)) - ) - ) - } - - cached newtype TInstruction = - MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast, - InstructionTag tag, Type resultType, boolean isGLValue) { - hasInstruction(funcIR.getFunction(), opcode, ast, tag, - resultType, isGLValue) - } - - private predicate hasInstruction(Function func, Opcode opcode, Locatable ast, - InstructionTag tag, Type resultType, boolean isGLValue) { - exists(TranslatedElement element | - element.getAST() = ast and - func = element.getFunction() and - element.hasInstruction(opcode, tag, resultType, isGLValue) - ) - } - - cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, - Type type) { - exists(TranslatedElement element | - element.getAST() = ast and - func = element.getFunction() and - element.hasTempVariable(tag, type) - ) - } - - cached predicate hasModeledMemoryResult(Instruction instruction) { - none() - } - - cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) { - result = getInstructionTranslatedElement(instruction).getInstructionOperand( - instruction.getTag(), tag) - } - - cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) { - none() - } - - cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) { - result = getInstructionTranslatedElement(instruction).getInstructionSuccessor( - instruction.getTag(), kind) - } - - cached IRVariable getInstructionVariable(Instruction instruction) { - result = getInstructionTranslatedElement(instruction).getInstructionVariable( - instruction.getTag()) - } - - cached Field getInstructionField(Instruction instruction) { - exists(TranslatedElement element, InstructionTag tag | - instructionOrigin(instruction, element, tag) and - result = element.getInstructionField(tag) - ) - } - - cached Function getInstructionFunction(Instruction instruction) { - exists(InstructionTag tag | - result = getInstructionTranslatedElementAndTag(instruction, tag) - .getInstructionFunction(tag) - ) - } - - cached string getInstructionConstantValue(Instruction instruction) { - result = - getInstructionTranslatedElement(instruction).getInstructionConstantValue( - instruction.getTag()) - } - - cached StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = - getInstructionTranslatedElement(instruction).getInstructionStringLiteral( - instruction.getTag()) - } - - cached Type getInstructionExceptionType(Instruction instruction) { - result = - getInstructionTranslatedElement(instruction).getInstructionExceptionType( - instruction.getTag()) - } - - cached predicate getInstructionInheritance(Instruction instruction, - Class baseClass, Class derivedClass) { - getInstructionTranslatedElement(instruction).getInstructionInheritance( - instruction.getTag(), baseClass, derivedClass) - } - - pragma[noinline] - private predicate instructionOrigin(Instruction instruction, - TranslatedElement element, InstructionTag tag) { - element = getInstructionTranslatedElement(instruction) and - tag = instruction.getTag() - } - - cached int getInstructionElementSize(Instruction instruction) { - exists(TranslatedElement element, InstructionTag tag | - instructionOrigin(instruction, element, tag) and - result = element.getInstructionElementSize(tag) - ) - } - - cached int getInstructionResultSize(Instruction instruction) { - exists(TranslatedElement element, InstructionTag tag | - instructionOrigin(instruction, element, tag) and - result = element.getInstructionResultSize(tag) - ) - } -} - -import CachedForDebugging -cached private module CachedForDebugging { - cached string getTempVariableUniqueId(IRTempVariable var) { - result = getTempVariableTranslatedElement(var).getId() + ":" + - getTempVariableTagId(var.getTag()) - } - - cached string getInstructionUniqueId(Instruction instruction) { - result = getInstructionTranslatedElement(instruction).getId() + ":" + - getInstructionTagId(instruction.getTag()) - } -} +import cpp +import semmle.code.cpp.ir.IR +private import InstructionTag +private import TempVariableTag +private import TranslatedElement +private import TranslatedFunction + +class InstructionTagType extends TInstructionTag { + final string toString() { + result = "Tag" + } +} + +private TranslatedElement getInstructionTranslatedElement( + Instruction instruction) { + result = getInstructionTranslatedElementAndTag(instruction, _) +} + +private TranslatedElement getInstructionTranslatedElementAndTag( + Instruction instruction, InstructionTag tag) { + result.getAST() = instruction.getAST() and + tag = instruction.getTag() and + result.hasInstruction(_, tag, _, _) +} + +private TranslatedElement getTempVariableTranslatedElement( + IRTempVariable var) { + result.getAST() = var.getAST() and + result.hasTempVariable(var.getTag(), _) +} + +import Cached +cached private module Cached { + cached predicate functionHasIR(Function func) { + exists(getTranslatedFunction(func)) + } + + cached int getMaxCallArgIndex() { + result = max(int argIndex | + exists(FunctionCall call | + exists(call.getArgument(argIndex)) + ) + ) + } + + cached newtype TInstruction = + MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast, + InstructionTag tag, Type resultType, boolean isGLValue) { + hasInstruction(funcIR.getFunction(), opcode, ast, tag, + resultType, isGLValue) + } + + private predicate hasInstruction(Function func, Opcode opcode, Locatable ast, + InstructionTag tag, Type resultType, boolean isGLValue) { + exists(TranslatedElement element | + element.getAST() = ast and + func = element.getFunction() and + element.hasInstruction(opcode, tag, resultType, isGLValue) + ) + } + + cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, + Type type) { + exists(TranslatedElement element | + element.getAST() = ast and + func = element.getFunction() and + element.hasTempVariable(tag, type) + ) + } + + cached predicate hasModeledMemoryResult(Instruction instruction) { + none() + } + + cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) { + result = getInstructionTranslatedElement(instruction).getInstructionOperand( + instruction.getTag(), tag) + } + + cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) { + none() + } + + cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) { + result = getInstructionTranslatedElement(instruction).getInstructionSuccessor( + instruction.getTag(), kind) + } + + cached IRVariable getInstructionVariable(Instruction instruction) { + result = getInstructionTranslatedElement(instruction).getInstructionVariable( + instruction.getTag()) + } + + cached Field getInstructionField(Instruction instruction) { + exists(TranslatedElement element, InstructionTag tag | + instructionOrigin(instruction, element, tag) and + result = element.getInstructionField(tag) + ) + } + + cached Function getInstructionFunction(Instruction instruction) { + exists(InstructionTag tag | + result = getInstructionTranslatedElementAndTag(instruction, tag) + .getInstructionFunction(tag) + ) + } + + cached string getInstructionConstantValue(Instruction instruction) { + result = + getInstructionTranslatedElement(instruction).getInstructionConstantValue( + instruction.getTag()) + } + + cached StringLiteral getInstructionStringLiteral(Instruction instruction) { + result = + getInstructionTranslatedElement(instruction).getInstructionStringLiteral( + instruction.getTag()) + } + + cached Type getInstructionExceptionType(Instruction instruction) { + result = + getInstructionTranslatedElement(instruction).getInstructionExceptionType( + instruction.getTag()) + } + + cached predicate getInstructionInheritance(Instruction instruction, + Class baseClass, Class derivedClass) { + getInstructionTranslatedElement(instruction).getInstructionInheritance( + instruction.getTag(), baseClass, derivedClass) + } + + pragma[noinline] + private predicate instructionOrigin(Instruction instruction, + TranslatedElement element, InstructionTag tag) { + element = getInstructionTranslatedElement(instruction) and + tag = instruction.getTag() + } + + cached int getInstructionElementSize(Instruction instruction) { + exists(TranslatedElement element, InstructionTag tag | + instructionOrigin(instruction, element, tag) and + result = element.getInstructionElementSize(tag) + ) + } + + cached int getInstructionResultSize(Instruction instruction) { + exists(TranslatedElement element, InstructionTag tag | + instructionOrigin(instruction, element, tag) and + result = element.getInstructionResultSize(tag) + ) + } +} + +import CachedForDebugging +cached private module CachedForDebugging { + cached string getTempVariableUniqueId(IRTempVariable var) { + result = getTempVariableTranslatedElement(var).getId() + ":" + + getTempVariableTagId(var.getTag()) + } + + cached string getInstructionUniqueId(Instruction instruction) { + result = getInstructionTranslatedElement(instruction).getId() + ":" + + getInstructionTagId(instruction.getTag()) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/IRInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/IRInternal.qll index 79a47b0f807..abfb61b38e3 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/IRInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/IRInternal.qll @@ -1 +1 @@ -import IRConstruction as Construction +import IRConstruction as Construction diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/IRSanityImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/IRSanityImpl.qll index 744b2870460..f4a1d12de89 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/IRSanityImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/IRSanityImpl.qll @@ -1,3 +1,3 @@ -private import IRImpl -import InstructionSanity - +private import IRImpl +import InstructionSanity + diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/IRVariable.qll index a903e227b26..2eae3dc7c17 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/IRVariable.qll @@ -1,202 +1,202 @@ -private import IRInternal -import FunctionIR -import cpp -import semmle.code.cpp.ir.TempVariableTag -private import semmle.code.cpp.ir.internal.TempVariableTag - -private newtype TIRVariable = - TIRAutomaticUserVariable(LocalScopeVariable var, FunctionIR funcIR) { - exists(Function func | - func = funcIR.getFunction() and - ( - var.getFunction() = func or - var.(Parameter).getCatchBlock().getEnclosingFunction() = func - ) - ) - } or - TIRStaticUserVariable(Variable var, FunctionIR funcIR) { - ( - var instanceof GlobalOrNamespaceVariable or - var instanceof MemberVariable and not var instanceof Field - ) and - exists(VariableAccess access | - access.getTarget() = var and - access.getEnclosingFunction() = funcIR.getFunction() - ) - } or - TIRTempVariable(FunctionIR funcIR, Locatable ast, TempVariableTag tag, - Type type) { - Construction::hasTempVariable(funcIR.getFunction(), ast, tag, type) - } - -IRUserVariable getIRUserVariable(Function func, Variable var) { - result.getVariable() = var and - result.getFunction() = func -} - -/** - * Represents a variable referenced by the IR for a function. The variable may - * be a user-declared variable (`IRUserVariable`) or a temporary variable - * generated by the AST-to-IR translation (`IRTempVariable`). - */ -abstract class IRVariable extends TIRVariable { - FunctionIR funcIR; - - abstract string toString(); - - /** - * Gets the type of the variable. - */ - abstract Type getType(); - - /** - * Gets the AST node that declared this variable, or that introduced this - * variable as part of the AST-to-IR translation. - */ - abstract Locatable getAST(); - - /** - * Gets an identifier string for the variable. This identifier is unique - * within the function. - */ - abstract string getUniqueId(); - - /** - * Gets the source location of this variable. - */ - final Location getLocation() { - result = getAST().getLocation() - } - - /** - * Gets the IR for the function that references this variable. - */ - final FunctionIR getFunctionIR() { - result = funcIR - } - - /** - * Gets the function that references this variable. - */ - final Function getFunction() { - result = funcIR.getFunction() - } -} - -/** - * Represents a user-declared variable referenced by the IR for a function. - */ -abstract class IRUserVariable extends IRVariable { - Variable var; - - override final string toString() { - result = var.toString() - } - - override final Type getType() { - result = var.getType().getUnspecifiedType() - } - - override final Locatable getAST() { - result = var - } - - override final string getUniqueId() { - result = var.toString() + " " + var.getLocation().toString() - } - - /** - * Gets the original user-declared variable. - */ - final Variable getVariable() { - result = var - } -} - -/** - * Represents a variable (user-declared or temporary) that is allocated on the - * stack. This includes all parameters, non-static local variables, and - * temporary variables. - */ -abstract class IRAutomaticVariable extends IRVariable { -} - -class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable, - TIRAutomaticUserVariable { - LocalScopeVariable localVar; - - IRAutomaticUserVariable() { - this = TIRAutomaticUserVariable(localVar, funcIR) and - var = localVar - } - - final LocalScopeVariable getLocalVariable() { - result = localVar - } -} - -class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable { - IRStaticUserVariable() { - this = TIRStaticUserVariable(var, funcIR) - } -} - -IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) { - result.getAST() = ast and - result.getTag() = tag -} - -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Locatable ast; - TempVariableTag tag; - Type type; - - IRTempVariable() { - this = TIRTempVariable(funcIR, ast, tag, type) - } - - override final Type getType() { - result = type - } - - override final Locatable getAST() { - result = ast - } - - override final string getUniqueId() { - result = "Temp: " + Construction::getTempVariableUniqueId(this) - } - - final TempVariableTag getTag() { - result = tag - } - - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { - result = "#temp" - } -} - -class IRReturnVariable extends IRTempVariable { - IRReturnVariable() { - tag = ReturnValueTempVar() - } - - override final string toString() { - result = "#return" - } -} - -class IRThrowVariable extends IRTempVariable { - IRThrowVariable() { - tag = ThrowTempVar() - } - - override string getBaseString() { - result = "#throw" - } -} +private import IRInternal +import FunctionIR +import cpp +import semmle.code.cpp.ir.TempVariableTag +private import semmle.code.cpp.ir.internal.TempVariableTag + +private newtype TIRVariable = + TIRAutomaticUserVariable(LocalScopeVariable var, FunctionIR funcIR) { + exists(Function func | + func = funcIR.getFunction() and + ( + var.getFunction() = func or + var.(Parameter).getCatchBlock().getEnclosingFunction() = func + ) + ) + } or + TIRStaticUserVariable(Variable var, FunctionIR funcIR) { + ( + var instanceof GlobalOrNamespaceVariable or + var instanceof MemberVariable and not var instanceof Field + ) and + exists(VariableAccess access | + access.getTarget() = var and + access.getEnclosingFunction() = funcIR.getFunction() + ) + } or + TIRTempVariable(FunctionIR funcIR, Locatable ast, TempVariableTag tag, + Type type) { + Construction::hasTempVariable(funcIR.getFunction(), ast, tag, type) + } + +IRUserVariable getIRUserVariable(Function func, Variable var) { + result.getVariable() = var and + result.getFunction() = func +} + +/** + * Represents a variable referenced by the IR for a function. The variable may + * be a user-declared variable (`IRUserVariable`) or a temporary variable + * generated by the AST-to-IR translation (`IRTempVariable`). + */ +abstract class IRVariable extends TIRVariable { + FunctionIR funcIR; + + abstract string toString(); + + /** + * Gets the type of the variable. + */ + abstract Type getType(); + + /** + * Gets the AST node that declared this variable, or that introduced this + * variable as part of the AST-to-IR translation. + */ + abstract Locatable getAST(); + + /** + * Gets an identifier string for the variable. This identifier is unique + * within the function. + */ + abstract string getUniqueId(); + + /** + * Gets the source location of this variable. + */ + final Location getLocation() { + result = getAST().getLocation() + } + + /** + * Gets the IR for the function that references this variable. + */ + final FunctionIR getFunctionIR() { + result = funcIR + } + + /** + * Gets the function that references this variable. + */ + final Function getFunction() { + result = funcIR.getFunction() + } +} + +/** + * Represents a user-declared variable referenced by the IR for a function. + */ +abstract class IRUserVariable extends IRVariable { + Variable var; + + override final string toString() { + result = var.toString() + } + + override final Type getType() { + result = var.getType().getUnspecifiedType() + } + + override final Locatable getAST() { + result = var + } + + override final string getUniqueId() { + result = var.toString() + " " + var.getLocation().toString() + } + + /** + * Gets the original user-declared variable. + */ + final Variable getVariable() { + result = var + } +} + +/** + * Represents a variable (user-declared or temporary) that is allocated on the + * stack. This includes all parameters, non-static local variables, and + * temporary variables. + */ +abstract class IRAutomaticVariable extends IRVariable { +} + +class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable, + TIRAutomaticUserVariable { + LocalScopeVariable localVar; + + IRAutomaticUserVariable() { + this = TIRAutomaticUserVariable(localVar, funcIR) and + var = localVar + } + + final LocalScopeVariable getLocalVariable() { + result = localVar + } +} + +class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable { + IRStaticUserVariable() { + this = TIRStaticUserVariable(var, funcIR) + } +} + +IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) { + result.getAST() = ast and + result.getTag() = tag +} + +class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { + Locatable ast; + TempVariableTag tag; + Type type; + + IRTempVariable() { + this = TIRTempVariable(funcIR, ast, tag, type) + } + + override final Type getType() { + result = type + } + + override final Locatable getAST() { + result = ast + } + + override final string getUniqueId() { + result = "Temp: " + Construction::getTempVariableUniqueId(this) + } + + final TempVariableTag getTag() { + result = tag + } + + override string toString() { + result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { + result = "#temp" + } +} + +class IRReturnVariable extends IRTempVariable { + IRReturnVariable() { + tag = ReturnValueTempVar() + } + + override final string toString() { + result = "#return" + } +} + +class IRThrowVariable extends IRTempVariable { + IRThrowVariable() { + tag = ThrowTempVar() + } + + override string getBaseString() { + result = "#throw" + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/InstructionTag.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/InstructionTag.qll index 7961df3c0e2..d15e1aad65f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/InstructionTag.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/InstructionTag.qll @@ -1,152 +1,152 @@ -import cpp - -private predicate fieldIsInitialized(Field field) { - exists(ClassAggregateLiteral initList | - initList.isInitialized(field) - ) or - exists(ConstructorFieldInit init | - field = init.getTarget() - ) -} - -private predicate elementIsInitialized(int elementIndex) { - exists(ArrayAggregateLiteral initList | - initList.isInitialized(elementIndex) - ) -} - -newtype TInstructionTag = - OnlyInstructionTag() or // Single instruction (not including implicit Load) - InitializeThisTag() or - InitializerVariableAddressTag() or - InitializerLoadStringTag() or - InitializerStoreTag() or - ZeroPadStringConstantTag() or - ZeroPadStringElementIndexTag() or - ZeroPadStringElementAddressTag() or - ZeroPadStringStoreTag() or - AssignOperationLoadTag() or - AssignOperationConvertLeftTag() or - AssignOperationOpTag() or - AssignOperationConvertResultTag() or - AssignmentStoreTag() or - CrementLoadTag() or - CrementConstantTag() or - CrementOpTag() or - CrementStoreTag() or - EnterFunctionTag() or - ReturnValueAddressTag() or - ReturnTag() or - ExitFunctionTag() or - UnmodeledDefinitionTag() or - UnmodeledUseTag() or - SwitchBranchTag() or - CallTargetTag() or - CallTag() or - AllocationSizeTag() or - AllocationElementSizeTag() or - AllocationExtentConvertTag() or - ValueConditionConditionalBranchTag() or - ConditionValueTrueTempAddressTag() or - ConditionValueTrueConstantTag() or - ConditionValueTrueStoreTag() or - ConditionValueFalseTempAddressTag() or - ConditionValueFalseConstantTag() or - ConditionValueFalseStoreTag() or - ConditionValueResultTempAddressTag() or - ConditionValueResultLoadTag() or - BoolConversionConstantTag() or - BoolConversionCompareTag() or - LoadTag() or // Implicit load due to lvalue-to-rvalue conversion - CatchTag() or - ThrowTag() or - UnwindTag() or - InitializerFieldAddressTag(Field field) { - fieldIsInitialized(field) - } or - InitializerFieldDefaultValueTag(Field field) { - fieldIsInitialized(field) - } or - InitializerFieldDefaultValueStoreTag(Field field) { - fieldIsInitialized(field) - } or - InitializerElementIndexTag(int elementIndex) { - elementIsInitialized(elementIndex) - } or - InitializerElementAddressTag(int elementIndex) { - elementIsInitialized(elementIndex) - } or - InitializerElementDefaultValueTag(int elementIndex) { - elementIsInitialized(elementIndex) - } or - InitializerElementDefaultValueStoreTag(int elementIndex) { - elementIsInitialized(elementIndex) - } - -/** - * Gets a unique string for the instruction tag. Primarily used for generating - * instruction IDs to ensure stable IR dumps. - */ -string getInstructionTagId(TInstructionTag tag) { - tag = OnlyInstructionTag() and result = "Only" or // Single instruction (not including implicit Load) - tag = InitializerVariableAddressTag() and result = "InitVarAddr" or - tag = InitializerStoreTag() and result = "InitStore" or - tag = ZeroPadStringConstantTag() and result = "ZeroPadConst" or - tag = ZeroPadStringElementIndexTag() and result = "ZeroPadElemIndex" or - tag = ZeroPadStringElementAddressTag() and result = "ZeroPadElemAddr" or - tag = ZeroPadStringStoreTag() and result = "ZeroPadStore" or - tag = AssignOperationLoadTag() and result = "AssignOpLoad" or - tag = AssignOperationConvertLeftTag() and result = "AssignOpConvLeft" or - tag = AssignOperationOpTag() and result = "AssignOpOp" or - tag = AssignOperationConvertResultTag() and result = "AssignOpConvRes" or - tag = AssignmentStoreTag() and result = "AssignStore" or - tag = CrementLoadTag() and result = "CrementLoad" or - tag = CrementConstantTag() and result = "CrementConst" or - tag = CrementOpTag() and result = "CrementOp" or - tag = CrementStoreTag() and result = "CrementStore" or - tag = EnterFunctionTag() and result = "EnterFunc" or - tag = ReturnValueAddressTag() and result = "RetValAddr" or - tag = ReturnTag() and result = "Ret" or - tag = ExitFunctionTag() and result = "ExitFunc" or - tag = UnmodeledDefinitionTag() and result = "UnmodeledDef" or - tag = UnmodeledUseTag() and result = "UnmodeledUse" or - tag = SwitchBranchTag() and result = "SwitchBranch" or - tag = CallTargetTag() and result = "CallTarget" or - tag = CallTag() and result = "Call" or - tag = AllocationSizeTag() and result = "AllocSize" or - tag = AllocationElementSizeTag() and result = "AllocElemSize" or - tag = AllocationExtentConvertTag() and result = "AllocExtConv" or - tag = ValueConditionConditionalBranchTag() and result = "ValCondCondBranch" or - tag = ConditionValueTrueTempAddressTag() and result = "CondValTrueTempAddr" or - tag = ConditionValueTrueConstantTag() and result = "CondValTrueConst" or - tag = ConditionValueTrueStoreTag() and result = "CondValTrueStore" or - tag = ConditionValueFalseTempAddressTag() and result = "CondValFalseTempAddr" or - tag = ConditionValueFalseConstantTag() and result = "CondValFalseConst" or - tag = ConditionValueFalseStoreTag() and result = "CondValFalseStore" or - tag = ConditionValueResultTempAddressTag() and result = "CondValResTempAddr" or - tag = ConditionValueResultLoadTag() and result = "CondValResLoad" or - tag = BoolConversionConstantTag() and result = "BoolConvConst" or - tag = BoolConversionCompareTag() and result = "BoolConvComp" or - tag = LoadTag() and result = "Load" or // Implicit load due to lvalue-to-rvalue conversion - tag = CatchTag() and result = "Catch" or - tag = ThrowTag() and result = "Throw" or - tag = UnwindTag() and result = "Unwind" or - exists(Field field, Class cls, int index, string tagName | - field = cls.getCanonicalMember(index) and - ( - tag = InitializerFieldAddressTag(field) and tagName = "InitFieldAddr" or - tag = InitializerFieldDefaultValueTag(field) and tagName = "InitFieldDefVal" or - tag = InitializerFieldDefaultValueStoreTag(field) and tagName = "InitFieldDefValStore" - ) and - result = tagName + "(" + index + ")" - ) or - exists(int index, string tagName | - ( - tag = InitializerElementIndexTag(index) and tagName = "InitElemIndex" or - tag = InitializerElementAddressTag(index) and tagName = "InitElemAddr" or - tag = InitializerElementDefaultValueTag(index) and tagName = "InitElemDefVal" or - tag = InitializerElementDefaultValueStoreTag(index) and tagName = "InitElemDefValStore" - ) and - result = tagName + "(" + index + ")" - ) -} +import cpp + +private predicate fieldIsInitialized(Field field) { + exists(ClassAggregateLiteral initList | + initList.isInitialized(field) + ) or + exists(ConstructorFieldInit init | + field = init.getTarget() + ) +} + +private predicate elementIsInitialized(int elementIndex) { + exists(ArrayAggregateLiteral initList | + initList.isInitialized(elementIndex) + ) +} + +newtype TInstructionTag = + OnlyInstructionTag() or // Single instruction (not including implicit Load) + InitializeThisTag() or + InitializerVariableAddressTag() or + InitializerLoadStringTag() or + InitializerStoreTag() or + ZeroPadStringConstantTag() or + ZeroPadStringElementIndexTag() or + ZeroPadStringElementAddressTag() or + ZeroPadStringStoreTag() or + AssignOperationLoadTag() or + AssignOperationConvertLeftTag() or + AssignOperationOpTag() or + AssignOperationConvertResultTag() or + AssignmentStoreTag() or + CrementLoadTag() or + CrementConstantTag() or + CrementOpTag() or + CrementStoreTag() or + EnterFunctionTag() or + ReturnValueAddressTag() or + ReturnTag() or + ExitFunctionTag() or + UnmodeledDefinitionTag() or + UnmodeledUseTag() or + SwitchBranchTag() or + CallTargetTag() or + CallTag() or + AllocationSizeTag() or + AllocationElementSizeTag() or + AllocationExtentConvertTag() or + ValueConditionConditionalBranchTag() or + ConditionValueTrueTempAddressTag() or + ConditionValueTrueConstantTag() or + ConditionValueTrueStoreTag() or + ConditionValueFalseTempAddressTag() or + ConditionValueFalseConstantTag() or + ConditionValueFalseStoreTag() or + ConditionValueResultTempAddressTag() or + ConditionValueResultLoadTag() or + BoolConversionConstantTag() or + BoolConversionCompareTag() or + LoadTag() or // Implicit load due to lvalue-to-rvalue conversion + CatchTag() or + ThrowTag() or + UnwindTag() or + InitializerFieldAddressTag(Field field) { + fieldIsInitialized(field) + } or + InitializerFieldDefaultValueTag(Field field) { + fieldIsInitialized(field) + } or + InitializerFieldDefaultValueStoreTag(Field field) { + fieldIsInitialized(field) + } or + InitializerElementIndexTag(int elementIndex) { + elementIsInitialized(elementIndex) + } or + InitializerElementAddressTag(int elementIndex) { + elementIsInitialized(elementIndex) + } or + InitializerElementDefaultValueTag(int elementIndex) { + elementIsInitialized(elementIndex) + } or + InitializerElementDefaultValueStoreTag(int elementIndex) { + elementIsInitialized(elementIndex) + } + +/** + * Gets a unique string for the instruction tag. Primarily used for generating + * instruction IDs to ensure stable IR dumps. + */ +string getInstructionTagId(TInstructionTag tag) { + tag = OnlyInstructionTag() and result = "Only" or // Single instruction (not including implicit Load) + tag = InitializerVariableAddressTag() and result = "InitVarAddr" or + tag = InitializerStoreTag() and result = "InitStore" or + tag = ZeroPadStringConstantTag() and result = "ZeroPadConst" or + tag = ZeroPadStringElementIndexTag() and result = "ZeroPadElemIndex" or + tag = ZeroPadStringElementAddressTag() and result = "ZeroPadElemAddr" or + tag = ZeroPadStringStoreTag() and result = "ZeroPadStore" or + tag = AssignOperationLoadTag() and result = "AssignOpLoad" or + tag = AssignOperationConvertLeftTag() and result = "AssignOpConvLeft" or + tag = AssignOperationOpTag() and result = "AssignOpOp" or + tag = AssignOperationConvertResultTag() and result = "AssignOpConvRes" or + tag = AssignmentStoreTag() and result = "AssignStore" or + tag = CrementLoadTag() and result = "CrementLoad" or + tag = CrementConstantTag() and result = "CrementConst" or + tag = CrementOpTag() and result = "CrementOp" or + tag = CrementStoreTag() and result = "CrementStore" or + tag = EnterFunctionTag() and result = "EnterFunc" or + tag = ReturnValueAddressTag() and result = "RetValAddr" or + tag = ReturnTag() and result = "Ret" or + tag = ExitFunctionTag() and result = "ExitFunc" or + tag = UnmodeledDefinitionTag() and result = "UnmodeledDef" or + tag = UnmodeledUseTag() and result = "UnmodeledUse" or + tag = SwitchBranchTag() and result = "SwitchBranch" or + tag = CallTargetTag() and result = "CallTarget" or + tag = CallTag() and result = "Call" or + tag = AllocationSizeTag() and result = "AllocSize" or + tag = AllocationElementSizeTag() and result = "AllocElemSize" or + tag = AllocationExtentConvertTag() and result = "AllocExtConv" or + tag = ValueConditionConditionalBranchTag() and result = "ValCondCondBranch" or + tag = ConditionValueTrueTempAddressTag() and result = "CondValTrueTempAddr" or + tag = ConditionValueTrueConstantTag() and result = "CondValTrueConst" or + tag = ConditionValueTrueStoreTag() and result = "CondValTrueStore" or + tag = ConditionValueFalseTempAddressTag() and result = "CondValFalseTempAddr" or + tag = ConditionValueFalseConstantTag() and result = "CondValFalseConst" or + tag = ConditionValueFalseStoreTag() and result = "CondValFalseStore" or + tag = ConditionValueResultTempAddressTag() and result = "CondValResTempAddr" or + tag = ConditionValueResultLoadTag() and result = "CondValResLoad" or + tag = BoolConversionConstantTag() and result = "BoolConvConst" or + tag = BoolConversionCompareTag() and result = "BoolConvComp" or + tag = LoadTag() and result = "Load" or // Implicit load due to lvalue-to-rvalue conversion + tag = CatchTag() and result = "Catch" or + tag = ThrowTag() and result = "Throw" or + tag = UnwindTag() and result = "Unwind" or + exists(Field field, Class cls, int index, string tagName | + field = cls.getCanonicalMember(index) and + ( + tag = InitializerFieldAddressTag(field) and tagName = "InitFieldAddr" or + tag = InitializerFieldDefaultValueTag(field) and tagName = "InitFieldDefVal" or + tag = InitializerFieldDefaultValueStoreTag(field) and tagName = "InitFieldDefValStore" + ) and + result = tagName + "(" + index + ")" + ) or + exists(int index, string tagName | + ( + tag = InitializerElementIndexTag(index) and tagName = "InitElemIndex" or + tag = InitializerElementAddressTag(index) and tagName = "InitElemAddr" or + tag = InitializerElementDefaultValueTag(index) and tagName = "InitElemDefVal" or + tag = InitializerElementDefaultValueStoreTag(index) and tagName = "InitElemDefValStore" + ) and + result = tagName + "(" + index + ")" + ) +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/Opcode.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/Opcode.qll index f8d028b9d09..b76a2c272a5 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/Opcode.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/Opcode.qll @@ -1,154 +1,154 @@ -private newtype TOpcode = - TNoOp() or - TUninitialized() or - TInitializeParameter() or - TInitializeThis() or - TEnterFunction() or - TExitFunction() or - TReturnValue() or - TReturnVoid() or - TCopyValue() or - TLoad() or - TStore() or - TAdd() or - TSub() or - TMul() or - TDiv() or - TRem() or - TNegate() or - TShiftLeft() or - TShiftRight() or - TBitAnd() or - TBitOr() or - TBitXor() or - TBitComplement() or - TLogicalNot() or - TCompareEQ() or - TCompareNE() or - TCompareLT() or - TCompareGT() or - TCompareLE() or - TCompareGE() or - TPointerAdd() or - TPointerSub() or - TPointerDiff() or - TConvert() or - TConvertToBase() or - TConvertToVirtualBase() or - TConvertToDerived() or - TCheckedConvertOrNull() or - TCheckedConvertOrThrow() or - TDynamicCastToVoid() or - TVariableAddress() or - TFieldAddress() or - TFunctionAddress() or - TConstant() or - TStringConstant() or - TConditionalBranch() or - TSwitch() or - TInvoke() or - TCatchByType() or - TCatchAny() or - TThrowValue() or - TReThrow() or - TUnwind() or - TUnmodeledDefinition() or - TUnmodeledUse() or - TPhi() or - TVarArgsStart() or - TVarArgsEnd() or - TVarArg() or - TVarArgCopy() - -class Opcode extends TOpcode { - string toString() { - result = "UnknownOpcode" - } -} - -abstract class UnaryOpcode extends Opcode {} - -abstract class BinaryOpcode extends Opcode {} - -abstract class PointerArithmeticOpcode extends BinaryOpcode {} - -abstract class PointerOffsetOpcode extends PointerArithmeticOpcode {} - -abstract class CompareOpcode extends BinaryOpcode {} - -abstract class CopyOpcode extends Opcode {} - -abstract class MemoryAccessOpcode extends Opcode {} - -abstract class ReturnOpcode extends Opcode {} - -abstract class ThrowOpcode extends Opcode {} - -abstract class CatchOpcode extends Opcode {} - -abstract class OpcodeWithCondition extends Opcode {} - -abstract class BuiltInOpcode extends Opcode {} - -module Opcode { - class NoOp extends Opcode, TNoOp { override final string toString() { result = "NoOp" } } - class Uninitialized extends MemoryAccessOpcode, TUninitialized { override final string toString() { result = "Uninitialized" } } - class InitializeParameter extends MemoryAccessOpcode, TInitializeParameter { override final string toString() { result = "InitializeParameter" } } - class InitializeThis extends Opcode, TInitializeThis { override final string toString() { result = "InitializeThis" } } - class EnterFunction extends Opcode, TEnterFunction { override final string toString() { result = "EnterFunction" } } - class ExitFunction extends Opcode, TExitFunction { override final string toString() { result = "ExitFunction" } } - class ReturnValue extends ReturnOpcode, MemoryAccessOpcode, TReturnValue { override final string toString() { result = "ReturnValue" } } - class ReturnVoid extends ReturnOpcode, TReturnVoid { override final string toString() { result = "ReturnVoid" } } - class CopyValue extends CopyOpcode, TCopyValue { override final string toString() { result = "CopyValue" } } - class Load extends CopyOpcode, MemoryAccessOpcode, TLoad { override final string toString() { result = "Load" } } - class Store extends CopyOpcode, MemoryAccessOpcode, TStore { override final string toString() { result = "Store" } } - class Add extends BinaryOpcode, TAdd { override final string toString() { result = "Add" } } - class Sub extends BinaryOpcode, TSub { override final string toString() { result = "Sub" } } - class Mul extends BinaryOpcode, TMul { override final string toString() { result = "Mul" } } - class Div extends BinaryOpcode, TDiv { override final string toString() { result = "Div" } } - class Rem extends BinaryOpcode, TRem { override final string toString() { result = "Rem" } } - class Negate extends UnaryOpcode, TNegate { override final string toString() { result = "Negate" } } - class ShiftLeft extends BinaryOpcode, TShiftLeft { override final string toString() { result = "ShiftLeft" } } - class ShiftRight extends BinaryOpcode, TShiftRight { override final string toString() { result = "ShiftRight" } } - class BitAnd extends BinaryOpcode, TBitAnd { override final string toString() { result = "BitAnd" } } - class BitOr extends BinaryOpcode, TBitOr { override final string toString() { result = "BitOr" } } - class BitXor extends BinaryOpcode, TBitXor { override final string toString() { result = "BitXor" } } - class BitComplement extends UnaryOpcode, TBitComplement { override final string toString() { result = "BitComplement" } } - class LogicalNot extends UnaryOpcode, TLogicalNot { override final string toString() { result = "LogicalNot" } } - class CompareEQ extends CompareOpcode, TCompareEQ { override final string toString() { result = "CompareEQ" } } - class CompareNE extends CompareOpcode, TCompareNE { override final string toString() { result = "CompareNE" } } - class CompareLT extends CompareOpcode, TCompareLT { override final string toString() { result = "CompareLT" } } - class CompareGT extends CompareOpcode, TCompareGT { override final string toString() { result = "CompareGT" } } - class CompareLE extends CompareOpcode, TCompareLE { override final string toString() { result = "CompareLE" } } - class CompareGE extends CompareOpcode, TCompareGE { override final string toString() { result = "CompareGE" } } - class PointerAdd extends PointerOffsetOpcode, TPointerAdd { override final string toString() { result = "PointerAdd" } } - class PointerSub extends PointerOffsetOpcode, TPointerSub { override final string toString() { result = "PointerSub" } } - class PointerDiff extends PointerArithmeticOpcode, TPointerDiff { override final string toString() { result = "PointerDiff" } } - class Convert extends UnaryOpcode, TConvert { override final string toString() { result = "Convert" } } - class ConvertToBase extends UnaryOpcode, TConvertToBase { override final string toString() { result = "ConvertToBase" } } - class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase { override final string toString() { result = "ConvertToVirtualBase" } } - class ConvertToDerived extends UnaryOpcode, TConvertToDerived { override final string toString() { result = "ConvertToDerived" } } - class CheckedConvertOrNull extends UnaryOpcode, TCheckedConvertOrNull { override final string toString() { result = "CheckedConvertOrNull" } } - class CheckedConvertOrThrow extends UnaryOpcode, TCheckedConvertOrThrow { override final string toString() { result = "CheckedConvertOrThrow" } } - class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid { override final string toString() { result = "DynamicCastToVoid" } } - class VariableAddress extends Opcode, TVariableAddress { override final string toString() { result = "VariableAddress" } } - class FieldAddress extends UnaryOpcode, TFieldAddress { override final string toString() { result = "FieldAddress" } } - class FunctionAddress extends Opcode, TFunctionAddress { override final string toString() { result = "FunctionAddress" } } - class Constant extends Opcode, TConstant { override final string toString() { result = "Constant" } } - class StringConstant extends Opcode, TStringConstant { override final string toString() { result = "StringConstant" } } - class ConditionalBranch extends OpcodeWithCondition, TConditionalBranch { override final string toString() { result = "ConditionalBranch" } } - class Switch extends OpcodeWithCondition, TSwitch { override final string toString() { result = "Switch" } } - class Invoke extends Opcode, TInvoke { override final string toString() { result = "Invoke" } } - class CatchByType extends CatchOpcode, TCatchByType { override final string toString() { result = "CatchByType" } } - class CatchAny extends CatchOpcode, TCatchAny { override final string toString() { result = "CatchAny" } } - class ThrowValue extends ThrowOpcode, MemoryAccessOpcode, TThrowValue { override final string toString() { result = "ThrowValue" } } - class ReThrow extends ThrowOpcode, TReThrow { override final string toString() { result = "ReThrow" } } - class Unwind extends Opcode, TUnwind { override final string toString() { result = "Unwind" } } - class UnmodeledDefinition extends Opcode, TUnmodeledDefinition { override final string toString() { result = "UnmodeledDefinition" } } - class UnmodeledUse extends Opcode, TUnmodeledUse { override final string toString() { result = "UnmodeledUse" } } - class Phi extends Opcode, TPhi { override final string toString() { result = "Phi" } } - class VarArgsStart extends BuiltInOpcode, TVarArgsStart { override final string toString() { result = "VarArgsStart" } } - class VarArgsEnd extends BuiltInOpcode, TVarArgsEnd { override final string toString() { result = "VarArgsEnd" } } - class VarArg extends BuiltInOpcode, TVarArg { override final string toString() { result = "VarArg" } } - class VarArgCopy extends BuiltInOpcode, TVarArgCopy { override final string toString() { result = "VarArgCopy" } } -} +private newtype TOpcode = + TNoOp() or + TUninitialized() or + TInitializeParameter() or + TInitializeThis() or + TEnterFunction() or + TExitFunction() or + TReturnValue() or + TReturnVoid() or + TCopyValue() or + TLoad() or + TStore() or + TAdd() or + TSub() or + TMul() or + TDiv() or + TRem() or + TNegate() or + TShiftLeft() or + TShiftRight() or + TBitAnd() or + TBitOr() or + TBitXor() or + TBitComplement() or + TLogicalNot() or + TCompareEQ() or + TCompareNE() or + TCompareLT() or + TCompareGT() or + TCompareLE() or + TCompareGE() or + TPointerAdd() or + TPointerSub() or + TPointerDiff() or + TConvert() or + TConvertToBase() or + TConvertToVirtualBase() or + TConvertToDerived() or + TCheckedConvertOrNull() or + TCheckedConvertOrThrow() or + TDynamicCastToVoid() or + TVariableAddress() or + TFieldAddress() or + TFunctionAddress() or + TConstant() or + TStringConstant() or + TConditionalBranch() or + TSwitch() or + TInvoke() or + TCatchByType() or + TCatchAny() or + TThrowValue() or + TReThrow() or + TUnwind() or + TUnmodeledDefinition() or + TUnmodeledUse() or + TPhi() or + TVarArgsStart() or + TVarArgsEnd() or + TVarArg() or + TVarArgCopy() + +class Opcode extends TOpcode { + string toString() { + result = "UnknownOpcode" + } +} + +abstract class UnaryOpcode extends Opcode {} + +abstract class BinaryOpcode extends Opcode {} + +abstract class PointerArithmeticOpcode extends BinaryOpcode {} + +abstract class PointerOffsetOpcode extends PointerArithmeticOpcode {} + +abstract class CompareOpcode extends BinaryOpcode {} + +abstract class CopyOpcode extends Opcode {} + +abstract class MemoryAccessOpcode extends Opcode {} + +abstract class ReturnOpcode extends Opcode {} + +abstract class ThrowOpcode extends Opcode {} + +abstract class CatchOpcode extends Opcode {} + +abstract class OpcodeWithCondition extends Opcode {} + +abstract class BuiltInOpcode extends Opcode {} + +module Opcode { + class NoOp extends Opcode, TNoOp { override final string toString() { result = "NoOp" } } + class Uninitialized extends MemoryAccessOpcode, TUninitialized { override final string toString() { result = "Uninitialized" } } + class InitializeParameter extends MemoryAccessOpcode, TInitializeParameter { override final string toString() { result = "InitializeParameter" } } + class InitializeThis extends Opcode, TInitializeThis { override final string toString() { result = "InitializeThis" } } + class EnterFunction extends Opcode, TEnterFunction { override final string toString() { result = "EnterFunction" } } + class ExitFunction extends Opcode, TExitFunction { override final string toString() { result = "ExitFunction" } } + class ReturnValue extends ReturnOpcode, MemoryAccessOpcode, TReturnValue { override final string toString() { result = "ReturnValue" } } + class ReturnVoid extends ReturnOpcode, TReturnVoid { override final string toString() { result = "ReturnVoid" } } + class CopyValue extends CopyOpcode, TCopyValue { override final string toString() { result = "CopyValue" } } + class Load extends CopyOpcode, MemoryAccessOpcode, TLoad { override final string toString() { result = "Load" } } + class Store extends CopyOpcode, MemoryAccessOpcode, TStore { override final string toString() { result = "Store" } } + class Add extends BinaryOpcode, TAdd { override final string toString() { result = "Add" } } + class Sub extends BinaryOpcode, TSub { override final string toString() { result = "Sub" } } + class Mul extends BinaryOpcode, TMul { override final string toString() { result = "Mul" } } + class Div extends BinaryOpcode, TDiv { override final string toString() { result = "Div" } } + class Rem extends BinaryOpcode, TRem { override final string toString() { result = "Rem" } } + class Negate extends UnaryOpcode, TNegate { override final string toString() { result = "Negate" } } + class ShiftLeft extends BinaryOpcode, TShiftLeft { override final string toString() { result = "ShiftLeft" } } + class ShiftRight extends BinaryOpcode, TShiftRight { override final string toString() { result = "ShiftRight" } } + class BitAnd extends BinaryOpcode, TBitAnd { override final string toString() { result = "BitAnd" } } + class BitOr extends BinaryOpcode, TBitOr { override final string toString() { result = "BitOr" } } + class BitXor extends BinaryOpcode, TBitXor { override final string toString() { result = "BitXor" } } + class BitComplement extends UnaryOpcode, TBitComplement { override final string toString() { result = "BitComplement" } } + class LogicalNot extends UnaryOpcode, TLogicalNot { override final string toString() { result = "LogicalNot" } } + class CompareEQ extends CompareOpcode, TCompareEQ { override final string toString() { result = "CompareEQ" } } + class CompareNE extends CompareOpcode, TCompareNE { override final string toString() { result = "CompareNE" } } + class CompareLT extends CompareOpcode, TCompareLT { override final string toString() { result = "CompareLT" } } + class CompareGT extends CompareOpcode, TCompareGT { override final string toString() { result = "CompareGT" } } + class CompareLE extends CompareOpcode, TCompareLE { override final string toString() { result = "CompareLE" } } + class CompareGE extends CompareOpcode, TCompareGE { override final string toString() { result = "CompareGE" } } + class PointerAdd extends PointerOffsetOpcode, TPointerAdd { override final string toString() { result = "PointerAdd" } } + class PointerSub extends PointerOffsetOpcode, TPointerSub { override final string toString() { result = "PointerSub" } } + class PointerDiff extends PointerArithmeticOpcode, TPointerDiff { override final string toString() { result = "PointerDiff" } } + class Convert extends UnaryOpcode, TConvert { override final string toString() { result = "Convert" } } + class ConvertToBase extends UnaryOpcode, TConvertToBase { override final string toString() { result = "ConvertToBase" } } + class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase { override final string toString() { result = "ConvertToVirtualBase" } } + class ConvertToDerived extends UnaryOpcode, TConvertToDerived { override final string toString() { result = "ConvertToDerived" } } + class CheckedConvertOrNull extends UnaryOpcode, TCheckedConvertOrNull { override final string toString() { result = "CheckedConvertOrNull" } } + class CheckedConvertOrThrow extends UnaryOpcode, TCheckedConvertOrThrow { override final string toString() { result = "CheckedConvertOrThrow" } } + class DynamicCastToVoid extends UnaryOpcode, TDynamicCastToVoid { override final string toString() { result = "DynamicCastToVoid" } } + class VariableAddress extends Opcode, TVariableAddress { override final string toString() { result = "VariableAddress" } } + class FieldAddress extends UnaryOpcode, TFieldAddress { override final string toString() { result = "FieldAddress" } } + class FunctionAddress extends Opcode, TFunctionAddress { override final string toString() { result = "FunctionAddress" } } + class Constant extends Opcode, TConstant { override final string toString() { result = "Constant" } } + class StringConstant extends Opcode, TStringConstant { override final string toString() { result = "StringConstant" } } + class ConditionalBranch extends OpcodeWithCondition, TConditionalBranch { override final string toString() { result = "ConditionalBranch" } } + class Switch extends OpcodeWithCondition, TSwitch { override final string toString() { result = "Switch" } } + class Invoke extends Opcode, TInvoke { override final string toString() { result = "Invoke" } } + class CatchByType extends CatchOpcode, TCatchByType { override final string toString() { result = "CatchByType" } } + class CatchAny extends CatchOpcode, TCatchAny { override final string toString() { result = "CatchAny" } } + class ThrowValue extends ThrowOpcode, MemoryAccessOpcode, TThrowValue { override final string toString() { result = "ThrowValue" } } + class ReThrow extends ThrowOpcode, TReThrow { override final string toString() { result = "ReThrow" } } + class Unwind extends Opcode, TUnwind { override final string toString() { result = "Unwind" } } + class UnmodeledDefinition extends Opcode, TUnmodeledDefinition { override final string toString() { result = "UnmodeledDefinition" } } + class UnmodeledUse extends Opcode, TUnmodeledUse { override final string toString() { result = "UnmodeledUse" } } + class Phi extends Opcode, TPhi { override final string toString() { result = "Phi" } } + class VarArgsStart extends BuiltInOpcode, TVarArgsStart { override final string toString() { result = "VarArgsStart" } } + class VarArgsEnd extends BuiltInOpcode, TVarArgsEnd { override final string toString() { result = "VarArgsEnd" } } + class VarArg extends BuiltInOpcode, TVarArg { override final string toString() { result = "VarArg" } } + class VarArgCopy extends BuiltInOpcode, TVarArgCopy { override final string toString() { result = "VarArgCopy" } } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/TempVariableTag.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/TempVariableTag.qll index e2decffc6c7..bafbf300a7d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/TempVariableTag.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/TempVariableTag.qll @@ -1,12 +1,12 @@ -import cpp - -newtype TTempVariableTag = - ConditionValueTempVar() or - ReturnValueTempVar() or - ThrowTempVar() - -string getTempVariableTagId(TTempVariableTag tag) { - tag = ConditionValueTempVar() and result = "CondVal" or - tag = ReturnValueTempVar() and result = "Ret" or - tag = ThrowTempVar() and result = "Throw" -} +import cpp + +newtype TTempVariableTag = + ConditionValueTempVar() or + ReturnValueTempVar() or + ThrowTempVar() + +string getTempVariableTagId(TTempVariableTag tag) { + tag = ConditionValueTempVar() and result = "CondVal" or + tag = ReturnValueTempVar() and result = "Ret" or + tag = ThrowTempVar() and result = "Throw" +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedCondition.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedCondition.qll index dd306632747..a8597e114fd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedCondition.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedCondition.qll @@ -1,263 +1,263 @@ -import cpp -private import InstructionTag -private import Opcode -private import TranslatedElement -private import TranslatedExpr - -abstract class ConditionContext extends TranslatedElement { - abstract Instruction getChildTrueSuccessor(TranslatedCondition child); - - abstract Instruction getChildFalseSuccessor(TranslatedCondition child); -} - -TranslatedCondition getTranslatedCondition(Expr expr) { - result.getExpr() = expr -} - -abstract class TranslatedCondition extends TranslatedElement { - Expr expr; - - override final string toString() { - result = expr.toString() - } - - override final Locatable getAST() { - result = expr - } - - final ConditionContext getConditionContext() { - result = getParent() - } - - final Expr getExpr() { - result = expr - } - - override final Function getFunction() { - result = expr.getEnclosingFunction() - } - - final Type getResultType() { - result = expr.getType().getUnspecifiedType() - } -} - -abstract class TranslatedFlexibleCondition extends TranslatedCondition, - ConditionContext, TTranslatedFlexibleCondition { - TranslatedFlexibleCondition() { - this = TTranslatedFlexibleCondition(expr) - } - - override final TranslatedElement getChild(int id) { - id = 0 and result = getOperand() - } - - override final Instruction getFirstInstruction() { - result = getOperand().getFirstInstruction() - } - - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - none() - } - - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } - - override final Instruction getChildSuccessor(TranslatedElement child) { - none() - } - - abstract TranslatedCondition getOperand(); -} - -class TranslatedParenthesisCondition extends TranslatedFlexibleCondition { - ParenthesisExpr paren; - - TranslatedParenthesisCondition() { - paren = expr - } - - final override Instruction getChildTrueSuccessor(TranslatedCondition child) { - child = getOperand() and - result = getConditionContext().getChildTrueSuccessor(this) - } - - final override Instruction getChildFalseSuccessor(TranslatedCondition child) { - child = getOperand() and - result = getConditionContext().getChildFalseSuccessor(this) - } - - final override TranslatedCondition getOperand() { - result = getTranslatedCondition(paren.getExpr()) - } -} - -class TranslatedNotCondition extends TranslatedFlexibleCondition { - NotExpr notExpr; - - TranslatedNotCondition() { - notExpr = expr - } - - override Instruction getChildTrueSuccessor(TranslatedCondition child) { - child = getOperand() and - result = getConditionContext().getChildFalseSuccessor(this) - } - - override Instruction getChildFalseSuccessor(TranslatedCondition child) { - child = getOperand() and - result = getConditionContext().getChildTrueSuccessor(this) - } - - override TranslatedCondition getOperand() { - result = getTranslatedCondition(notExpr.getOperand().getFullyConverted()) - } -} - -abstract class TranslatedNativeCondition extends TranslatedCondition, - TTranslatedNativeCondition { - TranslatedNativeCondition() { - this = TTranslatedNativeCondition(expr) - } - - override final Instruction getChildSuccessor(TranslatedElement child) { - none() - } -} - -abstract class TranslatedBinaryLogicalOperation extends - TranslatedNativeCondition, ConditionContext { - BinaryLogicalOperation op; - - TranslatedBinaryLogicalOperation() { - op = expr - } - - override final TranslatedElement getChild(int id) { - id = 0 and result = getLeftOperand() or - id = 1 and result = getRightOperand() - } - - override final Instruction getFirstInstruction() { - result = getLeftOperand().getFirstInstruction() - } - - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - none() - } - - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } - - final TranslatedCondition getLeftOperand() { - result = getTranslatedCondition(op.getLeftOperand().getFullyConverted()) - } - - final TranslatedCondition getRightOperand() { - result = getTranslatedCondition(op.getRightOperand().getFullyConverted()) - } -} - -class TranslatedLogicalAndExpr extends TranslatedBinaryLogicalOperation { - TranslatedLogicalAndExpr() { - op instanceof LogicalAndExpr - } - - override Instruction getChildTrueSuccessor(TranslatedCondition child) { - ( - child = getLeftOperand() and - result = getRightOperand().getFirstInstruction() - ) or - ( - child = getRightOperand() and - result = getConditionContext().getChildTrueSuccessor(this) - ) - } - - override Instruction getChildFalseSuccessor(TranslatedCondition child) { - (child = getLeftOperand() or child = getRightOperand()) and - result = getConditionContext().getChildFalseSuccessor(this) - } -} - -class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation { - TranslatedLogicalOrExpr() { - op instanceof LogicalOrExpr - } - - override Instruction getChildTrueSuccessor(TranslatedCondition child) { - (child = getLeftOperand() or child = getRightOperand()) and - result = getConditionContext().getChildTrueSuccessor(this) - } - - override Instruction getChildFalseSuccessor(TranslatedCondition child) { - ( - child = getLeftOperand() and - result = getRightOperand().getFirstInstruction() - ) or - ( - child = getRightOperand() and - result = getConditionContext().getChildFalseSuccessor(this) - ) - } -} - -class TranslatedValueCondition extends TranslatedCondition, - TTranslatedValueCondition { - TranslatedValueCondition() { - this = TTranslatedValueCondition(expr) - } - - override TranslatedElement getChild(int id) { - id = 0 and result = getValueExpr() - } - - override Instruction getFirstInstruction() { - result = getValueExpr().getFirstInstruction() - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - tag = ValueConditionConditionalBranchTag() and - opcode instanceof Opcode::ConditionalBranch and - resultType instanceof VoidType and - isGLValue = false - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getValueExpr() and - result = getInstruction(ValueConditionConditionalBranchTag()) - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = ValueConditionConditionalBranchTag() and - ( - ( - kind instanceof TrueEdge and - result = getConditionContext().getChildTrueSuccessor(this) - ) or - ( - kind instanceof FalseEdge and - result = getConditionContext().getChildFalseSuccessor(this) - ) - ) - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - tag = ValueConditionConditionalBranchTag() and - operandTag instanceof ConditionOperand and - result = getValueExpr().getResult() - } - - private TranslatedExpr getValueExpr() { - result = getTranslatedExpr(expr) - } -} +import cpp +private import InstructionTag +private import Opcode +private import TranslatedElement +private import TranslatedExpr + +abstract class ConditionContext extends TranslatedElement { + abstract Instruction getChildTrueSuccessor(TranslatedCondition child); + + abstract Instruction getChildFalseSuccessor(TranslatedCondition child); +} + +TranslatedCondition getTranslatedCondition(Expr expr) { + result.getExpr() = expr +} + +abstract class TranslatedCondition extends TranslatedElement { + Expr expr; + + override final string toString() { + result = expr.toString() + } + + override final Locatable getAST() { + result = expr + } + + final ConditionContext getConditionContext() { + result = getParent() + } + + final Expr getExpr() { + result = expr + } + + override final Function getFunction() { + result = expr.getEnclosingFunction() + } + + final Type getResultType() { + result = expr.getType().getUnspecifiedType() + } +} + +abstract class TranslatedFlexibleCondition extends TranslatedCondition, + ConditionContext, TTranslatedFlexibleCondition { + TranslatedFlexibleCondition() { + this = TTranslatedFlexibleCondition(expr) + } + + override final TranslatedElement getChild(int id) { + id = 0 and result = getOperand() + } + + override final Instruction getFirstInstruction() { + result = getOperand().getFirstInstruction() + } + + override final predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + none() + } + + override final Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + none() + } + + override final Instruction getChildSuccessor(TranslatedElement child) { + none() + } + + abstract TranslatedCondition getOperand(); +} + +class TranslatedParenthesisCondition extends TranslatedFlexibleCondition { + ParenthesisExpr paren; + + TranslatedParenthesisCondition() { + paren = expr + } + + final override Instruction getChildTrueSuccessor(TranslatedCondition child) { + child = getOperand() and + result = getConditionContext().getChildTrueSuccessor(this) + } + + final override Instruction getChildFalseSuccessor(TranslatedCondition child) { + child = getOperand() and + result = getConditionContext().getChildFalseSuccessor(this) + } + + final override TranslatedCondition getOperand() { + result = getTranslatedCondition(paren.getExpr()) + } +} + +class TranslatedNotCondition extends TranslatedFlexibleCondition { + NotExpr notExpr; + + TranslatedNotCondition() { + notExpr = expr + } + + override Instruction getChildTrueSuccessor(TranslatedCondition child) { + child = getOperand() and + result = getConditionContext().getChildFalseSuccessor(this) + } + + override Instruction getChildFalseSuccessor(TranslatedCondition child) { + child = getOperand() and + result = getConditionContext().getChildTrueSuccessor(this) + } + + override TranslatedCondition getOperand() { + result = getTranslatedCondition(notExpr.getOperand().getFullyConverted()) + } +} + +abstract class TranslatedNativeCondition extends TranslatedCondition, + TTranslatedNativeCondition { + TranslatedNativeCondition() { + this = TTranslatedNativeCondition(expr) + } + + override final Instruction getChildSuccessor(TranslatedElement child) { + none() + } +} + +abstract class TranslatedBinaryLogicalOperation extends + TranslatedNativeCondition, ConditionContext { + BinaryLogicalOperation op; + + TranslatedBinaryLogicalOperation() { + op = expr + } + + override final TranslatedElement getChild(int id) { + id = 0 and result = getLeftOperand() or + id = 1 and result = getRightOperand() + } + + override final Instruction getFirstInstruction() { + result = getLeftOperand().getFirstInstruction() + } + + override final predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + none() + } + + override final Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + none() + } + + final TranslatedCondition getLeftOperand() { + result = getTranslatedCondition(op.getLeftOperand().getFullyConverted()) + } + + final TranslatedCondition getRightOperand() { + result = getTranslatedCondition(op.getRightOperand().getFullyConverted()) + } +} + +class TranslatedLogicalAndExpr extends TranslatedBinaryLogicalOperation { + TranslatedLogicalAndExpr() { + op instanceof LogicalAndExpr + } + + override Instruction getChildTrueSuccessor(TranslatedCondition child) { + ( + child = getLeftOperand() and + result = getRightOperand().getFirstInstruction() + ) or + ( + child = getRightOperand() and + result = getConditionContext().getChildTrueSuccessor(this) + ) + } + + override Instruction getChildFalseSuccessor(TranslatedCondition child) { + (child = getLeftOperand() or child = getRightOperand()) and + result = getConditionContext().getChildFalseSuccessor(this) + } +} + +class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation { + TranslatedLogicalOrExpr() { + op instanceof LogicalOrExpr + } + + override Instruction getChildTrueSuccessor(TranslatedCondition child) { + (child = getLeftOperand() or child = getRightOperand()) and + result = getConditionContext().getChildTrueSuccessor(this) + } + + override Instruction getChildFalseSuccessor(TranslatedCondition child) { + ( + child = getLeftOperand() and + result = getRightOperand().getFirstInstruction() + ) or + ( + child = getRightOperand() and + result = getConditionContext().getChildFalseSuccessor(this) + ) + } +} + +class TranslatedValueCondition extends TranslatedCondition, + TTranslatedValueCondition { + TranslatedValueCondition() { + this = TTranslatedValueCondition(expr) + } + + override TranslatedElement getChild(int id) { + id = 0 and result = getValueExpr() + } + + override Instruction getFirstInstruction() { + result = getValueExpr().getFirstInstruction() + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + tag = ValueConditionConditionalBranchTag() and + opcode instanceof Opcode::ConditionalBranch and + resultType instanceof VoidType and + isGLValue = false + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getValueExpr() and + result = getInstruction(ValueConditionConditionalBranchTag()) + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = ValueConditionConditionalBranchTag() and + ( + ( + kind instanceof TrueEdge and + result = getConditionContext().getChildTrueSuccessor(this) + ) or + ( + kind instanceof FalseEdge and + result = getConditionContext().getChildFalseSuccessor(this) + ) + ) + } + + override Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + tag = ValueConditionConditionalBranchTag() and + operandTag instanceof ConditionOperand and + result = getValueExpr().getResult() + } + + private TranslatedExpr getValueExpr() { + result = getTranslatedExpr(expr) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedDeclarationEntry.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedDeclarationEntry.qll index fdfa153494c..917290df884 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedDeclarationEntry.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedDeclarationEntry.qll @@ -1,226 +1,226 @@ -import cpp -private import InstructionTag -private import Opcode -private import TranslatedElement -private import TranslatedExpr -private import TranslatedInitialization - -/** - * Gets the `TranslatedDeclarationEntry` that represents the declaration - * `entry`. - */ -TranslatedDeclarationEntry getTranslatedDeclarationEntry( - DeclarationEntry entry) { - result.getAST() = entry -} - -/** - * Represents the IR translation of a declaration within the body of a function. - * Most often, this is the declaration of an automatic local variable, although - * it can also be the declaration of a static local variable, an extern - * variable, or an extern function. - */ -abstract class TranslatedDeclarationEntry extends TranslatedElement, - TTranslatedDeclarationEntry { - DeclarationEntry entry; - - TranslatedDeclarationEntry() { - this = TTranslatedDeclarationEntry(entry) - } - - override final Function getFunction() { - exists(DeclStmt stmt | - stmt.getADeclarationEntry() = entry and - result = stmt.getEnclosingFunction() - ) - } - - override final string toString() { - result = entry.toString() - } - - override final Locatable getAST() { - result = entry - } -} - -/** - * Represents the IR translation of a declaration within the body of a function, - * for declarations other than local variables. Since these have no semantic - * effect, they are translated as `NoOp`. - */ -class TranslatedNonVariableDeclaration extends - TranslatedDeclarationEntry { - TranslatedNonVariableDeclaration() { - not entry.getDeclaration() instanceof LocalVariable - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - opcode instanceof Opcode::NoOp and - tag = OnlyInstructionTag() and - resultType instanceof VoidType and - isGLValue = false - } - - override Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } - - override TranslatedElement getChild(int id) { - none() - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = OnlyInstructionTag() and - result = getParent().getChildSuccessor(this) and - kind instanceof GotoEdge - } - - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } -} - -/** - * Represents the IR translation of the declaration of a local variable, - * including its initialization, if any. - */ -abstract class TranslatedVariableDeclaration extends - TranslatedDeclarationEntry { - LocalVariable var; - - TranslatedVariableDeclaration() { - entry.getDeclaration() = var - } -} - -/** - * Represents the IR translation of a local variable with no initializer. The - * generated IR stores into the variable using an `Uninitialized` instruction, - * rather than a `Store`. - */ -class TranslatedUninitializedVariable extends - TranslatedVariableDeclaration { - TranslatedUninitializedVariable() { - not exists(Initializer init | - init.getDeclaration() = var - ) - } - - override TranslatedElement getChild(int id) { - none() - } - - override Instruction getFirstInstruction() { - result = getInstruction(InitializerVariableAddressTag()) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - ( - tag = InitializerVariableAddressTag() and - opcode instanceof Opcode::VariableAddress and - resultType = var.getType().getUnspecifiedType() and - isGLValue = true - ) or - ( - tag = InitializerStoreTag() and - opcode instanceof Opcode::Uninitialized and - resultType = var.getType().getUnspecifiedType() and - isGLValue = false - ) - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - kind instanceof GotoEdge and - ( - ( - tag = InitializerVariableAddressTag() and - result = getInstruction(InitializerStoreTag()) - ) or - ( - tag = InitializerStoreTag() and - result = getParent().getChildSuccessor(this) - ) - ) - } - - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - tag = InitializerStoreTag() and - ( - ( - operandTag instanceof LoadStoreAddressOperand and - result = getInstruction(InitializerVariableAddressTag()) - ) - ) - } - - override IRVariable getInstructionVariable(InstructionTag tag) { - tag = InitializerVariableAddressTag() and - result = getIRUserVariable(var.getFunction(), var) - } -} - -/** - * Represents the IR translation of a local variable with an initializer. - */ -class TranslatedInitializedVariable extends - TranslatedVariableDeclaration, InitializationContext { - Initializer init; - - TranslatedInitializedVariable() { - init.getDeclaration() = var - } - - override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() - } - - override Instruction getFirstInstruction() { - result = getInstruction(InitializerVariableAddressTag()) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - tag = InitializerVariableAddressTag() and - opcode instanceof Opcode::VariableAddress and - resultType = var.getType().getUnspecifiedType() and - isGLValue = true - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = InitializerVariableAddressTag() and - result = getInitialization().getFirstInstruction() and - kind instanceof GotoEdge - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitialization() and result = getParent().getChildSuccessor(this) - } - - override IRVariable getInstructionVariable(InstructionTag tag) { - tag = InitializerVariableAddressTag() and - result = getIRUserVariable(var.getFunction(), var) - } - - override Instruction getTargetAddress() { - result = getInstruction(InitializerVariableAddressTag()) - } - - override Type getTargetType() { - result = var.getType().getUnspecifiedType() - } - - private TranslatedInitialization getInitialization() { - result = getTranslatedInitialization(init.getExpr().getFullyConverted()) - } -} +import cpp +private import InstructionTag +private import Opcode +private import TranslatedElement +private import TranslatedExpr +private import TranslatedInitialization + +/** + * Gets the `TranslatedDeclarationEntry` that represents the declaration + * `entry`. + */ +TranslatedDeclarationEntry getTranslatedDeclarationEntry( + DeclarationEntry entry) { + result.getAST() = entry +} + +/** + * Represents the IR translation of a declaration within the body of a function. + * Most often, this is the declaration of an automatic local variable, although + * it can also be the declaration of a static local variable, an extern + * variable, or an extern function. + */ +abstract class TranslatedDeclarationEntry extends TranslatedElement, + TTranslatedDeclarationEntry { + DeclarationEntry entry; + + TranslatedDeclarationEntry() { + this = TTranslatedDeclarationEntry(entry) + } + + override final Function getFunction() { + exists(DeclStmt stmt | + stmt.getADeclarationEntry() = entry and + result = stmt.getEnclosingFunction() + ) + } + + override final string toString() { + result = entry.toString() + } + + override final Locatable getAST() { + result = entry + } +} + +/** + * Represents the IR translation of a declaration within the body of a function, + * for declarations other than local variables. Since these have no semantic + * effect, they are translated as `NoOp`. + */ +class TranslatedNonVariableDeclaration extends + TranslatedDeclarationEntry { + TranslatedNonVariableDeclaration() { + not entry.getDeclaration() instanceof LocalVariable + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + opcode instanceof Opcode::NoOp and + tag = OnlyInstructionTag() and + resultType instanceof VoidType and + isGLValue = false + } + + override Instruction getFirstInstruction() { + result = getInstruction(OnlyInstructionTag()) + } + + override TranslatedElement getChild(int id) { + none() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = OnlyInstructionTag() and + result = getParent().getChildSuccessor(this) and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + none() + } +} + +/** + * Represents the IR translation of the declaration of a local variable, + * including its initialization, if any. + */ +abstract class TranslatedVariableDeclaration extends + TranslatedDeclarationEntry { + LocalVariable var; + + TranslatedVariableDeclaration() { + entry.getDeclaration() = var + } +} + +/** + * Represents the IR translation of a local variable with no initializer. The + * generated IR stores into the variable using an `Uninitialized` instruction, + * rather than a `Store`. + */ +class TranslatedUninitializedVariable extends + TranslatedVariableDeclaration { + TranslatedUninitializedVariable() { + not exists(Initializer init | + init.getDeclaration() = var + ) + } + + override TranslatedElement getChild(int id) { + none() + } + + override Instruction getFirstInstruction() { + result = getInstruction(InitializerVariableAddressTag()) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + ( + tag = InitializerVariableAddressTag() and + opcode instanceof Opcode::VariableAddress and + resultType = var.getType().getUnspecifiedType() and + isGLValue = true + ) or + ( + tag = InitializerStoreTag() and + opcode instanceof Opcode::Uninitialized and + resultType = var.getType().getUnspecifiedType() and + isGLValue = false + ) + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + kind instanceof GotoEdge and + ( + ( + tag = InitializerVariableAddressTag() and + result = getInstruction(InitializerStoreTag()) + ) or + ( + tag = InitializerStoreTag() and + result = getParent().getChildSuccessor(this) + ) + ) + } + + override Instruction getChildSuccessor(TranslatedElement child) { + none() + } + + override Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + tag = InitializerStoreTag() and + ( + ( + operandTag instanceof LoadStoreAddressOperand and + result = getInstruction(InitializerVariableAddressTag()) + ) + ) + } + + override IRVariable getInstructionVariable(InstructionTag tag) { + tag = InitializerVariableAddressTag() and + result = getIRUserVariable(var.getFunction(), var) + } +} + +/** + * Represents the IR translation of a local variable with an initializer. + */ +class TranslatedInitializedVariable extends + TranslatedVariableDeclaration, InitializationContext { + Initializer init; + + TranslatedInitializedVariable() { + init.getDeclaration() = var + } + + override TranslatedElement getChild(int id) { + id = 0 and result = getInitialization() + } + + override Instruction getFirstInstruction() { + result = getInstruction(InitializerVariableAddressTag()) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + tag = InitializerVariableAddressTag() and + opcode instanceof Opcode::VariableAddress and + resultType = var.getType().getUnspecifiedType() and + isGLValue = true + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = InitializerVariableAddressTag() and + result = getInitialization().getFirstInstruction() and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getInitialization() and result = getParent().getChildSuccessor(this) + } + + override IRVariable getInstructionVariable(InstructionTag tag) { + tag = InitializerVariableAddressTag() and + result = getIRUserVariable(var.getFunction(), var) + } + + override Instruction getTargetAddress() { + result = getInstruction(InitializerVariableAddressTag()) + } + + override Type getTargetType() { + result = var.getType().getUnspecifiedType() + } + + private TranslatedInitialization getInitialization() { + result = getTranslatedInitialization(init.getExpr().getFullyConverted()) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedExpr.qll index 2bc563f22bb..22f6eb373aa 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedExpr.qll @@ -50,7 +50,7 @@ abstract class TranslatedExpr extends TranslatedElement { * Gets the type of the result produced by this expression. */ final Type getResultType() { - result = expr.getType().getUnspecifiedType() + result = expr.getType().getUnspecifiedType() } override final Locatable getAST() { @@ -303,7 +303,7 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad { } override string toString() { - result = "Load of " + expr.toString() + result = "Load of " + expr.toString() } override Instruction getFirstInstruction() { @@ -1945,7 +1945,7 @@ abstract class TranslatedAllocationSize extends TranslatedExpr, } override final predicate producesExprResult() { - none() + none() } override final Instruction getResult() { @@ -2144,7 +2144,7 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, } override final predicate producesExprResult() { - none() + none() } override Function getInstructionFunction(InstructionTag tag) { diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedFunction.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedFunction.qll index 9125d6bf7d2..68d46b400a4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedFunction.qll @@ -1,535 +1,535 @@ -import cpp -import semmle.code.cpp.ir.IR -private import InstructionTag -private import Opcode -private import TempVariableTag -private import TranslatedElement -private import TranslatedExpr -private import TranslatedInitialization -private import TranslatedStmt - -/** - * Gets the `TranslatedFunction` that represents function `func`. - */ -TranslatedFunction getTranslatedFunction(Function func) { - result.getAST() = func -} - -/** - * Represents the IR translation of a function. This is the root elements for - * all other elements associated with this function. - */ -class TranslatedFunction extends TranslatedElement, - TTranslatedFunction { - Function func; - - TranslatedFunction() { - this = TTranslatedFunction(func) - } - - override final string toString() { - result = func.toString() - } - - override final Locatable getAST() { - result = func - } - - /** - * Gets the function being translated. - */ - override final Function getFunction() { - result = func - } - - override final TranslatedElement getChild(int id) { - id = -3 and result = getConstructorInitList() or - id = -2 and result = getBody() or - id = -1 and result = getDestructorDestructionList() or - id >= 0 and result = getParameter(id) - } - - private final TranslatedConstructorInitList getConstructorInitList() { - result = getTranslatedConstructorInitList(func) - } - - private final TranslatedDestructorDestructionList getDestructorDestructionList() { - result = getTranslatedDestructorDestructionList(func) - } - - private final TranslatedStmt getBody() { - result = getTranslatedStmt(func.getEntryPoint()) - } - - private final TranslatedParameter getParameter(int index) { - result = getTranslatedParameter(func.getParameter(index)) - } - - override final Instruction getFirstInstruction() { - result = getInstruction(EnterFunctionTag()) - } - - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - kind instanceof GotoEdge and - ( - ( - tag = EnterFunctionTag() and - result = getInstruction(UnmodeledDefinitionTag()) - ) or - ( - tag = UnmodeledDefinitionTag() and - if exists(getThisType()) then - result = getInstruction(InitializeThisTag()) - else if exists(getParameter(0)) then - result = getParameter(0).getFirstInstruction() - else - result = getBody().getFirstInstruction() - ) or - ( - tag = InitializeThisTag() and - if exists(getParameter(0)) then - result = getParameter(0).getFirstInstruction() - else - result = getConstructorInitList().getFirstInstruction() - ) or - ( - tag = ReturnValueAddressTag() and - result = getInstruction(ReturnTag()) - ) or - ( - tag = ReturnTag() and - result = getInstruction(UnmodeledUseTag()) - ) or - ( - tag = UnwindTag() and - result = getInstruction(UnmodeledUseTag()) - ) or - ( - tag = UnmodeledUseTag() and - result = getInstruction(ExitFunctionTag()) - ) - ) - } - - override final Instruction getChildSuccessor(TranslatedElement child) { - exists(int paramIndex | - child = getParameter(paramIndex) and - if exists(func.getParameter(paramIndex + 1)) then - result = getParameter(paramIndex + 1).getFirstInstruction() - else - result = getConstructorInitList().getFirstInstruction() - ) or - ( - child = getConstructorInitList() and - result = getBody().getFirstInstruction() - ) or - ( - child = getBody() and - result = getReturnSuccessorInstruction() - ) or - ( - child = getDestructorDestructionList() and - if getReturnType() instanceof VoidType then - result = getInstruction(ReturnTag()) - else - result = getInstruction(ReturnValueAddressTag()) - ) - } - - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - ( - ( - tag = EnterFunctionTag() and - opcode instanceof Opcode::EnterFunction and - resultType instanceof VoidType and - isGLValue = false - ) or - ( - tag = UnmodeledDefinitionTag() and - opcode instanceof Opcode::UnmodeledDefinition and - resultType instanceof UnknownType and - isGLValue = false - ) or - ( - tag = InitializeThisTag() and - opcode instanceof Opcode::InitializeThis and - resultType = getThisType() and - isGLValue = true - ) or - ( - tag = ReturnValueAddressTag() and - opcode instanceof Opcode::VariableAddress and - resultType = getReturnType() and - not resultType instanceof VoidType and - isGLValue = true - ) or - ( - tag = ReturnTag() and - resultType instanceof VoidType and - isGLValue = false and - if getReturnType() instanceof VoidType then - opcode instanceof Opcode::ReturnVoid - else - opcode instanceof Opcode::ReturnValue - ) or - ( - tag = UnwindTag() and - opcode instanceof Opcode::Unwind and - resultType instanceof VoidType and - isGLValue = false and - ( - // Only generate the `Unwind` instruction if there is any exception - // handling present in the function. - exists(TryStmt try | - try.getEnclosingFunction() = func - ) or - exists(ThrowExpr throw | - throw.getEnclosingFunction() = func - ) - ) - ) or - ( - tag = UnmodeledUseTag() and - opcode instanceof Opcode::UnmodeledUse and - resultType instanceof VoidType and - isGLValue = false - ) or - ( - tag = ExitFunctionTag() and - opcode instanceof Opcode::ExitFunction and - resultType instanceof VoidType and - isGLValue = false - ) - ) - } - - override final Instruction getExceptionSuccessorInstruction() { - result = getInstruction(UnwindTag()) - } - - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - ( - tag = UnmodeledUseTag() and - operandTag instanceof UnmodeledUseOperand and - result.getFunction() = func and - result.hasMemoryResult() - ) or - ( - tag = ReturnTag() and - not getReturnType() instanceof VoidType and - ( - ( - operandTag instanceof LoadStoreAddressOperand and - result = getInstruction(ReturnValueAddressTag()) - ) or - ( - operandTag instanceof ReturnValueOperand and - result = getUnmodeledDefinitionInstruction() - ) - ) - ) - } - - override final IRVariable getInstructionVariable(InstructionTag tag) { - tag = ReturnValueAddressTag() and - result = getReturnVariable() - } - - override final predicate hasTempVariable(TempVariableTag tag, Type type) { - tag = ReturnValueTempVar() and - type = getReturnType() and - not type instanceof VoidType - } - - /** - * Gets the instruction to which control should flow after a `return` - * statement. - */ - final Instruction getReturnSuccessorInstruction() { - result = getDestructorDestructionList().getFirstInstruction() - } - - /** - * Gets the variable that represents the return value of this function. - */ - final IRReturnVariable getReturnVariable() { - result = getIRTempVariable(func, ReturnValueTempVar()) - } - - /** - * Gets the single `UnmodeledDefinition` instruction for this function. - */ - final Instruction getUnmodeledDefinitionInstruction() { - result = getInstruction(UnmodeledDefinitionTag()) - } - - /** - * Gets the single `InitializeThis` instruction for this function. Holds only - * if the function is an instance member function, constructor, or destructor. - */ - final Instruction getInitializeThisInstruction() { - result = getInstruction(InitializeThisTag()) - } - - /** - * Gets the type pointed to by the `this` pointer for this function (i.e. `*this`). - * Holds only if the function is an instance member function, constructor, or destructor. - */ - final Type getThisType() { - exists(MemberFunction mfunc | - mfunc = func and - not mfunc.isStatic() and - result = mfunc.getDeclaringType() - ) - } - - private final Type getReturnType() { - result = func.getType().getUnspecifiedType() - } -} - -/** - * Gets the `TranslatedParameter` that represents parameter `param`. - */ -TranslatedParameter getTranslatedParameter(Parameter param) { - result.getAST() = param -} - -/** - * Represents the IR translation of a function parameter, including the - * initialization of that parameter with the incoming argument. - */ -class TranslatedParameter extends TranslatedElement, TTranslatedParameter { - Parameter param; - - TranslatedParameter() { - this = TTranslatedParameter(param) - } - - override final string toString() { - result = param.toString() - } - - override final Locatable getAST() { - result = param - } - - override final Function getFunction() { - result = param.getFunction() or - result = param.getCatchBlock().getEnclosingFunction() - } - - override final Instruction getFirstInstruction() { - result = getInstruction(InitializerVariableAddressTag()) - } - - override final TranslatedElement getChild(int id) { - none() - } - - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - kind instanceof GotoEdge and - ( - ( - tag = InitializerVariableAddressTag() and - result = getInstruction(InitializerStoreTag()) - ) or - ( - tag = InitializerStoreTag() and - result = getParent().getChildSuccessor(this) - ) - ) - } - - override final Instruction getChildSuccessor(TranslatedElement child) { - none() - } - - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - ( - tag = InitializerVariableAddressTag() and - opcode instanceof Opcode::VariableAddress and - resultType = param.getType().getUnspecifiedType() and - isGLValue = true - ) or - ( - tag = InitializerStoreTag() and - opcode instanceof Opcode::InitializeParameter and - resultType = param.getType().getUnspecifiedType() and - isGLValue = false - ) - } - - override final IRVariable getInstructionVariable(InstructionTag tag) { - ( - tag = InitializerStoreTag() or - tag = InitializerVariableAddressTag() - ) and - result = getIRUserVariable(getFunction(), param) - } - - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - tag = InitializerStoreTag() and - ( - ( - operandTag instanceof LoadStoreAddressOperand and - result = getInstruction(InitializerVariableAddressTag()) - ) - ) - } -} - -private TranslatedConstructorInitList -getTranslatedConstructorInitList(Function func) { - result.getAST() = func -} - -/** - * Represents the IR translation of a constructor initializer list. To simplify - * the implementation of `TranslatedFunction`, a `TranslatedConstructorInitList` - * exists for every function, not just for constructors. Of course, only the - * instances for constructors can actually contain initializers. - */ -class TranslatedConstructorInitList extends TranslatedElement, - InitializationContext, TTranslatedConstructorInitList { - Function func; - - TranslatedConstructorInitList() { - this = TTranslatedConstructorInitList(func) - } - - override string toString() { - result = "ctor init: " + func.toString() - } - - override Locatable getAST() { - result = func - } - - override TranslatedElement getChild(int id) { - exists(ConstructorFieldInit fieldInit | - fieldInit = func.(Constructor).getInitializer(id) and - result = getTranslatedConstructorFieldInitialization(fieldInit) - ) or - exists(ConstructorBaseInit baseInit | - baseInit = func.(Constructor).getInitializer(id) and - result = getTranslatedConstructorBaseInit(baseInit) - ) - } - - override Instruction getFirstInstruction() { - if exists(getChild(0)) then - result = getChild(0).getFirstInstruction() - else - result = getParent().getChildSuccessor(this) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - none() - } - - override Function getFunction() { - result = func - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } - - override Instruction getChildSuccessor(TranslatedElement child) { - exists(int id | - child = getChild(id) and - if exists(getChild(id + 1)) then - result = getChild(id + 1).getFirstInstruction() - else - result = getParent().getChildSuccessor(this) - ) - } - - override Instruction getTargetAddress() { - result = getTranslatedFunction(func).getInitializeThisInstruction() - } - - override Type getTargetType() { - result = getTranslatedFunction(func).getThisType() - } -} - -private TranslatedDestructorDestructionList -getTranslatedDestructorDestructionList(Function func) { - result.getAST() = func -} - -/** - * Represents the IR translation of a destructor's implicit calls to destructors - * for fields and base classes. To simplify the implementation of `TranslatedFunction`, - * a `TranslatedDestructorDestructionList` exists for every function, not just for - * destructors. Of course, only the instances for destructors can actually contain - * destructions. - */ -class TranslatedDestructorDestructionList extends TranslatedElement, - TTranslatedDestructorDestructionList { - Function func; - - TranslatedDestructorDestructionList() { - this = TTranslatedDestructorDestructionList(func) - } - - override string toString() { - result = "dtor destruction: " + func.toString() - } - - override Locatable getAST() { - result = func - } - - override TranslatedElement getChild(int id) { - exists(DestructorFieldDestruction fieldDestruction | - fieldDestruction = func.(Destructor).getDestruction(id) and - result = getTranslatedExpr(fieldDestruction) - ) or - exists(DestructorBaseDestruction baseDestruction | - baseDestruction = func.(Destructor).getDestruction(id) and - result = getTranslatedDestructorBaseDestruction(baseDestruction) - ) - } - - override Instruction getFirstInstruction() { - if exists(getChild(0)) then - result = getChild(0).getFirstInstruction() - else - result = getParent().getChildSuccessor(this) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - none() - } - - override Function getFunction() { - result = func - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } - - override Instruction getChildSuccessor(TranslatedElement child) { - exists(int id | - child = getChild(id) and - if exists(getChild(id + 1)) then - result = getChild(id + 1).getFirstInstruction() - else - result = getParent().getChildSuccessor(this) - ) - } -} +import cpp +import semmle.code.cpp.ir.IR +private import InstructionTag +private import Opcode +private import TempVariableTag +private import TranslatedElement +private import TranslatedExpr +private import TranslatedInitialization +private import TranslatedStmt + +/** + * Gets the `TranslatedFunction` that represents function `func`. + */ +TranslatedFunction getTranslatedFunction(Function func) { + result.getAST() = func +} + +/** + * Represents the IR translation of a function. This is the root elements for + * all other elements associated with this function. + */ +class TranslatedFunction extends TranslatedElement, + TTranslatedFunction { + Function func; + + TranslatedFunction() { + this = TTranslatedFunction(func) + } + + override final string toString() { + result = func.toString() + } + + override final Locatable getAST() { + result = func + } + + /** + * Gets the function being translated. + */ + override final Function getFunction() { + result = func + } + + override final TranslatedElement getChild(int id) { + id = -3 and result = getConstructorInitList() or + id = -2 and result = getBody() or + id = -1 and result = getDestructorDestructionList() or + id >= 0 and result = getParameter(id) + } + + private final TranslatedConstructorInitList getConstructorInitList() { + result = getTranslatedConstructorInitList(func) + } + + private final TranslatedDestructorDestructionList getDestructorDestructionList() { + result = getTranslatedDestructorDestructionList(func) + } + + private final TranslatedStmt getBody() { + result = getTranslatedStmt(func.getEntryPoint()) + } + + private final TranslatedParameter getParameter(int index) { + result = getTranslatedParameter(func.getParameter(index)) + } + + override final Instruction getFirstInstruction() { + result = getInstruction(EnterFunctionTag()) + } + + override final Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + kind instanceof GotoEdge and + ( + ( + tag = EnterFunctionTag() and + result = getInstruction(UnmodeledDefinitionTag()) + ) or + ( + tag = UnmodeledDefinitionTag() and + if exists(getThisType()) then + result = getInstruction(InitializeThisTag()) + else if exists(getParameter(0)) then + result = getParameter(0).getFirstInstruction() + else + result = getBody().getFirstInstruction() + ) or + ( + tag = InitializeThisTag() and + if exists(getParameter(0)) then + result = getParameter(0).getFirstInstruction() + else + result = getConstructorInitList().getFirstInstruction() + ) or + ( + tag = ReturnValueAddressTag() and + result = getInstruction(ReturnTag()) + ) or + ( + tag = ReturnTag() and + result = getInstruction(UnmodeledUseTag()) + ) or + ( + tag = UnwindTag() and + result = getInstruction(UnmodeledUseTag()) + ) or + ( + tag = UnmodeledUseTag() and + result = getInstruction(ExitFunctionTag()) + ) + ) + } + + override final Instruction getChildSuccessor(TranslatedElement child) { + exists(int paramIndex | + child = getParameter(paramIndex) and + if exists(func.getParameter(paramIndex + 1)) then + result = getParameter(paramIndex + 1).getFirstInstruction() + else + result = getConstructorInitList().getFirstInstruction() + ) or + ( + child = getConstructorInitList() and + result = getBody().getFirstInstruction() + ) or + ( + child = getBody() and + result = getReturnSuccessorInstruction() + ) or + ( + child = getDestructorDestructionList() and + if getReturnType() instanceof VoidType then + result = getInstruction(ReturnTag()) + else + result = getInstruction(ReturnValueAddressTag()) + ) + } + + override final predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + ( + ( + tag = EnterFunctionTag() and + opcode instanceof Opcode::EnterFunction and + resultType instanceof VoidType and + isGLValue = false + ) or + ( + tag = UnmodeledDefinitionTag() and + opcode instanceof Opcode::UnmodeledDefinition and + resultType instanceof UnknownType and + isGLValue = false + ) or + ( + tag = InitializeThisTag() and + opcode instanceof Opcode::InitializeThis and + resultType = getThisType() and + isGLValue = true + ) or + ( + tag = ReturnValueAddressTag() and + opcode instanceof Opcode::VariableAddress and + resultType = getReturnType() and + not resultType instanceof VoidType and + isGLValue = true + ) or + ( + tag = ReturnTag() and + resultType instanceof VoidType and + isGLValue = false and + if getReturnType() instanceof VoidType then + opcode instanceof Opcode::ReturnVoid + else + opcode instanceof Opcode::ReturnValue + ) or + ( + tag = UnwindTag() and + opcode instanceof Opcode::Unwind and + resultType instanceof VoidType and + isGLValue = false and + ( + // Only generate the `Unwind` instruction if there is any exception + // handling present in the function. + exists(TryStmt try | + try.getEnclosingFunction() = func + ) or + exists(ThrowExpr throw | + throw.getEnclosingFunction() = func + ) + ) + ) or + ( + tag = UnmodeledUseTag() and + opcode instanceof Opcode::UnmodeledUse and + resultType instanceof VoidType and + isGLValue = false + ) or + ( + tag = ExitFunctionTag() and + opcode instanceof Opcode::ExitFunction and + resultType instanceof VoidType and + isGLValue = false + ) + ) + } + + override final Instruction getExceptionSuccessorInstruction() { + result = getInstruction(UnwindTag()) + } + + override final Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + ( + tag = UnmodeledUseTag() and + operandTag instanceof UnmodeledUseOperand and + result.getFunction() = func and + result.hasMemoryResult() + ) or + ( + tag = ReturnTag() and + not getReturnType() instanceof VoidType and + ( + ( + operandTag instanceof LoadStoreAddressOperand and + result = getInstruction(ReturnValueAddressTag()) + ) or + ( + operandTag instanceof ReturnValueOperand and + result = getUnmodeledDefinitionInstruction() + ) + ) + ) + } + + override final IRVariable getInstructionVariable(InstructionTag tag) { + tag = ReturnValueAddressTag() and + result = getReturnVariable() + } + + override final predicate hasTempVariable(TempVariableTag tag, Type type) { + tag = ReturnValueTempVar() and + type = getReturnType() and + not type instanceof VoidType + } + + /** + * Gets the instruction to which control should flow after a `return` + * statement. + */ + final Instruction getReturnSuccessorInstruction() { + result = getDestructorDestructionList().getFirstInstruction() + } + + /** + * Gets the variable that represents the return value of this function. + */ + final IRReturnVariable getReturnVariable() { + result = getIRTempVariable(func, ReturnValueTempVar()) + } + + /** + * Gets the single `UnmodeledDefinition` instruction for this function. + */ + final Instruction getUnmodeledDefinitionInstruction() { + result = getInstruction(UnmodeledDefinitionTag()) + } + + /** + * Gets the single `InitializeThis` instruction for this function. Holds only + * if the function is an instance member function, constructor, or destructor. + */ + final Instruction getInitializeThisInstruction() { + result = getInstruction(InitializeThisTag()) + } + + /** + * Gets the type pointed to by the `this` pointer for this function (i.e. `*this`). + * Holds only if the function is an instance member function, constructor, or destructor. + */ + final Type getThisType() { + exists(MemberFunction mfunc | + mfunc = func and + not mfunc.isStatic() and + result = mfunc.getDeclaringType() + ) + } + + private final Type getReturnType() { + result = func.getType().getUnspecifiedType() + } +} + +/** + * Gets the `TranslatedParameter` that represents parameter `param`. + */ +TranslatedParameter getTranslatedParameter(Parameter param) { + result.getAST() = param +} + +/** + * Represents the IR translation of a function parameter, including the + * initialization of that parameter with the incoming argument. + */ +class TranslatedParameter extends TranslatedElement, TTranslatedParameter { + Parameter param; + + TranslatedParameter() { + this = TTranslatedParameter(param) + } + + override final string toString() { + result = param.toString() + } + + override final Locatable getAST() { + result = param + } + + override final Function getFunction() { + result = param.getFunction() or + result = param.getCatchBlock().getEnclosingFunction() + } + + override final Instruction getFirstInstruction() { + result = getInstruction(InitializerVariableAddressTag()) + } + + override final TranslatedElement getChild(int id) { + none() + } + + override final Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + kind instanceof GotoEdge and + ( + ( + tag = InitializerVariableAddressTag() and + result = getInstruction(InitializerStoreTag()) + ) or + ( + tag = InitializerStoreTag() and + result = getParent().getChildSuccessor(this) + ) + ) + } + + override final Instruction getChildSuccessor(TranslatedElement child) { + none() + } + + override final predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + ( + tag = InitializerVariableAddressTag() and + opcode instanceof Opcode::VariableAddress and + resultType = param.getType().getUnspecifiedType() and + isGLValue = true + ) or + ( + tag = InitializerStoreTag() and + opcode instanceof Opcode::InitializeParameter and + resultType = param.getType().getUnspecifiedType() and + isGLValue = false + ) + } + + override final IRVariable getInstructionVariable(InstructionTag tag) { + ( + tag = InitializerStoreTag() or + tag = InitializerVariableAddressTag() + ) and + result = getIRUserVariable(getFunction(), param) + } + + override final Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + tag = InitializerStoreTag() and + ( + ( + operandTag instanceof LoadStoreAddressOperand and + result = getInstruction(InitializerVariableAddressTag()) + ) + ) + } +} + +private TranslatedConstructorInitList +getTranslatedConstructorInitList(Function func) { + result.getAST() = func +} + +/** + * Represents the IR translation of a constructor initializer list. To simplify + * the implementation of `TranslatedFunction`, a `TranslatedConstructorInitList` + * exists for every function, not just for constructors. Of course, only the + * instances for constructors can actually contain initializers. + */ +class TranslatedConstructorInitList extends TranslatedElement, + InitializationContext, TTranslatedConstructorInitList { + Function func; + + TranslatedConstructorInitList() { + this = TTranslatedConstructorInitList(func) + } + + override string toString() { + result = "ctor init: " + func.toString() + } + + override Locatable getAST() { + result = func + } + + override TranslatedElement getChild(int id) { + exists(ConstructorFieldInit fieldInit | + fieldInit = func.(Constructor).getInitializer(id) and + result = getTranslatedConstructorFieldInitialization(fieldInit) + ) or + exists(ConstructorBaseInit baseInit | + baseInit = func.(Constructor).getInitializer(id) and + result = getTranslatedConstructorBaseInit(baseInit) + ) + } + + override Instruction getFirstInstruction() { + if exists(getChild(0)) then + result = getChild(0).getFirstInstruction() + else + result = getParent().getChildSuccessor(this) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + none() + } + + override Function getFunction() { + result = func + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + none() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + exists(int id | + child = getChild(id) and + if exists(getChild(id + 1)) then + result = getChild(id + 1).getFirstInstruction() + else + result = getParent().getChildSuccessor(this) + ) + } + + override Instruction getTargetAddress() { + result = getTranslatedFunction(func).getInitializeThisInstruction() + } + + override Type getTargetType() { + result = getTranslatedFunction(func).getThisType() + } +} + +private TranslatedDestructorDestructionList +getTranslatedDestructorDestructionList(Function func) { + result.getAST() = func +} + +/** + * Represents the IR translation of a destructor's implicit calls to destructors + * for fields and base classes. To simplify the implementation of `TranslatedFunction`, + * a `TranslatedDestructorDestructionList` exists for every function, not just for + * destructors. Of course, only the instances for destructors can actually contain + * destructions. + */ +class TranslatedDestructorDestructionList extends TranslatedElement, + TTranslatedDestructorDestructionList { + Function func; + + TranslatedDestructorDestructionList() { + this = TTranslatedDestructorDestructionList(func) + } + + override string toString() { + result = "dtor destruction: " + func.toString() + } + + override Locatable getAST() { + result = func + } + + override TranslatedElement getChild(int id) { + exists(DestructorFieldDestruction fieldDestruction | + fieldDestruction = func.(Destructor).getDestruction(id) and + result = getTranslatedExpr(fieldDestruction) + ) or + exists(DestructorBaseDestruction baseDestruction | + baseDestruction = func.(Destructor).getDestruction(id) and + result = getTranslatedDestructorBaseDestruction(baseDestruction) + ) + } + + override Instruction getFirstInstruction() { + if exists(getChild(0)) then + result = getChild(0).getFirstInstruction() + else + result = getParent().getChildSuccessor(this) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + none() + } + + override Function getFunction() { + result = func + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + none() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + exists(int id | + child = getChild(id) and + if exists(getChild(id + 1)) then + result = getChild(id + 1).getFirstInstruction() + else + result = getParent().getChildSuccessor(this) + ) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedInitialization.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedInitialization.qll index 8116b2cb302..6bdee89458e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedInitialization.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedInitialization.qll @@ -1,1074 +1,1074 @@ -import cpp -private import InstructionTag -private import Opcode -private import TranslatedElement -private import TranslatedExpr -private import TranslatedFunction - -/** - * Gets the `TranslatedInitialization` for the expression `expr`. - */ -TranslatedInitialization getTranslatedInitialization(Expr expr) { - result.getExpr() = expr -} - -/** - * Base class for any `TranslatedElement` that has an initialization as a child. - * Provides the child with the address and type of the location to be - * initialized. - */ -abstract class InitializationContext extends TranslatedElement { - /** - * Gets the instruction that produces the address of the location to be - * initialized. - */ - abstract Instruction getTargetAddress(); - - /** - * Gets the type of the location to be initialized. - */ - abstract Type getTargetType(); -} - -/** - * Represents the IR translation of any initialization, whether from an - * initializer list or from a direct initializer. - */ -abstract class TranslatedInitialization extends TranslatedElement, - TTranslatedInitialization { - Expr expr; - - TranslatedInitialization() { - this = TTranslatedInitialization(expr) - } - - override final string toString() { - result = "init: " + expr.toString() - } - - override final Function getFunction() { - result = expr.getEnclosingFunction() - } - - override final Locatable getAST() { - result = expr - } - - /** - * Gets the expression that is doing the initialization. - */ - final Expr getExpr() { - result = expr - } - - /** - * Gets the initialization context that describes the location being - * initialized. - */ - final InitializationContext getContext() { - result = getParent() - } - - final TranslatedFunction getEnclosingFunction() { - result = getTranslatedFunction(expr.getEnclosingFunction()) - } -} - -/** - * Represents the IR translation of an initialization from an initializer list. - */ -abstract class TranslatedListInitialization extends TranslatedInitialization, - InitializationContext { - override Instruction getFirstInstruction() { - result = getChild(0).getFirstInstruction() - } - - override Instruction getChildSuccessor(TranslatedElement child) { - exists(int index | - child = getChild(index) and - if exists(getChild(index + 1)) then - result = getChild(index + 1).getFirstInstruction() - else - result = getParent().getChildSuccessor(this) - ) - } - - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - none() - } - - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } - - override Instruction getTargetAddress() { - result = getContext().getTargetAddress() - } - - override Type getTargetType() { - result = getContext().getTargetType() - } -} - -/** - * Represents the IR translation of an initialization of a class object from an - * initializer list. - */ -class TranslatedClassListInitialization extends - TranslatedListInitialization -{ - ClassAggregateLiteral initList; - - TranslatedClassListInitialization() { - initList = expr - } - - override TranslatedElement getChild(int id) { - exists(TranslatedFieldInitialization fieldInit | - result = fieldInit and - fieldInit = getTranslatedFieldInitialization(initList, _) and - fieldInit.getOrder() = id - ) - } -} - -/** - * Represents the IR translation of an initialization of an array from an - * initializer list. - */ -class TranslatedArrayListInitialization extends - TranslatedListInitialization { - ArrayAggregateLiteral initList; - - TranslatedArrayListInitialization() { - initList = expr - } - - override TranslatedElement getChild(int id) { - result = getTranslatedElementInitialization(initList, id) - } -} - -/** - * Represents the IR translation of an initialization from a single initializer - * expression. - */ -abstract class TranslatedDirectInitialization extends TranslatedInitialization { - TranslatedDirectInitialization() { - not expr instanceof AggregateLiteral - } - - override TranslatedElement getChild(int id) { - id = 0 and result = getInitializer() - } - - override Instruction getFirstInstruction() { - result = getInitializer().getFirstInstruction() - } - - final TranslatedExpr getInitializer() { - result = getTranslatedExpr(expr) - } -} - -/** - * Represents the IR translation of an initialization from a single initializer - * expression, where the initialization is performed via bitwise copy (as - * opposed to a constructor). - */ -class TranslatedSimpleDirectInitialization extends - TranslatedDirectInitialization { - TranslatedSimpleDirectInitialization() { - not expr instanceof ConstructorCall and - not expr instanceof StringLiteral - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - tag = InitializerStoreTag() and - opcode instanceof Opcode::Store and - resultType = getContext().getTargetType() and - isGLValue = false - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = InitializerStoreTag() and - result = getParent().getChildSuccessor(this) and - kind instanceof GotoEdge - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitializer() and result = getInstruction(InitializerStoreTag()) - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - tag = InitializerStoreTag() and - ( - ( - operandTag instanceof LoadStoreAddressOperand and - result = getContext().getTargetAddress() - ) or - ( - operandTag instanceof CopySourceOperand and - result = getInitializer().getResult() - ) - ) - } -} - -/** - * Represents the IR translation of an initialization of an array from a string - * literal. - */ -class TranslatedStringLiteralInitialization extends - TranslatedDirectInitialization { - TranslatedStringLiteralInitialization() { - expr instanceof StringLiteral - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - ( - // Load the string literal to make it a prvalue of type `char[len]` - tag = InitializerLoadStringTag() and - opcode instanceof Opcode::Load and - resultType = getInitializer().getResultType() and - isGLValue = false - ) or - ( - // Store the string into the target. - tag = InitializerStoreTag() and - opcode instanceof Opcode::Store and - resultType = getInitializer().getResultType() and - isGLValue = false - ) or - exists(int startIndex, int elementCount | - // If the initializer string isn't large enough to fill the target, then - // we have to generate another instruction sequence to store a constant - // zero into the remainder of the array. - zeroInitRange(startIndex, elementCount) and - ( - ( - // Create a constant zero whose size is the size of the remaining - // space in the target array. - tag = ZeroPadStringConstantTag() and - opcode instanceof Opcode::Constant and - resultType instanceof UnknownType and - isGLValue = false - ) or - ( - // The index of the first element to be zero initialized. - tag = ZeroPadStringElementIndexTag() and - opcode instanceof Opcode::Constant and - resultType = getIntType() and - isGLValue = false - ) or - ( - // Compute the address of the first element to be zero initialized. - tag = ZeroPadStringElementAddressTag() and - opcode instanceof Opcode::PointerAdd and - resultType = getElementType() and - isGLValue = true - ) or - ( - // Store the constant zero into the remainder of the string. - tag = ZeroPadStringStoreTag() and - opcode instanceof Opcode::Store and - resultType instanceof UnknownType and - isGLValue = false - ) - ) - ) - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - kind instanceof GotoEdge and - ( - ( - tag = InitializerLoadStringTag() and - result = getInstruction(InitializerStoreTag()) - ) or - if zeroInitRange(_, _) then ( - ( - tag = InitializerStoreTag() and - result = getInstruction(ZeroPadStringConstantTag()) - ) or - ( - tag = ZeroPadStringConstantTag() and - result = getInstruction(ZeroPadStringElementIndexTag()) - ) or - ( - tag = ZeroPadStringElementIndexTag() and - result = getInstruction(ZeroPadStringElementAddressTag()) - ) or - ( - tag = ZeroPadStringElementAddressTag() and - result = getInstruction(ZeroPadStringStoreTag()) - ) or - ( - tag = ZeroPadStringStoreTag() and - result = getParent().getChildSuccessor(this) - ) - ) - else ( - tag = InitializerStoreTag() and - result = getParent().getChildSuccessor(this) - ) - ) - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitializer() and result = getInstruction(InitializerLoadStringTag()) - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - ( - tag = InitializerLoadStringTag() and - ( - ( - operandTag instanceof LoadStoreAddressOperand and - result = getInitializer().getResult() - ) or - ( - operandTag instanceof CopySourceOperand and - result = getEnclosingFunction().getUnmodeledDefinitionInstruction() - ) - ) - ) or - ( - tag = InitializerStoreTag() and - ( - ( - operandTag instanceof LoadStoreAddressOperand and - result = getContext().getTargetAddress() - ) or - ( - operandTag instanceof CopySourceOperand and - result = getInstruction(InitializerLoadStringTag()) - ) - ) - ) or - ( - tag = ZeroPadStringElementAddressTag() and - ( - ( - operandTag instanceof LeftOperand and - result = getContext().getTargetAddress() - ) or - ( - operandTag instanceof RightOperand and - result = getInstruction(ZeroPadStringElementIndexTag()) - ) - ) - ) or - ( - tag = ZeroPadStringStoreTag() and - ( - ( - operandTag instanceof LoadStoreAddressOperand and - result = getInstruction(ZeroPadStringElementAddressTag()) - ) or - ( - operandTag instanceof CopySourceOperand and - result = getInstruction(ZeroPadStringConstantTag()) - ) - ) - ) - } - - override string getInstructionConstantValue(InstructionTag tag) { - exists(int startIndex | - zeroInitRange(startIndex, _) and - ( - ( - tag = ZeroPadStringConstantTag() and - result = "0" - ) or - ( - tag = ZeroPadStringElementIndexTag() and - result = startIndex.toString() - ) - ) - ) - } - - override int getInstructionResultSize(InstructionTag tag) { - exists(int elementCount | - zeroInitRange(_, elementCount) and - ( - tag = ZeroPadStringConstantTag() or - tag = ZeroPadStringStoreTag() - ) and - result = elementCount * getElementType().getSize() - ) - } - - private Type getElementType() { - result = getContext().getTargetType().(ArrayType).getBaseType().getUnspecifiedType() - } - - /** - * Holds if the `elementCount` array elements starting at `startIndex` must be - * zero initialized. - */ - private predicate zeroInitRange(int startIndex, int elementCount) { - exists(int targetCount | - startIndex = expr.getType().getUnspecifiedType().(ArrayType).getArraySize() and - targetCount = getContext().getTargetType().(ArrayType).getArraySize() and - elementCount = targetCount - startIndex and - elementCount > 0 - ) - } -} - -class TranslatedConstructorInitialization extends - TranslatedDirectInitialization, StructorCallContext { - ConstructorCall ctorCall; - - TranslatedConstructorInitialization() { - ctorCall = expr - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - none() - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitializer() and result = getParent().getChildSuccessor(this) - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - none() - } - - override Instruction getReceiver() { - result = getContext().getTargetAddress() - } -} - -/** - * Gets the `TranslatedFieldInitialization` for field `field` within initializer - * list `initList`. - */ -TranslatedFieldInitialization getTranslatedFieldInitialization( - ClassAggregateLiteral initList, Field field) { - result.getAST() = initList and result.getField() = field -} - -TranslatedFieldInitialization getTranslatedConstructorFieldInitialization( - ConstructorFieldInit init) { - result.getAST() = init -} - -/** - * Represents the IR translation of the initialization of a field from an - * element of an initializer list. - */ -abstract class TranslatedFieldInitialization extends TranslatedElement { - Expr ast; - Field field; - - override final string toString() { - result = ast.toString() + "." + field.toString() - } - - override final Locatable getAST() { - result = ast - } - - override final Function getFunction() { - result = ast.getEnclosingFunction() - } - - override final Instruction getFirstInstruction() { - result = getInstruction(getFieldAddressTag()) - } - - /** - * Gets the zero-based index describing the order in which this field is to be - * initialized relative to the other fields in the class. - */ - final int getOrder() { - result = field.getInitializationOrder() - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - tag = getFieldAddressTag() and - opcode instanceof Opcode::FieldAddress and - resultType = field.getType().getUnspecifiedType() and - isGLValue = true - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - tag = getFieldAddressTag() and - operandTag instanceof UnaryOperand and - result = getParent().(InitializationContext).getTargetAddress() - } - - override Field getInstructionField(InstructionTag tag) { - tag = getFieldAddressTag() and result = field - } - - final InstructionTag getFieldAddressTag() { - result = InitializerFieldAddressTag(field) - } - - final Field getField() { - result = field - } -} - -/** - * Represents the IR translation of the initialization of a field from an - * explicit element in an initializer list. - */ -class TranslatedExplicitFieldInitialization extends - TranslatedFieldInitialization, InitializationContext, - TTranslatedExplicitFieldInitialization { - Expr expr; - - TranslatedExplicitFieldInitialization() { - this = TTranslatedExplicitFieldInitialization(ast, field, expr) - } - - override Instruction getTargetAddress() { - result = getInstruction(getFieldAddressTag()) - } - - override Type getTargetType() { - result = field.getType().getUnspecifiedType() - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = getFieldAddressTag() and - result = getInitialization().getFirstInstruction() and - kind instanceof GotoEdge - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitialization() and result = getParent().getChildSuccessor(this) - } - - override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() - } - - private TranslatedInitialization getInitialization() { - result = getTranslatedInitialization(expr) - } -} - -private string getZeroValue(Type type) { - if type instanceof FloatingPointType then - result = "0.0" - else - result = "0" -} - -/** - * Represents the IR translation of the initialization of a field without a - * corresponding element in the initializer list. - */ -class TranslatedFieldValueInitialization extends - TranslatedFieldInitialization, TTranslatedFieldValueInitialization { - TranslatedFieldValueInitialization() { - this = TTranslatedFieldValueInitialization(ast, field) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType, isGLValue) or - ( - tag = getFieldDefaultValueTag() and - opcode instanceof Opcode::Constant and - resultType = field.getType().getUnspecifiedType() and - isGLValue = false - ) or - ( - tag = getFieldDefaultValueStoreTag() and - opcode instanceof Opcode::Store and - resultType = field.getType().getUnspecifiedType() and - isGLValue = false - ) - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - kind instanceof GotoEdge and - ( - ( - tag = getFieldAddressTag() and - result = getInstruction(getFieldDefaultValueTag()) - ) or - ( - tag = getFieldDefaultValueTag() and - result = getInstruction(getFieldDefaultValueStoreTag()) - ) or - ( - tag = getFieldDefaultValueStoreTag() and - result = getParent().getChildSuccessor(this) - ) - ) - } - - override string getInstructionConstantValue(InstructionTag tag) { - tag = getFieldDefaultValueTag() and - result = getZeroValue(field.getType().getUnspecifiedType()) - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - result = TranslatedFieldInitialization.super.getInstructionOperand(tag, operandTag) or - ( - tag = getFieldDefaultValueStoreTag() and - ( - ( - operandTag instanceof LoadStoreAddressOperand and - result = getInstruction(getFieldAddressTag()) - ) or - ( - operandTag instanceof CopySourceOperand and - result = getInstruction(getFieldDefaultValueTag()) - ) - ) - ) - } - - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } - - override TranslatedElement getChild(int id) { - none() - } - - private InstructionTag getFieldDefaultValueTag() { - result = InitializerFieldDefaultValueTag(field) - } - - private InstructionTag getFieldDefaultValueStoreTag() { - result = InitializerFieldDefaultValueStoreTag(field) - } -} - -/** - * Gets the `TranslatedElementInitialization` for element `elementIndex` in - * initializer list `initList`. - */ -TranslatedElementInitialization getTranslatedElementInitialization( - ArrayAggregateLiteral initList, int elementIndex) { - result.getInitList() = initList and result.getElementIndex() = elementIndex -} - -/** - * Represents the IR translation of the initialization of an array element from - * an element of an initializer list. - */ -abstract class TranslatedElementInitialization extends TranslatedElement { - ArrayAggregateLiteral initList; - - override final string toString() { - result = initList.toString() + "[" + getElementIndex().toString() + "]" - } - - override final Locatable getAST() { - result = initList - } - - override final Function getFunction() { - result = initList.getEnclosingFunction() - } - - override final Instruction getFirstInstruction() { - result = getInstruction(getElementIndexTag()) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - ( - tag = getElementIndexTag() and - opcode instanceof Opcode::Constant and - resultType = getIntType() and - isGLValue = false - ) or - ( - tag = getElementAddressTag() and - opcode instanceof Opcode::PointerAdd and - resultType = getElementType() and - isGLValue = true - ) - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = getElementIndexTag() and - result = getInstruction(getElementAddressTag()) and - kind instanceof GotoEdge - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - tag = getElementAddressTag() and - ( - ( - operandTag instanceof LeftOperand and - result = getParent().(InitializationContext).getTargetAddress() - ) or - ( - operandTag instanceof RightOperand and - result = getInstruction(getElementIndexTag()) - ) - ) - } - - override string getInstructionConstantValue(InstructionTag tag) { - tag = getElementIndexTag() and - result = getElementIndex().toString() - } - - abstract int getElementIndex(); - - final InstructionTag getElementAddressTag() { - result = InitializerElementAddressTag(getElementIndex()) - } - - final InstructionTag getElementIndexTag() { - result = InitializerElementIndexTag(getElementIndex()) - } - - final ArrayAggregateLiteral getInitList() { - result = initList - } - - final Type getElementType() { - result = initList.getType().getUnspecifiedType().(ArrayType). - getBaseType().getUnspecifiedType() - } -} - -/** - * Represents the IR translation of the initialization of an array element from - * an explicit element in an initializer list. - */ -class TranslatedExplicitElementInitialization extends - TranslatedElementInitialization, TTranslatedExplicitElementInitialization, - InitializationContext { - int elementIndex; - - TranslatedExplicitElementInitialization() { - this = TTranslatedExplicitElementInitialization(initList, elementIndex) - } - - override Instruction getTargetAddress() { - result = getInstruction(getElementAddressTag()) - } - - override Type getTargetType() { - result = getElementType() - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind) or - ( - tag = getElementAddressTag() and - result = getInitialization().getFirstInstruction() and - kind instanceof GotoEdge - ) - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitialization() and result = getParent().getChildSuccessor(this) - } - - override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() - } - - override int getElementIndex() { - result = elementIndex - } - - TranslatedInitialization getInitialization() { - result = getTranslatedInitialization( - initList.getElementExpr(elementIndex).getFullyConverted()) - } -} - -/** - * Represents the IR translation of the initialization of a range of array - * elements without corresponding elements in the initializer list. - */ -class TranslatedElementValueInitialization extends - TranslatedElementInitialization, TTranslatedElementValueInitialization { - int elementIndex; - int elementCount; - - TranslatedElementValueInitialization() { - this = TTranslatedElementValueInitialization(initList, elementIndex, - elementCount) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType, isGLValue) or - ( - tag = getElementDefaultValueTag() and - opcode instanceof Opcode::Constant and - resultType = getDefaultValueType() and - isGLValue = false - ) or - ( - tag = getElementDefaultValueStoreTag() and - opcode instanceof Opcode::Store and - resultType = getDefaultValueType() and - isGLValue = false - ) - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind) or - ( - kind instanceof GotoEdge and - ( - ( - tag = getElementAddressTag() and - result = getInstruction(getElementDefaultValueTag()) - ) or - ( - tag = getElementDefaultValueTag() and - result = getInstruction(getElementDefaultValueStoreTag()) - ) or - ( - tag = getElementDefaultValueStoreTag() and - result = getParent().getChildSuccessor(this) - ) - ) - ) - } - - override string getInstructionConstantValue(InstructionTag tag) { - result = TranslatedElementInitialization.super.getInstructionConstantValue(tag) or - ( - tag = getElementDefaultValueTag() and - result = getZeroValue(getElementType()) - ) - } - - override int getInstructionResultSize(InstructionTag tag) { - elementCount > 1 and - ( - tag = getElementDefaultValueTag() or - tag = getElementDefaultValueStoreTag() - ) and - result = elementCount * getElementType().getSize() - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - result = TranslatedElementInitialization.super.getInstructionOperand(tag, operandTag) or - ( - tag = getElementDefaultValueStoreTag() and - ( - ( - operandTag instanceof LoadStoreAddressOperand and - result = getInstruction(getElementAddressTag()) - ) or - ( - operandTag instanceof CopySourceOperand and - result = getInstruction(getElementDefaultValueTag()) - ) - ) - ) - } - - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } - - override TranslatedElement getChild(int id) { - none() - } - - override int getElementIndex() { - result = elementIndex - } - - private InstructionTag getElementDefaultValueTag() { - result = InitializerElementDefaultValueTag(elementIndex) - } - - private InstructionTag getElementDefaultValueStoreTag() { - result = InitializerElementDefaultValueStoreTag(elementIndex) - } - - private Type getDefaultValueType() { - if elementCount = 1 then - result = getElementType() - else - result instanceof UnknownType - } -} - -abstract class TranslatedStructorCallFromStructor extends TranslatedElement, StructorCallContext { - FunctionCall call; - - override final Locatable getAST() { - result = call - } - - override final TranslatedElement getChild(int id) { - id = 0 and - result = getStructorCall() - } - - override final Function getFunction() { - result = call.getEnclosingFunction() - } - - override final Instruction getChildSuccessor(TranslatedElement child) { - child = getStructorCall() and - result = getParent().getChildSuccessor(this) - } - - final TranslatedExpr getStructorCall() { - result = getTranslatedExpr(call) - } -} - -/** - * Represents the IR translation of a call to a base class constructor or - * destructor from within a derived class constructor or destructor. - */ -abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStructor { - override final Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } - - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, - boolean isGLValue) { - tag = OnlyInstructionTag() and - opcode instanceof Opcode::ConvertToBase and - resultType = call.getTarget().getDeclaringType().getUnspecifiedType() and - isGLValue = true - } - - override final Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { - tag = OnlyInstructionTag() and - kind instanceof GotoEdge and - result = getStructorCall().getFirstInstruction() - } - - override final Instruction getReceiver() { - result = getInstruction(OnlyInstructionTag()) - } - - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - tag = OnlyInstructionTag() and - operandTag instanceof UnaryOperand and - result = getTranslatedFunction(getFunction()).getInitializeThisInstruction() - } - - override final predicate getInstructionInheritance(InstructionTag tag, - Class baseClass, Class derivedClass) { - tag = OnlyInstructionTag() and - baseClass = call.getTarget().getDeclaringType().getUnspecifiedType() and - derivedClass = getFunction().getDeclaringType().getUnspecifiedType() - } -} - -/** - * Represents a call to a delegating or base class constructor from within a constructor. - */ -abstract class TranslatedConstructorCallFromConstructor extends TranslatedStructorCallFromStructor, - TTranslatedConstructorBaseInit { - TranslatedConstructorCallFromConstructor() { - this = TTranslatedConstructorBaseInit(call) - } -} - -TranslatedConstructorCallFromConstructor getTranslatedConstructorBaseInit(ConstructorBaseInit init) { - result.getAST() = init -} - -/** - * Represents the IR translation of a delegating constructor call from within a constructor. - */ -class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromConstructor { - TranslatedConstructorDelegationInit() { - call instanceof ConstructorDelegationInit - } - - override final string toString() { - result = "delegation construct: " + call.toString() - } - - override final Instruction getFirstInstruction() { - result = getStructorCall().getFirstInstruction() - } - - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, - boolean isGLValue) { - none() - } - - override final Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { - none() - } - - override final Instruction getReceiver() { - result = getTranslatedFunction(getFunction()).getInitializeThisInstruction() - } -} - -/** - * Represents the IR translation of a call to a base class constructor from within a - * derived class constructor - */ -class TranslatedConstructorBaseInit extends TranslatedConstructorCallFromConstructor, - TranslatedBaseStructorCall { - TranslatedConstructorBaseInit() { - not call instanceof ConstructorDelegationInit - } - - override final string toString() { - result = "construct base: " + call.toString() - } -} - -TranslatedDestructorBaseDestruction getTranslatedDestructorBaseDestruction(DestructorBaseDestruction destruction) { - result.getAST() = destruction -} - -/** - * Represents the IR translation of a call to a base class destructor from within a - * derived class destructor. - */ -class TranslatedDestructorBaseDestruction extends TranslatedBaseStructorCall, - TTranslatedDestructorBaseDestruction { - TranslatedDestructorBaseDestruction() { - this = TTranslatedDestructorBaseDestruction(call) - } - - override final string toString() { - result = "destroy base: " + call.toString() - } -} +import cpp +private import InstructionTag +private import Opcode +private import TranslatedElement +private import TranslatedExpr +private import TranslatedFunction + +/** + * Gets the `TranslatedInitialization` for the expression `expr`. + */ +TranslatedInitialization getTranslatedInitialization(Expr expr) { + result.getExpr() = expr +} + +/** + * Base class for any `TranslatedElement` that has an initialization as a child. + * Provides the child with the address and type of the location to be + * initialized. + */ +abstract class InitializationContext extends TranslatedElement { + /** + * Gets the instruction that produces the address of the location to be + * initialized. + */ + abstract Instruction getTargetAddress(); + + /** + * Gets the type of the location to be initialized. + */ + abstract Type getTargetType(); +} + +/** + * Represents the IR translation of any initialization, whether from an + * initializer list or from a direct initializer. + */ +abstract class TranslatedInitialization extends TranslatedElement, + TTranslatedInitialization { + Expr expr; + + TranslatedInitialization() { + this = TTranslatedInitialization(expr) + } + + override final string toString() { + result = "init: " + expr.toString() + } + + override final Function getFunction() { + result = expr.getEnclosingFunction() + } + + override final Locatable getAST() { + result = expr + } + + /** + * Gets the expression that is doing the initialization. + */ + final Expr getExpr() { + result = expr + } + + /** + * Gets the initialization context that describes the location being + * initialized. + */ + final InitializationContext getContext() { + result = getParent() + } + + final TranslatedFunction getEnclosingFunction() { + result = getTranslatedFunction(expr.getEnclosingFunction()) + } +} + +/** + * Represents the IR translation of an initialization from an initializer list. + */ +abstract class TranslatedListInitialization extends TranslatedInitialization, + InitializationContext { + override Instruction getFirstInstruction() { + result = getChild(0).getFirstInstruction() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + exists(int index | + child = getChild(index) and + if exists(getChild(index + 1)) then + result = getChild(index + 1).getFirstInstruction() + else + result = getParent().getChildSuccessor(this) + ) + } + + override final predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + none() + } + + override final Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + none() + } + + override Instruction getTargetAddress() { + result = getContext().getTargetAddress() + } + + override Type getTargetType() { + result = getContext().getTargetType() + } +} + +/** + * Represents the IR translation of an initialization of a class object from an + * initializer list. + */ +class TranslatedClassListInitialization extends + TranslatedListInitialization +{ + ClassAggregateLiteral initList; + + TranslatedClassListInitialization() { + initList = expr + } + + override TranslatedElement getChild(int id) { + exists(TranslatedFieldInitialization fieldInit | + result = fieldInit and + fieldInit = getTranslatedFieldInitialization(initList, _) and + fieldInit.getOrder() = id + ) + } +} + +/** + * Represents the IR translation of an initialization of an array from an + * initializer list. + */ +class TranslatedArrayListInitialization extends + TranslatedListInitialization { + ArrayAggregateLiteral initList; + + TranslatedArrayListInitialization() { + initList = expr + } + + override TranslatedElement getChild(int id) { + result = getTranslatedElementInitialization(initList, id) + } +} + +/** + * Represents the IR translation of an initialization from a single initializer + * expression. + */ +abstract class TranslatedDirectInitialization extends TranslatedInitialization { + TranslatedDirectInitialization() { + not expr instanceof AggregateLiteral + } + + override TranslatedElement getChild(int id) { + id = 0 and result = getInitializer() + } + + override Instruction getFirstInstruction() { + result = getInitializer().getFirstInstruction() + } + + final TranslatedExpr getInitializer() { + result = getTranslatedExpr(expr) + } +} + +/** + * Represents the IR translation of an initialization from a single initializer + * expression, where the initialization is performed via bitwise copy (as + * opposed to a constructor). + */ +class TranslatedSimpleDirectInitialization extends + TranslatedDirectInitialization { + TranslatedSimpleDirectInitialization() { + not expr instanceof ConstructorCall and + not expr instanceof StringLiteral + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + tag = InitializerStoreTag() and + opcode instanceof Opcode::Store and + resultType = getContext().getTargetType() and + isGLValue = false + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = InitializerStoreTag() and + result = getParent().getChildSuccessor(this) and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getInitializer() and result = getInstruction(InitializerStoreTag()) + } + + override Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + tag = InitializerStoreTag() and + ( + ( + operandTag instanceof LoadStoreAddressOperand and + result = getContext().getTargetAddress() + ) or + ( + operandTag instanceof CopySourceOperand and + result = getInitializer().getResult() + ) + ) + } +} + +/** + * Represents the IR translation of an initialization of an array from a string + * literal. + */ +class TranslatedStringLiteralInitialization extends + TranslatedDirectInitialization { + TranslatedStringLiteralInitialization() { + expr instanceof StringLiteral + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + ( + // Load the string literal to make it a prvalue of type `char[len]` + tag = InitializerLoadStringTag() and + opcode instanceof Opcode::Load and + resultType = getInitializer().getResultType() and + isGLValue = false + ) or + ( + // Store the string into the target. + tag = InitializerStoreTag() and + opcode instanceof Opcode::Store and + resultType = getInitializer().getResultType() and + isGLValue = false + ) or + exists(int startIndex, int elementCount | + // If the initializer string isn't large enough to fill the target, then + // we have to generate another instruction sequence to store a constant + // zero into the remainder of the array. + zeroInitRange(startIndex, elementCount) and + ( + ( + // Create a constant zero whose size is the size of the remaining + // space in the target array. + tag = ZeroPadStringConstantTag() and + opcode instanceof Opcode::Constant and + resultType instanceof UnknownType and + isGLValue = false + ) or + ( + // The index of the first element to be zero initialized. + tag = ZeroPadStringElementIndexTag() and + opcode instanceof Opcode::Constant and + resultType = getIntType() and + isGLValue = false + ) or + ( + // Compute the address of the first element to be zero initialized. + tag = ZeroPadStringElementAddressTag() and + opcode instanceof Opcode::PointerAdd and + resultType = getElementType() and + isGLValue = true + ) or + ( + // Store the constant zero into the remainder of the string. + tag = ZeroPadStringStoreTag() and + opcode instanceof Opcode::Store and + resultType instanceof UnknownType and + isGLValue = false + ) + ) + ) + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + kind instanceof GotoEdge and + ( + ( + tag = InitializerLoadStringTag() and + result = getInstruction(InitializerStoreTag()) + ) or + if zeroInitRange(_, _) then ( + ( + tag = InitializerStoreTag() and + result = getInstruction(ZeroPadStringConstantTag()) + ) or + ( + tag = ZeroPadStringConstantTag() and + result = getInstruction(ZeroPadStringElementIndexTag()) + ) or + ( + tag = ZeroPadStringElementIndexTag() and + result = getInstruction(ZeroPadStringElementAddressTag()) + ) or + ( + tag = ZeroPadStringElementAddressTag() and + result = getInstruction(ZeroPadStringStoreTag()) + ) or + ( + tag = ZeroPadStringStoreTag() and + result = getParent().getChildSuccessor(this) + ) + ) + else ( + tag = InitializerStoreTag() and + result = getParent().getChildSuccessor(this) + ) + ) + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getInitializer() and result = getInstruction(InitializerLoadStringTag()) + } + + override Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + ( + tag = InitializerLoadStringTag() and + ( + ( + operandTag instanceof LoadStoreAddressOperand and + result = getInitializer().getResult() + ) or + ( + operandTag instanceof CopySourceOperand and + result = getEnclosingFunction().getUnmodeledDefinitionInstruction() + ) + ) + ) or + ( + tag = InitializerStoreTag() and + ( + ( + operandTag instanceof LoadStoreAddressOperand and + result = getContext().getTargetAddress() + ) or + ( + operandTag instanceof CopySourceOperand and + result = getInstruction(InitializerLoadStringTag()) + ) + ) + ) or + ( + tag = ZeroPadStringElementAddressTag() and + ( + ( + operandTag instanceof LeftOperand and + result = getContext().getTargetAddress() + ) or + ( + operandTag instanceof RightOperand and + result = getInstruction(ZeroPadStringElementIndexTag()) + ) + ) + ) or + ( + tag = ZeroPadStringStoreTag() and + ( + ( + operandTag instanceof LoadStoreAddressOperand and + result = getInstruction(ZeroPadStringElementAddressTag()) + ) or + ( + operandTag instanceof CopySourceOperand and + result = getInstruction(ZeroPadStringConstantTag()) + ) + ) + ) + } + + override string getInstructionConstantValue(InstructionTag tag) { + exists(int startIndex | + zeroInitRange(startIndex, _) and + ( + ( + tag = ZeroPadStringConstantTag() and + result = "0" + ) or + ( + tag = ZeroPadStringElementIndexTag() and + result = startIndex.toString() + ) + ) + ) + } + + override int getInstructionResultSize(InstructionTag tag) { + exists(int elementCount | + zeroInitRange(_, elementCount) and + ( + tag = ZeroPadStringConstantTag() or + tag = ZeroPadStringStoreTag() + ) and + result = elementCount * getElementType().getSize() + ) + } + + private Type getElementType() { + result = getContext().getTargetType().(ArrayType).getBaseType().getUnspecifiedType() + } + + /** + * Holds if the `elementCount` array elements starting at `startIndex` must be + * zero initialized. + */ + private predicate zeroInitRange(int startIndex, int elementCount) { + exists(int targetCount | + startIndex = expr.getType().getUnspecifiedType().(ArrayType).getArraySize() and + targetCount = getContext().getTargetType().(ArrayType).getArraySize() and + elementCount = targetCount - startIndex and + elementCount > 0 + ) + } +} + +class TranslatedConstructorInitialization extends + TranslatedDirectInitialization, StructorCallContext { + ConstructorCall ctorCall; + + TranslatedConstructorInitialization() { + ctorCall = expr + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + none() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + none() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getInitializer() and result = getParent().getChildSuccessor(this) + } + + override Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + none() + } + + override Instruction getReceiver() { + result = getContext().getTargetAddress() + } +} + +/** + * Gets the `TranslatedFieldInitialization` for field `field` within initializer + * list `initList`. + */ +TranslatedFieldInitialization getTranslatedFieldInitialization( + ClassAggregateLiteral initList, Field field) { + result.getAST() = initList and result.getField() = field +} + +TranslatedFieldInitialization getTranslatedConstructorFieldInitialization( + ConstructorFieldInit init) { + result.getAST() = init +} + +/** + * Represents the IR translation of the initialization of a field from an + * element of an initializer list. + */ +abstract class TranslatedFieldInitialization extends TranslatedElement { + Expr ast; + Field field; + + override final string toString() { + result = ast.toString() + "." + field.toString() + } + + override final Locatable getAST() { + result = ast + } + + override final Function getFunction() { + result = ast.getEnclosingFunction() + } + + override final Instruction getFirstInstruction() { + result = getInstruction(getFieldAddressTag()) + } + + /** + * Gets the zero-based index describing the order in which this field is to be + * initialized relative to the other fields in the class. + */ + final int getOrder() { + result = field.getInitializationOrder() + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + tag = getFieldAddressTag() and + opcode instanceof Opcode::FieldAddress and + resultType = field.getType().getUnspecifiedType() and + isGLValue = true + } + + override Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + tag = getFieldAddressTag() and + operandTag instanceof UnaryOperand and + result = getParent().(InitializationContext).getTargetAddress() + } + + override Field getInstructionField(InstructionTag tag) { + tag = getFieldAddressTag() and result = field + } + + final InstructionTag getFieldAddressTag() { + result = InitializerFieldAddressTag(field) + } + + final Field getField() { + result = field + } +} + +/** + * Represents the IR translation of the initialization of a field from an + * explicit element in an initializer list. + */ +class TranslatedExplicitFieldInitialization extends + TranslatedFieldInitialization, InitializationContext, + TTranslatedExplicitFieldInitialization { + Expr expr; + + TranslatedExplicitFieldInitialization() { + this = TTranslatedExplicitFieldInitialization(ast, field, expr) + } + + override Instruction getTargetAddress() { + result = getInstruction(getFieldAddressTag()) + } + + override Type getTargetType() { + result = field.getType().getUnspecifiedType() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = getFieldAddressTag() and + result = getInitialization().getFirstInstruction() and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getInitialization() and result = getParent().getChildSuccessor(this) + } + + override TranslatedElement getChild(int id) { + id = 0 and result = getInitialization() + } + + private TranslatedInitialization getInitialization() { + result = getTranslatedInitialization(expr) + } +} + +private string getZeroValue(Type type) { + if type instanceof FloatingPointType then + result = "0.0" + else + result = "0" +} + +/** + * Represents the IR translation of the initialization of a field without a + * corresponding element in the initializer list. + */ +class TranslatedFieldValueInitialization extends + TranslatedFieldInitialization, TTranslatedFieldValueInitialization { + TranslatedFieldValueInitialization() { + this = TTranslatedFieldValueInitialization(ast, field) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType, isGLValue) or + ( + tag = getFieldDefaultValueTag() and + opcode instanceof Opcode::Constant and + resultType = field.getType().getUnspecifiedType() and + isGLValue = false + ) or + ( + tag = getFieldDefaultValueStoreTag() and + opcode instanceof Opcode::Store and + resultType = field.getType().getUnspecifiedType() and + isGLValue = false + ) + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + kind instanceof GotoEdge and + ( + ( + tag = getFieldAddressTag() and + result = getInstruction(getFieldDefaultValueTag()) + ) or + ( + tag = getFieldDefaultValueTag() and + result = getInstruction(getFieldDefaultValueStoreTag()) + ) or + ( + tag = getFieldDefaultValueStoreTag() and + result = getParent().getChildSuccessor(this) + ) + ) + } + + override string getInstructionConstantValue(InstructionTag tag) { + tag = getFieldDefaultValueTag() and + result = getZeroValue(field.getType().getUnspecifiedType()) + } + + override Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + result = TranslatedFieldInitialization.super.getInstructionOperand(tag, operandTag) or + ( + tag = getFieldDefaultValueStoreTag() and + ( + ( + operandTag instanceof LoadStoreAddressOperand and + result = getInstruction(getFieldAddressTag()) + ) or + ( + operandTag instanceof CopySourceOperand and + result = getInstruction(getFieldDefaultValueTag()) + ) + ) + ) + } + + override Instruction getChildSuccessor(TranslatedElement child) { + none() + } + + override TranslatedElement getChild(int id) { + none() + } + + private InstructionTag getFieldDefaultValueTag() { + result = InitializerFieldDefaultValueTag(field) + } + + private InstructionTag getFieldDefaultValueStoreTag() { + result = InitializerFieldDefaultValueStoreTag(field) + } +} + +/** + * Gets the `TranslatedElementInitialization` for element `elementIndex` in + * initializer list `initList`. + */ +TranslatedElementInitialization getTranslatedElementInitialization( + ArrayAggregateLiteral initList, int elementIndex) { + result.getInitList() = initList and result.getElementIndex() = elementIndex +} + +/** + * Represents the IR translation of the initialization of an array element from + * an element of an initializer list. + */ +abstract class TranslatedElementInitialization extends TranslatedElement { + ArrayAggregateLiteral initList; + + override final string toString() { + result = initList.toString() + "[" + getElementIndex().toString() + "]" + } + + override final Locatable getAST() { + result = initList + } + + override final Function getFunction() { + result = initList.getEnclosingFunction() + } + + override final Instruction getFirstInstruction() { + result = getInstruction(getElementIndexTag()) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + ( + tag = getElementIndexTag() and + opcode instanceof Opcode::Constant and + resultType = getIntType() and + isGLValue = false + ) or + ( + tag = getElementAddressTag() and + opcode instanceof Opcode::PointerAdd and + resultType = getElementType() and + isGLValue = true + ) + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = getElementIndexTag() and + result = getInstruction(getElementAddressTag()) and + kind instanceof GotoEdge + } + + override Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + tag = getElementAddressTag() and + ( + ( + operandTag instanceof LeftOperand and + result = getParent().(InitializationContext).getTargetAddress() + ) or + ( + operandTag instanceof RightOperand and + result = getInstruction(getElementIndexTag()) + ) + ) + } + + override string getInstructionConstantValue(InstructionTag tag) { + tag = getElementIndexTag() and + result = getElementIndex().toString() + } + + abstract int getElementIndex(); + + final InstructionTag getElementAddressTag() { + result = InitializerElementAddressTag(getElementIndex()) + } + + final InstructionTag getElementIndexTag() { + result = InitializerElementIndexTag(getElementIndex()) + } + + final ArrayAggregateLiteral getInitList() { + result = initList + } + + final Type getElementType() { + result = initList.getType().getUnspecifiedType().(ArrayType). + getBaseType().getUnspecifiedType() + } +} + +/** + * Represents the IR translation of the initialization of an array element from + * an explicit element in an initializer list. + */ +class TranslatedExplicitElementInitialization extends + TranslatedElementInitialization, TTranslatedExplicitElementInitialization, + InitializationContext { + int elementIndex; + + TranslatedExplicitElementInitialization() { + this = TTranslatedExplicitElementInitialization(initList, elementIndex) + } + + override Instruction getTargetAddress() { + result = getInstruction(getElementAddressTag()) + } + + override Type getTargetType() { + result = getElementType() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind) or + ( + tag = getElementAddressTag() and + result = getInitialization().getFirstInstruction() and + kind instanceof GotoEdge + ) + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getInitialization() and result = getParent().getChildSuccessor(this) + } + + override TranslatedElement getChild(int id) { + id = 0 and result = getInitialization() + } + + override int getElementIndex() { + result = elementIndex + } + + TranslatedInitialization getInitialization() { + result = getTranslatedInitialization( + initList.getElementExpr(elementIndex).getFullyConverted()) + } +} + +/** + * Represents the IR translation of the initialization of a range of array + * elements without corresponding elements in the initializer list. + */ +class TranslatedElementValueInitialization extends + TranslatedElementInitialization, TTranslatedElementValueInitialization { + int elementIndex; + int elementCount; + + TranslatedElementValueInitialization() { + this = TTranslatedElementValueInitialization(initList, elementIndex, + elementCount) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType, isGLValue) or + ( + tag = getElementDefaultValueTag() and + opcode instanceof Opcode::Constant and + resultType = getDefaultValueType() and + isGLValue = false + ) or + ( + tag = getElementDefaultValueStoreTag() and + opcode instanceof Opcode::Store and + resultType = getDefaultValueType() and + isGLValue = false + ) + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind) or + ( + kind instanceof GotoEdge and + ( + ( + tag = getElementAddressTag() and + result = getInstruction(getElementDefaultValueTag()) + ) or + ( + tag = getElementDefaultValueTag() and + result = getInstruction(getElementDefaultValueStoreTag()) + ) or + ( + tag = getElementDefaultValueStoreTag() and + result = getParent().getChildSuccessor(this) + ) + ) + ) + } + + override string getInstructionConstantValue(InstructionTag tag) { + result = TranslatedElementInitialization.super.getInstructionConstantValue(tag) or + ( + tag = getElementDefaultValueTag() and + result = getZeroValue(getElementType()) + ) + } + + override int getInstructionResultSize(InstructionTag tag) { + elementCount > 1 and + ( + tag = getElementDefaultValueTag() or + tag = getElementDefaultValueStoreTag() + ) and + result = elementCount * getElementType().getSize() + } + + override Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + result = TranslatedElementInitialization.super.getInstructionOperand(tag, operandTag) or + ( + tag = getElementDefaultValueStoreTag() and + ( + ( + operandTag instanceof LoadStoreAddressOperand and + result = getInstruction(getElementAddressTag()) + ) or + ( + operandTag instanceof CopySourceOperand and + result = getInstruction(getElementDefaultValueTag()) + ) + ) + ) + } + + override Instruction getChildSuccessor(TranslatedElement child) { + none() + } + + override TranslatedElement getChild(int id) { + none() + } + + override int getElementIndex() { + result = elementIndex + } + + private InstructionTag getElementDefaultValueTag() { + result = InitializerElementDefaultValueTag(elementIndex) + } + + private InstructionTag getElementDefaultValueStoreTag() { + result = InitializerElementDefaultValueStoreTag(elementIndex) + } + + private Type getDefaultValueType() { + if elementCount = 1 then + result = getElementType() + else + result instanceof UnknownType + } +} + +abstract class TranslatedStructorCallFromStructor extends TranslatedElement, StructorCallContext { + FunctionCall call; + + override final Locatable getAST() { + result = call + } + + override final TranslatedElement getChild(int id) { + id = 0 and + result = getStructorCall() + } + + override final Function getFunction() { + result = call.getEnclosingFunction() + } + + override final Instruction getChildSuccessor(TranslatedElement child) { + child = getStructorCall() and + result = getParent().getChildSuccessor(this) + } + + final TranslatedExpr getStructorCall() { + result = getTranslatedExpr(call) + } +} + +/** + * Represents the IR translation of a call to a base class constructor or + * destructor from within a derived class constructor or destructor. + */ +abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStructor { + override final Instruction getFirstInstruction() { + result = getInstruction(OnlyInstructionTag()) + } + + override final predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, + boolean isGLValue) { + tag = OnlyInstructionTag() and + opcode instanceof Opcode::ConvertToBase and + resultType = call.getTarget().getDeclaringType().getUnspecifiedType() and + isGLValue = true + } + + override final Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + tag = OnlyInstructionTag() and + kind instanceof GotoEdge and + result = getStructorCall().getFirstInstruction() + } + + override final Instruction getReceiver() { + result = getInstruction(OnlyInstructionTag()) + } + + override final Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + tag = OnlyInstructionTag() and + operandTag instanceof UnaryOperand and + result = getTranslatedFunction(getFunction()).getInitializeThisInstruction() + } + + override final predicate getInstructionInheritance(InstructionTag tag, + Class baseClass, Class derivedClass) { + tag = OnlyInstructionTag() and + baseClass = call.getTarget().getDeclaringType().getUnspecifiedType() and + derivedClass = getFunction().getDeclaringType().getUnspecifiedType() + } +} + +/** + * Represents a call to a delegating or base class constructor from within a constructor. + */ +abstract class TranslatedConstructorCallFromConstructor extends TranslatedStructorCallFromStructor, + TTranslatedConstructorBaseInit { + TranslatedConstructorCallFromConstructor() { + this = TTranslatedConstructorBaseInit(call) + } +} + +TranslatedConstructorCallFromConstructor getTranslatedConstructorBaseInit(ConstructorBaseInit init) { + result.getAST() = init +} + +/** + * Represents the IR translation of a delegating constructor call from within a constructor. + */ +class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromConstructor { + TranslatedConstructorDelegationInit() { + call instanceof ConstructorDelegationInit + } + + override final string toString() { + result = "delegation construct: " + call.toString() + } + + override final Instruction getFirstInstruction() { + result = getStructorCall().getFirstInstruction() + } + + override final predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, + boolean isGLValue) { + none() + } + + override final Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + none() + } + + override final Instruction getReceiver() { + result = getTranslatedFunction(getFunction()).getInitializeThisInstruction() + } +} + +/** + * Represents the IR translation of a call to a base class constructor from within a + * derived class constructor + */ +class TranslatedConstructorBaseInit extends TranslatedConstructorCallFromConstructor, + TranslatedBaseStructorCall { + TranslatedConstructorBaseInit() { + not call instanceof ConstructorDelegationInit + } + + override final string toString() { + result = "construct base: " + call.toString() + } +} + +TranslatedDestructorBaseDestruction getTranslatedDestructorBaseDestruction(DestructorBaseDestruction destruction) { + result.getAST() = destruction +} + +/** + * Represents the IR translation of a call to a base class destructor from within a + * derived class destructor. + */ +class TranslatedDestructorBaseDestruction extends TranslatedBaseStructorCall, + TTranslatedDestructorBaseDestruction { + TranslatedDestructorBaseDestruction() { + this = TTranslatedDestructorBaseDestruction(call) + } + + override final string toString() { + result = "destroy base: " + call.toString() + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedStmt.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedStmt.qll index 407507531da..37b2c61d8fc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedStmt.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/TranslatedStmt.qll @@ -1,753 +1,753 @@ -import cpp -private import InstructionTag -private import Opcode -private import TranslatedCondition -private import TranslatedDeclarationEntry -private import TranslatedElement -private import TranslatedExpr -private import TranslatedFunction -private import TranslatedInitialization - -TranslatedStmt getTranslatedStmt(Stmt stmt) { - result.getAST() = stmt -} - -abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt { - Stmt stmt; - - TranslatedStmt() { - this = TTranslatedStmt(stmt) - } - - override final string toString() { - result = stmt.toString() - } - - override final Locatable getAST() { - result = stmt - } - - override final Function getFunction() { - result = stmt.getEnclosingFunction() - } -} - -class TranslatedEmptyStmt extends TranslatedStmt { - TranslatedEmptyStmt() { - stmt instanceof EmptyStmt or - stmt instanceof LabelStmt or - stmt instanceof SwitchCase - } - - override TranslatedElement getChild(int id) { - none() - } - - override Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - tag = OnlyInstructionTag() and - opcode instanceof Opcode::NoOp and - resultType instanceof VoidType and - isGLValue = false - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = OnlyInstructionTag() and - result = getParent().getChildSuccessor(this) and - kind instanceof GotoEdge - } - - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } -} - -class TranslatedDeclStmt extends TranslatedStmt { - DeclStmt declStmt; - - TranslatedDeclStmt() { - declStmt = stmt - } - - override TranslatedElement getChild(int id) { - result = getDeclarationEntry(id) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - none() - } - - override Instruction getFirstInstruction() { - result = getDeclarationEntry(0).getFirstInstruction() //REVIEW: Empty? - } - - private int getChildCount() { - result = declStmt.getNumDeclarations() - } - - private TranslatedDeclarationEntry getDeclarationEntry(int index) { - result = getTranslatedDeclarationEntry(declStmt.getDeclarationEntry(index)) - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } - - override Instruction getChildSuccessor(TranslatedElement child) { - exists(int index | - child = getDeclarationEntry(index) and - if index = (getChildCount() - 1) then - result = getParent().getChildSuccessor(this) - else - result = getDeclarationEntry(index + 1).getFirstInstruction() - ) - } -} - -class TranslatedExprStmt extends TranslatedStmt { - TranslatedExprStmt() { - stmt instanceof ExprStmt - } - - TranslatedExpr getExpr() { - result = getTranslatedExpr(stmt.(ExprStmt).getExpr().getFullyConverted()) - } - - override TranslatedElement getChild(int id) { - id = 0 and result = getExpr() - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - none() - } - - override Instruction getFirstInstruction() { - result = getExpr().getFirstInstruction() - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getExpr() and - result = getParent().getChildSuccessor(this) - } -} - -abstract class TranslatedReturnStmt extends TranslatedStmt { - ReturnStmt returnStmt; - - TranslatedReturnStmt() { - returnStmt = stmt - } - - final TranslatedFunction getEnclosingFunction() { - result = getTranslatedFunction(returnStmt.getEnclosingFunction()) - } -} - -class TranslatedReturnValueStmt extends TranslatedReturnStmt, - InitializationContext { - TranslatedReturnValueStmt() { - returnStmt.hasExpr() - } - - override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() - } - - override Instruction getFirstInstruction() { - result = getInstruction(InitializerVariableAddressTag()) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - tag = InitializerVariableAddressTag() and - opcode instanceof Opcode::VariableAddress and - resultType = getEnclosingFunction().getReturnVariable().getType() and - isGLValue = true - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = InitializerVariableAddressTag() and - result = getInitialization().getFirstInstruction() and - kind instanceof GotoEdge - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getInitialization() and - result = getEnclosingFunction().getReturnSuccessorInstruction() - } - - override IRVariable getInstructionVariable(InstructionTag tag) { - tag = InitializerVariableAddressTag() and - result = getEnclosingFunction().getReturnVariable() - } - - override Instruction getTargetAddress() { - result = getInstruction(InitializerVariableAddressTag()) - } - - override Type getTargetType() { - result = getEnclosingFunction().getReturnVariable().getType() - } - - TranslatedInitialization getInitialization() { - result = getTranslatedInitialization( - returnStmt.getExpr().getFullyConverted()) - } -} - -class TranslatedReturnVoidStmt extends TranslatedReturnStmt { - TranslatedReturnVoidStmt() { - not returnStmt.hasExpr() - } - - override TranslatedElement getChild(int id) { - none() - } - - override Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - tag = OnlyInstructionTag() and - opcode instanceof Opcode::NoOp and - resultType instanceof VoidType and - isGLValue = false - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = OnlyInstructionTag() and - result = getEnclosingFunction().getReturnSuccessorInstruction() and - kind instanceof GotoEdge - } - - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } -} - -/** - * The IR translation of a C++ `try` statement. - */ -class TranslatedTryStmt extends TranslatedStmt { - TryStmt try; - - TranslatedTryStmt() { - try = stmt - } - - override TranslatedElement getChild(int id) { - id = 0 and result = getBody() or - result = getHandler(id - 1) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - none() - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } - - override Instruction getFirstInstruction() { - result = getBody().getFirstInstruction() - } - - override Instruction getChildSuccessor(TranslatedElement child) { - // All children go to the successor of the `try`. - child = getAChild() and result = getParent().getChildSuccessor(this) - } - - final Instruction getNextHandler(TranslatedHandler handler) { - exists(int index | - handler = getHandler(index) and - result = getHandler(index + 1).getFirstInstruction() - ) or - ( - // The last catch clause flows to the exception successor of the parent - // of the `try`, because the exception successor of the `try` itself is - // the first catch clause. - handler = getHandler(try.getNumberOfCatchClauses()) and - result = getParent().getExceptionSuccessorInstruction() - ) - } - - override final Instruction getExceptionSuccessorInstruction() { - result = getHandler(0).getFirstInstruction() - } - - private TranslatedHandler getHandler(int index) { - result = getTranslatedStmt(try.getChild(index + 1)) - } - - private TranslatedStmt getBody() { - result = getTranslatedStmt(try.getStmt()) - } -} - -class TranslatedBlock extends TranslatedStmt { - Block block; - - TranslatedBlock() { - block = stmt - } - - override TranslatedElement getChild(int id) { - result = getStmt(id) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - isEmpty() and - opcode instanceof Opcode::NoOp and - tag = OnlyInstructionTag() and - resultType instanceof VoidType and - isGLValue = false - } - - override Instruction getFirstInstruction() { - if isEmpty() then - result = getInstruction(OnlyInstructionTag()) - else - result = getStmt(0).getFirstInstruction() - } - - private predicate isEmpty() { - not exists(block.getStmt(0)) - } - - private TranslatedStmt getStmt(int index) { - result = getTranslatedStmt(block.getStmt(index)) - } - - private int getStmtCount() { - result = block.getNumStmt() - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = OnlyInstructionTag() and - result = getParent().getChildSuccessor(this) and - kind instanceof GotoEdge - } - - override Instruction getChildSuccessor(TranslatedElement child) { - exists(int index | - child = getStmt(index) and - if index = (getStmtCount() - 1) then - result = getParent().getChildSuccessor(this) - else - result = getStmt(index + 1).getFirstInstruction() - ) - } -} - -/** - * The IR translation of a C++ `catch` handler. - */ -abstract class TranslatedHandler extends TranslatedStmt { - Handler handler; - - TranslatedHandler() { - handler = stmt - } - - override TranslatedElement getChild(int id) { - id = 1 and result = getBlock() - } - - override Instruction getFirstInstruction() { - result = getInstruction(CatchTag()) - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getBlock() and result = getParent().getChildSuccessor(this) - } - - override Instruction getExceptionSuccessorInstruction() { - // A throw from within a `catch` block flows to the handler for the parent of - // the `try`. - result = getParent().getParent().getExceptionSuccessorInstruction() - } - - TranslatedStmt getBlock() { - result = getTranslatedStmt(handler.getBlock()) - } -} - -/** - * The IR translation of a C++ `catch` block that catches an exception with a - * specific type (e.g. `catch (const std::exception&)`). - */ -class TranslatedCatchByTypeHandler extends TranslatedHandler { - TranslatedCatchByTypeHandler() { - exists(handler.getParameter()) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - tag = CatchTag() and - opcode instanceof Opcode::CatchByType and - resultType instanceof VoidType and - isGLValue = false - } - - override TranslatedElement getChild(int id) { - result = super.getChild(id) or - id = 0 and result = getParameter() - } - - override Instruction getChildSuccessor(TranslatedElement child) { - result = super.getChildSuccessor(child) or - child = getParameter() and result = getBlock().getFirstInstruction() - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = CatchTag() and - ( - ( - kind instanceof GotoEdge and - result = getParameter().getFirstInstruction() - ) or - ( - kind instanceof ExceptionEdge and - result = getParent().(TranslatedTryStmt).getNextHandler(this) - ) - ) - } - - override Type getInstructionExceptionType(InstructionTag tag) { - tag = CatchTag() and - result = handler.getParameter().getType() - } - - private TranslatedParameter getParameter() { - result = getTranslatedParameter(handler.getParameter()) - } -} - -/** - * The IR translation of a C++ `catch (...)` block. - */ -class TranslatedCatchAnyHandler extends TranslatedHandler { - TranslatedCatchAnyHandler() { - not exists(handler.getParameter()) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - tag = CatchTag() and - opcode instanceof Opcode::CatchAny and - resultType instanceof VoidType and - isGLValue = false - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = CatchTag() and - kind instanceof GotoEdge and - result = getBlock().getFirstInstruction() - } -} - -class TranslatedIfStmt extends TranslatedStmt, ConditionContext { - IfStmt ifStmt; - - TranslatedIfStmt() { - stmt = ifStmt - } - - override Instruction getFirstInstruction() { - result = getCondition().getFirstInstruction() - } - - override TranslatedElement getChild(int id) { - id = 0 and result = getCondition() or - id = 1 and result = getThen() or - id = 2 and result = getElse() - } - - private TranslatedCondition getCondition() { - result = getTranslatedCondition(ifStmt.getCondition().getFullyConverted()) - } - - private TranslatedStmt getThen() { - result = getTranslatedStmt(ifStmt.getThen()) - } - - private TranslatedStmt getElse() { - result = getTranslatedStmt(ifStmt.getElse()) - } - - private predicate hasElse() { - exists(ifStmt.getElse()) - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } - - override Instruction getChildTrueSuccessor(TranslatedCondition child) { - child = getCondition() and - result = getThen().getFirstInstruction() - } - - override Instruction getChildFalseSuccessor(TranslatedCondition child) { - child = getCondition() and - if hasElse() then - result = getElse().getFirstInstruction() - else - result = getParent().getChildSuccessor(this) - } - - override Instruction getChildSuccessor(TranslatedElement child) { - (child = getThen() or child = getElse()) and - result = getParent().getChildSuccessor(this) - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - none() - } -} - -abstract class TranslatedLoop extends TranslatedStmt, ConditionContext { - Loop loop; - - TranslatedLoop() { - loop = stmt - } - - final TranslatedCondition getCondition() { - result = getTranslatedCondition(loop.getCondition().getFullyConverted()) - } - - final TranslatedStmt getBody() { - result = getTranslatedStmt(loop.getStmt()) - } - - final Instruction getFirstConditionInstruction() { - if hasCondition() then - result = getCondition().getFirstInstruction() - else - result = getBody().getFirstInstruction() - } - - final predicate hasCondition() { - exists(loop.getCondition()) - } - - override TranslatedElement getChild(int id) { - id = 0 and result = getCondition() or - id = 1 and result = getBody() - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - none() - } - - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } - - override final Instruction getChildTrueSuccessor(TranslatedCondition child) { - child = getCondition() and result = getBody().getFirstInstruction() - } - - override final Instruction getChildFalseSuccessor(TranslatedCondition child) { - child = getCondition() and result = getParent().getChildSuccessor(this) - } -} - -class TranslatedWhileStmt extends TranslatedLoop { - TranslatedWhileStmt() { - stmt instanceof WhileStmt - } - - override Instruction getFirstInstruction() { - result = getFirstConditionInstruction() - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getBody() and result = getFirstConditionInstruction() - } -} - -class TranslatedDoStmt extends TranslatedLoop { - TranslatedDoStmt() { - stmt instanceof DoStmt - } - - override Instruction getFirstInstruction() { - result = getBody().getFirstInstruction() - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getBody() and result = getFirstConditionInstruction() - } -} - -class TranslatedForStmt extends TranslatedLoop { - ForStmt forStmt; - - TranslatedForStmt() { - forStmt = stmt - } - - override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() or - id = 1 and result = getCondition() or - id = 2 and result = getUpdate() or - id = 3 and result = getBody() - } - - private TranslatedStmt getInitialization() { - result = getTranslatedStmt(forStmt.getInitialization()) - } - - private predicate hasInitialization() { - exists(forStmt.getInitialization()) - } - - private TranslatedExpr getUpdate() { - result = getTranslatedExpr(forStmt.getUpdate().getFullyConverted()) - } - - private predicate hasUpdate() { - exists(forStmt.getUpdate()) - } - - override Instruction getFirstInstruction() { - if hasInitialization() then - result = getInitialization().getFirstInstruction() - else - result = getFirstConditionInstruction() - } - - override Instruction getChildSuccessor(TranslatedElement child) { - ( - child = getInitialization() and - result = getFirstConditionInstruction() - ) or - ( - child = getBody() and - if hasUpdate() then - result = getUpdate().getFirstInstruction() - else - result = getFirstConditionInstruction() - ) or - child = getUpdate() and result = getFirstConditionInstruction() - } -} - -class TranslatedJumpStmt extends TranslatedStmt { - JumpStmt jump; - - TranslatedJumpStmt() { - stmt = jump - } - - override Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } - - override TranslatedElement getChild(int id) { - none() - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - tag = OnlyInstructionTag() and - opcode instanceof Opcode::NoOp and - resultType instanceof VoidType and - isGLValue = false - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = OnlyInstructionTag() and - kind instanceof GotoEdge and - result = getTranslatedStmt(jump.getTarget()).getFirstInstruction() - } - - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } -} - -class TranslatedSwitchStmt extends TranslatedStmt { - SwitchStmt switchStmt; - - TranslatedSwitchStmt() { - switchStmt = stmt - } - - private TranslatedExpr getExpr() { - result = getTranslatedExpr(switchStmt.getExpr().getFullyConverted()) - } - - private TranslatedStmt getBody() { - result = getTranslatedStmt(switchStmt.getStmt()) - } - - override Instruction getFirstInstruction() { - result = getExpr().getFirstInstruction() - } - - override TranslatedElement getChild(int id) { - id = 0 and result = getExpr() or - id = 1 and result = getBody() - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - tag = SwitchBranchTag() and - opcode instanceof Opcode::Switch and - resultType instanceof VoidType and - isGLValue = false - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - tag = SwitchBranchTag() and - operandTag instanceof ConditionOperand and - result = getExpr().getResult() - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - tag = SwitchBranchTag() and - exists(SwitchCase switchCase | - switchCase = switchStmt.getASwitchCase() and - kind = getCaseEdge(switchCase) and - result = getTranslatedStmt(switchCase).getFirstInstruction() - ) - } - - override Instruction getChildSuccessor(TranslatedElement child) { - child = getExpr() and result = getInstruction(SwitchBranchTag()) or - child = getBody() and result = getParent().getChildSuccessor(this) - } -} +import cpp +private import InstructionTag +private import Opcode +private import TranslatedCondition +private import TranslatedDeclarationEntry +private import TranslatedElement +private import TranslatedExpr +private import TranslatedFunction +private import TranslatedInitialization + +TranslatedStmt getTranslatedStmt(Stmt stmt) { + result.getAST() = stmt +} + +abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt { + Stmt stmt; + + TranslatedStmt() { + this = TTranslatedStmt(stmt) + } + + override final string toString() { + result = stmt.toString() + } + + override final Locatable getAST() { + result = stmt + } + + override final Function getFunction() { + result = stmt.getEnclosingFunction() + } +} + +class TranslatedEmptyStmt extends TranslatedStmt { + TranslatedEmptyStmt() { + stmt instanceof EmptyStmt or + stmt instanceof LabelStmt or + stmt instanceof SwitchCase + } + + override TranslatedElement getChild(int id) { + none() + } + + override Instruction getFirstInstruction() { + result = getInstruction(OnlyInstructionTag()) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + tag = OnlyInstructionTag() and + opcode instanceof Opcode::NoOp and + resultType instanceof VoidType and + isGLValue = false + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = OnlyInstructionTag() and + result = getParent().getChildSuccessor(this) and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + none() + } +} + +class TranslatedDeclStmt extends TranslatedStmt { + DeclStmt declStmt; + + TranslatedDeclStmt() { + declStmt = stmt + } + + override TranslatedElement getChild(int id) { + result = getDeclarationEntry(id) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + none() + } + + override Instruction getFirstInstruction() { + result = getDeclarationEntry(0).getFirstInstruction() //REVIEW: Empty? + } + + private int getChildCount() { + result = declStmt.getNumDeclarations() + } + + private TranslatedDeclarationEntry getDeclarationEntry(int index) { + result = getTranslatedDeclarationEntry(declStmt.getDeclarationEntry(index)) + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + none() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + exists(int index | + child = getDeclarationEntry(index) and + if index = (getChildCount() - 1) then + result = getParent().getChildSuccessor(this) + else + result = getDeclarationEntry(index + 1).getFirstInstruction() + ) + } +} + +class TranslatedExprStmt extends TranslatedStmt { + TranslatedExprStmt() { + stmt instanceof ExprStmt + } + + TranslatedExpr getExpr() { + result = getTranslatedExpr(stmt.(ExprStmt).getExpr().getFullyConverted()) + } + + override TranslatedElement getChild(int id) { + id = 0 and result = getExpr() + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + none() + } + + override Instruction getFirstInstruction() { + result = getExpr().getFirstInstruction() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + none() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getExpr() and + result = getParent().getChildSuccessor(this) + } +} + +abstract class TranslatedReturnStmt extends TranslatedStmt { + ReturnStmt returnStmt; + + TranslatedReturnStmt() { + returnStmt = stmt + } + + final TranslatedFunction getEnclosingFunction() { + result = getTranslatedFunction(returnStmt.getEnclosingFunction()) + } +} + +class TranslatedReturnValueStmt extends TranslatedReturnStmt, + InitializationContext { + TranslatedReturnValueStmt() { + returnStmt.hasExpr() + } + + override TranslatedElement getChild(int id) { + id = 0 and result = getInitialization() + } + + override Instruction getFirstInstruction() { + result = getInstruction(InitializerVariableAddressTag()) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + tag = InitializerVariableAddressTag() and + opcode instanceof Opcode::VariableAddress and + resultType = getEnclosingFunction().getReturnVariable().getType() and + isGLValue = true + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = InitializerVariableAddressTag() and + result = getInitialization().getFirstInstruction() and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getInitialization() and + result = getEnclosingFunction().getReturnSuccessorInstruction() + } + + override IRVariable getInstructionVariable(InstructionTag tag) { + tag = InitializerVariableAddressTag() and + result = getEnclosingFunction().getReturnVariable() + } + + override Instruction getTargetAddress() { + result = getInstruction(InitializerVariableAddressTag()) + } + + override Type getTargetType() { + result = getEnclosingFunction().getReturnVariable().getType() + } + + TranslatedInitialization getInitialization() { + result = getTranslatedInitialization( + returnStmt.getExpr().getFullyConverted()) + } +} + +class TranslatedReturnVoidStmt extends TranslatedReturnStmt { + TranslatedReturnVoidStmt() { + not returnStmt.hasExpr() + } + + override TranslatedElement getChild(int id) { + none() + } + + override Instruction getFirstInstruction() { + result = getInstruction(OnlyInstructionTag()) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + tag = OnlyInstructionTag() and + opcode instanceof Opcode::NoOp and + resultType instanceof VoidType and + isGLValue = false + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = OnlyInstructionTag() and + result = getEnclosingFunction().getReturnSuccessorInstruction() and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + none() + } +} + +/** + * The IR translation of a C++ `try` statement. + */ +class TranslatedTryStmt extends TranslatedStmt { + TryStmt try; + + TranslatedTryStmt() { + try = stmt + } + + override TranslatedElement getChild(int id) { + id = 0 and result = getBody() or + result = getHandler(id - 1) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + none() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + none() + } + + override Instruction getFirstInstruction() { + result = getBody().getFirstInstruction() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + // All children go to the successor of the `try`. + child = getAChild() and result = getParent().getChildSuccessor(this) + } + + final Instruction getNextHandler(TranslatedHandler handler) { + exists(int index | + handler = getHandler(index) and + result = getHandler(index + 1).getFirstInstruction() + ) or + ( + // The last catch clause flows to the exception successor of the parent + // of the `try`, because the exception successor of the `try` itself is + // the first catch clause. + handler = getHandler(try.getNumberOfCatchClauses()) and + result = getParent().getExceptionSuccessorInstruction() + ) + } + + override final Instruction getExceptionSuccessorInstruction() { + result = getHandler(0).getFirstInstruction() + } + + private TranslatedHandler getHandler(int index) { + result = getTranslatedStmt(try.getChild(index + 1)) + } + + private TranslatedStmt getBody() { + result = getTranslatedStmt(try.getStmt()) + } +} + +class TranslatedBlock extends TranslatedStmt { + Block block; + + TranslatedBlock() { + block = stmt + } + + override TranslatedElement getChild(int id) { + result = getStmt(id) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + isEmpty() and + opcode instanceof Opcode::NoOp and + tag = OnlyInstructionTag() and + resultType instanceof VoidType and + isGLValue = false + } + + override Instruction getFirstInstruction() { + if isEmpty() then + result = getInstruction(OnlyInstructionTag()) + else + result = getStmt(0).getFirstInstruction() + } + + private predicate isEmpty() { + not exists(block.getStmt(0)) + } + + private TranslatedStmt getStmt(int index) { + result = getTranslatedStmt(block.getStmt(index)) + } + + private int getStmtCount() { + result = block.getNumStmt() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = OnlyInstructionTag() and + result = getParent().getChildSuccessor(this) and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + exists(int index | + child = getStmt(index) and + if index = (getStmtCount() - 1) then + result = getParent().getChildSuccessor(this) + else + result = getStmt(index + 1).getFirstInstruction() + ) + } +} + +/** + * The IR translation of a C++ `catch` handler. + */ +abstract class TranslatedHandler extends TranslatedStmt { + Handler handler; + + TranslatedHandler() { + handler = stmt + } + + override TranslatedElement getChild(int id) { + id = 1 and result = getBlock() + } + + override Instruction getFirstInstruction() { + result = getInstruction(CatchTag()) + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getBlock() and result = getParent().getChildSuccessor(this) + } + + override Instruction getExceptionSuccessorInstruction() { + // A throw from within a `catch` block flows to the handler for the parent of + // the `try`. + result = getParent().getParent().getExceptionSuccessorInstruction() + } + + TranslatedStmt getBlock() { + result = getTranslatedStmt(handler.getBlock()) + } +} + +/** + * The IR translation of a C++ `catch` block that catches an exception with a + * specific type (e.g. `catch (const std::exception&)`). + */ +class TranslatedCatchByTypeHandler extends TranslatedHandler { + TranslatedCatchByTypeHandler() { + exists(handler.getParameter()) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + tag = CatchTag() and + opcode instanceof Opcode::CatchByType and + resultType instanceof VoidType and + isGLValue = false + } + + override TranslatedElement getChild(int id) { + result = super.getChild(id) or + id = 0 and result = getParameter() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + result = super.getChildSuccessor(child) or + child = getParameter() and result = getBlock().getFirstInstruction() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = CatchTag() and + ( + ( + kind instanceof GotoEdge and + result = getParameter().getFirstInstruction() + ) or + ( + kind instanceof ExceptionEdge and + result = getParent().(TranslatedTryStmt).getNextHandler(this) + ) + ) + } + + override Type getInstructionExceptionType(InstructionTag tag) { + tag = CatchTag() and + result = handler.getParameter().getType() + } + + private TranslatedParameter getParameter() { + result = getTranslatedParameter(handler.getParameter()) + } +} + +/** + * The IR translation of a C++ `catch (...)` block. + */ +class TranslatedCatchAnyHandler extends TranslatedHandler { + TranslatedCatchAnyHandler() { + not exists(handler.getParameter()) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + tag = CatchTag() and + opcode instanceof Opcode::CatchAny and + resultType instanceof VoidType and + isGLValue = false + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = CatchTag() and + kind instanceof GotoEdge and + result = getBlock().getFirstInstruction() + } +} + +class TranslatedIfStmt extends TranslatedStmt, ConditionContext { + IfStmt ifStmt; + + TranslatedIfStmt() { + stmt = ifStmt + } + + override Instruction getFirstInstruction() { + result = getCondition().getFirstInstruction() + } + + override TranslatedElement getChild(int id) { + id = 0 and result = getCondition() or + id = 1 and result = getThen() or + id = 2 and result = getElse() + } + + private TranslatedCondition getCondition() { + result = getTranslatedCondition(ifStmt.getCondition().getFullyConverted()) + } + + private TranslatedStmt getThen() { + result = getTranslatedStmt(ifStmt.getThen()) + } + + private TranslatedStmt getElse() { + result = getTranslatedStmt(ifStmt.getElse()) + } + + private predicate hasElse() { + exists(ifStmt.getElse()) + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + none() + } + + override Instruction getChildTrueSuccessor(TranslatedCondition child) { + child = getCondition() and + result = getThen().getFirstInstruction() + } + + override Instruction getChildFalseSuccessor(TranslatedCondition child) { + child = getCondition() and + if hasElse() then + result = getElse().getFirstInstruction() + else + result = getParent().getChildSuccessor(this) + } + + override Instruction getChildSuccessor(TranslatedElement child) { + (child = getThen() or child = getElse()) and + result = getParent().getChildSuccessor(this) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + none() + } +} + +abstract class TranslatedLoop extends TranslatedStmt, ConditionContext { + Loop loop; + + TranslatedLoop() { + loop = stmt + } + + final TranslatedCondition getCondition() { + result = getTranslatedCondition(loop.getCondition().getFullyConverted()) + } + + final TranslatedStmt getBody() { + result = getTranslatedStmt(loop.getStmt()) + } + + final Instruction getFirstConditionInstruction() { + if hasCondition() then + result = getCondition().getFirstInstruction() + else + result = getBody().getFirstInstruction() + } + + final predicate hasCondition() { + exists(loop.getCondition()) + } + + override TranslatedElement getChild(int id) { + id = 0 and result = getCondition() or + id = 1 and result = getBody() + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + none() + } + + override final Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + none() + } + + override final Instruction getChildTrueSuccessor(TranslatedCondition child) { + child = getCondition() and result = getBody().getFirstInstruction() + } + + override final Instruction getChildFalseSuccessor(TranslatedCondition child) { + child = getCondition() and result = getParent().getChildSuccessor(this) + } +} + +class TranslatedWhileStmt extends TranslatedLoop { + TranslatedWhileStmt() { + stmt instanceof WhileStmt + } + + override Instruction getFirstInstruction() { + result = getFirstConditionInstruction() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getBody() and result = getFirstConditionInstruction() + } +} + +class TranslatedDoStmt extends TranslatedLoop { + TranslatedDoStmt() { + stmt instanceof DoStmt + } + + override Instruction getFirstInstruction() { + result = getBody().getFirstInstruction() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getBody() and result = getFirstConditionInstruction() + } +} + +class TranslatedForStmt extends TranslatedLoop { + ForStmt forStmt; + + TranslatedForStmt() { + forStmt = stmt + } + + override TranslatedElement getChild(int id) { + id = 0 and result = getInitialization() or + id = 1 and result = getCondition() or + id = 2 and result = getUpdate() or + id = 3 and result = getBody() + } + + private TranslatedStmt getInitialization() { + result = getTranslatedStmt(forStmt.getInitialization()) + } + + private predicate hasInitialization() { + exists(forStmt.getInitialization()) + } + + private TranslatedExpr getUpdate() { + result = getTranslatedExpr(forStmt.getUpdate().getFullyConverted()) + } + + private predicate hasUpdate() { + exists(forStmt.getUpdate()) + } + + override Instruction getFirstInstruction() { + if hasInitialization() then + result = getInitialization().getFirstInstruction() + else + result = getFirstConditionInstruction() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + ( + child = getInitialization() and + result = getFirstConditionInstruction() + ) or + ( + child = getBody() and + if hasUpdate() then + result = getUpdate().getFirstInstruction() + else + result = getFirstConditionInstruction() + ) or + child = getUpdate() and result = getFirstConditionInstruction() + } +} + +class TranslatedJumpStmt extends TranslatedStmt { + JumpStmt jump; + + TranslatedJumpStmt() { + stmt = jump + } + + override Instruction getFirstInstruction() { + result = getInstruction(OnlyInstructionTag()) + } + + override TranslatedElement getChild(int id) { + none() + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + tag = OnlyInstructionTag() and + opcode instanceof Opcode::NoOp and + resultType instanceof VoidType and + isGLValue = false + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = OnlyInstructionTag() and + kind instanceof GotoEdge and + result = getTranslatedStmt(jump.getTarget()).getFirstInstruction() + } + + override Instruction getChildSuccessor(TranslatedElement child) { + none() + } +} + +class TranslatedSwitchStmt extends TranslatedStmt { + SwitchStmt switchStmt; + + TranslatedSwitchStmt() { + switchStmt = stmt + } + + private TranslatedExpr getExpr() { + result = getTranslatedExpr(switchStmt.getExpr().getFullyConverted()) + } + + private TranslatedStmt getBody() { + result = getTranslatedStmt(switchStmt.getStmt()) + } + + override Instruction getFirstInstruction() { + result = getExpr().getFirstInstruction() + } + + override TranslatedElement getChild(int id) { + id = 0 and result = getExpr() or + id = 1 and result = getBody() + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, + Type resultType, boolean isGLValue) { + tag = SwitchBranchTag() and + opcode instanceof Opcode::Switch and + resultType instanceof VoidType and + isGLValue = false + } + + override Instruction getInstructionOperand(InstructionTag tag, + OperandTag operandTag) { + tag = SwitchBranchTag() and + operandTag instanceof ConditionOperand and + result = getExpr().getResult() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, + EdgeKind kind) { + tag = SwitchBranchTag() and + exists(SwitchCase switchCase | + switchCase = switchStmt.getASwitchCase() and + kind = getCaseEdge(switchCase) and + result = getTranslatedStmt(switchCase).getFirstInstruction() + ) + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getExpr() and result = getInstruction(SwitchBranchTag()) or + child = getBody() and result = getParent().getChildSuccessor(this) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/models/Models.qll b/cpp/ql/src/semmle/code/cpp/models/Models.qll index 9fefd5243f1..672354c9625 100644 --- a/cpp/ql/src/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/src/semmle/code/cpp/models/Models.qll @@ -1,7 +1,7 @@ -private import implementations.Inet -private import implementations.Memcpy -private import implementations.Printf -private import implementations.Pure -private import implementations.Strcat -private import implementations.Strcpy -private import implementations.Strftime +private import implementations.Inet +private import implementations.Memcpy +private import implementations.Printf +private import implementations.Pure +private import implementations.Strcat +private import implementations.Strcpy +private import implementations.Strftime diff --git a/cpp/ql/src/semmle/code/cpp/ssa/AliasedSSAIR.qll b/cpp/ql/src/semmle/code/cpp/ssa/AliasedSSAIR.qll index ca6ec999c6f..8aee096b06e 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/AliasedSSAIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/AliasedSSAIR.qll @@ -1 +1 @@ -import internal.aliased_ssa.IRImpl +import internal.aliased_ssa.IRImpl diff --git a/cpp/ql/src/semmle/code/cpp/ssa/PrintAliasedSSAIR.ql b/cpp/ql/src/semmle/code/cpp/ssa/PrintAliasedSSAIR.ql index fbee9b598fc..ac8caa4ad94 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/PrintAliasedSSAIR.ql +++ b/cpp/ql/src/semmle/code/cpp/ssa/PrintAliasedSSAIR.ql @@ -1,8 +1,8 @@ -/** - * @name Print Aliased SSA IR - * @description Outputs a representation of the Aliased SSA IR graph - * @id cpp/print-aliased-ssa-ir - * @kind graph - */ - -import PrintAliasedSSAIR +/** + * @name Print Aliased SSA IR + * @description Outputs a representation of the Aliased SSA IR graph + * @id cpp/print-aliased-ssa-ir + * @kind graph + */ + +import PrintAliasedSSAIR diff --git a/cpp/ql/src/semmle/code/cpp/ssa/PrintAliasedSSAIR.qll b/cpp/ql/src/semmle/code/cpp/ssa/PrintAliasedSSAIR.qll index 8498bff9550..0bd6b346d6d 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/PrintAliasedSSAIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/PrintAliasedSSAIR.qll @@ -1 +1 @@ -import internal.aliased_ssa.PrintIRImpl +import internal.aliased_ssa.PrintIRImpl diff --git a/cpp/ql/src/semmle/code/cpp/ssa/PrintSSAIR.ql b/cpp/ql/src/semmle/code/cpp/ssa/PrintSSAIR.ql index ceef60a696b..b3569b481e6 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/PrintSSAIR.ql +++ b/cpp/ql/src/semmle/code/cpp/ssa/PrintSSAIR.ql @@ -1,8 +1,8 @@ -/** - * @name Print SSA IR - * @description Outputs a representation of the SSA IR graph - * @id cpp/print-ssa-ir - * @kind graph - */ - -import PrintSSAIR +/** + * @name Print SSA IR + * @description Outputs a representation of the SSA IR graph + * @id cpp/print-ssa-ir + * @kind graph + */ + +import PrintSSAIR diff --git a/cpp/ql/src/semmle/code/cpp/ssa/PrintSSAIR.qll b/cpp/ql/src/semmle/code/cpp/ssa/PrintSSAIR.qll index 6389c421498..a7a019299f2 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/PrintSSAIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/PrintSSAIR.qll @@ -1 +1 @@ -import internal.ssa.PrintIRImpl +import internal.ssa.PrintIRImpl diff --git a/cpp/ql/src/semmle/code/cpp/ssa/SSAIR.qll b/cpp/ql/src/semmle/code/cpp/ssa/SSAIR.qll index 7ac7aea2c84..477c25b1a35 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/SSAIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/SSAIR.qll @@ -1 +1 @@ -import internal.ssa.IRImpl +import internal.ssa.IRImpl diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/IntegerConstant.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/IntegerConstant.qll index 22fb8dea824..f92b9f57f0f 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/IntegerConstant.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/IntegerConstant.qll @@ -1,111 +1,111 @@ -import cpp - -class IntValue = int; - -/** - * Returns the value of the maximum representable integer. - */ -int maxValue() { - result = 2147483647 -} - -/** - * Returns the value of the minimum representable integer. - */ -int minValue() { - result = -2147483647 -} - -/** - * Returns a value representing an unknown integer. - */ -IntValue unknown() { - result = -2147483648 -} - -/** - * Holds if `n` has a known value. - */ -bindingset[n] -predicate hasValue(IntValue n) { - n != unknown() -} - -/** - * Holds if the value `f` is within the range of representable integers. - */ -pragma[inline] -bindingset[f] -private predicate isRepresentable(float f) { - (f >= minValue()) and (f <= maxValue()) -} - -/** - * Gets the value of `n`. Holds only if `n` has a known value. - */ -bindingset[n] -int getValue(IntValue n) { - hasValue(n) and result = n -} - -/** - * Returns `a + b`. If either input is unknown, or if the addition overflows, - * the result is unknown. - */ -bindingset[a, b] -IntValue add(IntValue a, IntValue b) { - if hasValue(a) and hasValue(b) and isRepresentable((float)a + (float)b) then - result = a + b - else - result = unknown() -} - -/** - * Returns `a - b`. If either input is unknown, or if the subtraction overflows, - * the result is unknown. - */ -bindingset[a, b] -IntValue sub(IntValue a, IntValue b) { - if hasValue(a) and hasValue(b) and isRepresentable((float)a - (float)b) then - result = a - b - else - result = unknown() -} - -/** - * Returns `a * b`. If the multiplication overflows, the result is unknown. If - * either input is unknown and the other input is non-zero, the result is - * unknown. - */ -bindingset[a, b] -IntValue mul(IntValue a, IntValue b) { - if (a = 0) or (b = 0) then - result = 0 - else if hasValue(a) and hasValue(b) and isRepresentable((float)a * (float)b) then - result = a * b - else - result = unknown() -} - -/** - * Returns `a / b`. If either input is unknown, or if `b` is zero, the result is - * unknown. - */ -bindingset[a, b] -IntValue div(IntValue a, IntValue b) { - // Normally, integer division has to worry about overflow for INT_MIN/-1. - // However, since we use INT_MIN to represent an unknown value anyway, we only - // have to worry about division by zero. - if hasValue(a) and hasValue(b) and (b != 0) then - result = a / b - else - result = unknown() -} - -/** - * Return `-a`. If `a` is unknown, the result is unknown. - */ -bindingset[a] -IntValue neg(IntValue a) { - result = -a // -INT_MIN = INT_MIN, so this preserves unknown -} +import cpp + +class IntValue = int; + +/** + * Returns the value of the maximum representable integer. + */ +int maxValue() { + result = 2147483647 +} + +/** + * Returns the value of the minimum representable integer. + */ +int minValue() { + result = -2147483647 +} + +/** + * Returns a value representing an unknown integer. + */ +IntValue unknown() { + result = -2147483648 +} + +/** + * Holds if `n` has a known value. + */ +bindingset[n] +predicate hasValue(IntValue n) { + n != unknown() +} + +/** + * Holds if the value `f` is within the range of representable integers. + */ +pragma[inline] +bindingset[f] +private predicate isRepresentable(float f) { + (f >= minValue()) and (f <= maxValue()) +} + +/** + * Gets the value of `n`. Holds only if `n` has a known value. + */ +bindingset[n] +int getValue(IntValue n) { + hasValue(n) and result = n +} + +/** + * Returns `a + b`. If either input is unknown, or if the addition overflows, + * the result is unknown. + */ +bindingset[a, b] +IntValue add(IntValue a, IntValue b) { + if hasValue(a) and hasValue(b) and isRepresentable((float)a + (float)b) then + result = a + b + else + result = unknown() +} + +/** + * Returns `a - b`. If either input is unknown, or if the subtraction overflows, + * the result is unknown. + */ +bindingset[a, b] +IntValue sub(IntValue a, IntValue b) { + if hasValue(a) and hasValue(b) and isRepresentable((float)a - (float)b) then + result = a - b + else + result = unknown() +} + +/** + * Returns `a * b`. If the multiplication overflows, the result is unknown. If + * either input is unknown and the other input is non-zero, the result is + * unknown. + */ +bindingset[a, b] +IntValue mul(IntValue a, IntValue b) { + if (a = 0) or (b = 0) then + result = 0 + else if hasValue(a) and hasValue(b) and isRepresentable((float)a * (float)b) then + result = a * b + else + result = unknown() +} + +/** + * Returns `a / b`. If either input is unknown, or if `b` is zero, the result is + * unknown. + */ +bindingset[a, b] +IntValue div(IntValue a, IntValue b) { + // Normally, integer division has to worry about overflow for INT_MIN/-1. + // However, since we use INT_MIN to represent an unknown value anyway, we only + // have to worry about division by zero. + if hasValue(a) and hasValue(b) and (b != 0) then + result = a / b + else + result = unknown() +} + +/** + * Return `-a`. If `a` is unknown, the result is unknown. + */ +bindingset[a] +IntValue neg(IntValue a) { + result = -a // -INT_MIN = INT_MIN, so this preserves unknown +} diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/Overlap.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/Overlap.qll index 5786a136345..ab07d9d7af6 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/Overlap.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/Overlap.qll @@ -1,28 +1,28 @@ -import cpp - -private newtype TOverlap = - TMayPartiallyOverlap() or - TMustTotallyOverlap() or - TMustExactlyOverlap() - -abstract class Overlap extends TOverlap { - abstract string toString(); -} - -class MayPartiallyOverlap extends Overlap, TMayPartiallyOverlap { - override final string toString() { - result = "MayPartiallyOverlap" - } -} - -class MustTotallyOverlap extends Overlap, TMustTotallyOverlap { - override final string toString() { - result = "MustTotallyOverlap" - } -} - -class MustExactlyOverlap extends Overlap, TMustExactlyOverlap { - override final string toString() { - result = "MustExactlyOverlap" - } -} +import cpp + +private newtype TOverlap = + TMayPartiallyOverlap() or + TMustTotallyOverlap() or + TMustExactlyOverlap() + +abstract class Overlap extends TOverlap { + abstract string toString(); +} + +class MayPartiallyOverlap extends Overlap, TMayPartiallyOverlap { + override final string toString() { + result = "MayPartiallyOverlap" + } +} + +class MustTotallyOverlap extends Overlap, TMustTotallyOverlap { + override final string toString() { + result = "MustTotallyOverlap" + } +} + +class MustExactlyOverlap extends Overlap, TMustExactlyOverlap { + override final string toString() { + result = "MustExactlyOverlap" + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/AliasAnalysis.qll index cc42ce1c96e..6d40ee0f66b 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/AliasAnalysis.qll @@ -1,214 +1,214 @@ -private import AliasAnalysisInternal -import cpp -private import IR -private import semmle.code.cpp.ssa.internal.IntegerConstant as Ints - -private class IntValue = Ints::IntValue; - -/** - * Converts the bit count in `bits` to a byte count and a bit count in the form - * bytes:bits. - */ -bindingset[bits] -string bitsToBytesAndBits(int bits) { - result = (bits / 8).toString() + ":" + (bits % 8).toString() -} - -/** - * Gets a printable string for a bit offset with possibly unknown value. - */ -bindingset[bitOffset] -string getBitOffsetString(IntValue bitOffset) { - if Ints::hasValue(bitOffset) then - if bitOffset >= 0 then - result = "+" + bitsToBytesAndBits(bitOffset) - else - result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset)) - else - result = "+?" -} - -/** - * Gets the offset of field `field` in bits. - */ -private IntValue getFieldBitOffset(Field field) { - if (field instanceof BitField) then ( - result = Ints::add(Ints::mul(field.getByteOffset(), 8), - field.(BitField).getBitOffset()) - ) - else ( - result = Ints::mul(field.getByteOffset(), 8) - ) -} - -/** - * Holds if the operand `tag` of instruction `instr` is used in a way that does - * not result in any address held in that operand from escaping beyond the - * instruction. - */ -predicate operandIsConsumedWithoutEscaping(Instruction instr, OperandTag tag) { - exists(instr.getOperand(tag)) and - ( - // The source/destination address of a Load/Store does not escape (but the - // loaded/stored value could). - tag instanceof LoadStoreAddressOperand or - // Neither operand of a Compare escapes. - instr instanceof CompareInstruction or - // Neither operand of a PointerDiff escapes. - instr instanceof PointerDiffInstruction or - // Converting an address to a `bool` does not escape the address. - instr.(ConvertInstruction).getResultType() instanceof BoolType - ) -} - -/** - * If the result of instruction `instr` is an integer constant, returns the - * value of that constant. Otherwise, returns unknown. - */ -IntValue getConstantValue(Instruction instr) { - if instr instanceof IntegerConstantInstruction then - result = instr.(IntegerConstantInstruction).getValue().toInt() - else - result = Ints::unknown() -} - -/** - * Computes the offset, in bits, by which the result of `instr` differs from the - * pointer argument to `instr`, if that offset is a constant. Otherwise, returns - * unknown. - */ -IntValue getPointerBitOffset(PointerOffsetInstruction instr) { - exists(IntValue bitOffset | - ( - bitOffset = Ints::mul(Ints::mul(getConstantValue(instr.getRightOperand()), - instr.getElementSize()), 8) - ) and - ( - instr instanceof PointerAddInstruction and result = bitOffset or - instr instanceof PointerSubInstruction and result = Ints::neg(bitOffset) - ) - ) -} - -/** - * Holds if any address held in operand `tag` of instruction `instr` is - * propagated to the result of `instr`, offset by the number of bits in - * `bitOffset`. If the address is propagated, but the offset is not known to be - * a constant, then `bitOffset` is unknown. - */ -predicate operandIsPropagated(Instruction instr, OperandTag tag, - IntValue bitOffset) { - exists(instr.getOperand(tag)) and - ( - // Converting to a non-virtual base class adds the offset of the base class. - exists(ConvertToBaseInstruction convert | - convert = instr and - bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) - ) or - // Converting to a derived class subtracts the offset of the base class. - exists(ConvertToDerivedInstruction convert | - convert = instr and - bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8)) - ) or - // Converting to a virtual base class adds an unknown offset. - ( - instr instanceof ConvertToVirtualBaseInstruction and - bitOffset = Ints::unknown() - ) or - // Conversion to another pointer type propagates the source address. - exists(ConvertInstruction convert, Type resultType | - convert = instr and - resultType = convert.getResultType() and - ( - resultType instanceof PointerType or - resultType instanceof Class //REVIEW: Remove when all glvalues are pointers - ) and - bitOffset = 0 - ) or - // Adding an integer to or subtracting an integer from a pointer propagates - // the address with an offset. - bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or - // Computing a field address from a pointer propagates the address plus the - // offset of the field. - bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or - // A copy propagates the source value. - tag instanceof CopySourceOperand and bitOffset = 0 - ) -} - -/** - * Holds if any address held in operand number `tag` of instruction `instr` - * escapes outside the domain of the analysis. - */ -predicate operandEscapes(Instruction instr, OperandTag tag) { - exists(instr.getOperand(tag)) and - // Conservatively assume that the address escapes unless one of the following - // holds: - not ( - // The operand is used in a way that does not escape the instruction - operandIsConsumedWithoutEscaping(instr, tag) or - // The address is propagated to the result of the instruction, but that - // result does not itself escape. - operandIsPropagated(instr, tag, _) and not resultEscapes(instr) - ) -} - -/** - * Holds if any address held in the result of instruction `instr` escapes - * outside the domain of the analysis. - */ -predicate resultEscapes(Instruction instr) { - // The result escapes if it has at least one use that escapes. - exists(Instruction useInstr, OperandTag useOperandTag | - useInstr.getOperand(useOperandTag) = instr and - operandEscapes(useInstr, useOperandTag) - ) -} - -/** - * Holds if the address of the specified local variable or parameter escapes the - * domain of the analysis. - */ -private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) { - exists(FunctionIR funcIR | - funcIR = var.getFunctionIR() and - // The variable's address escapes if the result of any - // VariableAddressInstruction that computes the variable's address escapes. - exists(VariableAddressInstruction instr | - instr.getFunctionIR() = funcIR and - instr.getVariable() = var and - resultEscapes(instr) - ) - ) -} - -/** - * Holds if the address of the specified variable escapes the domain of the - * analysis. - */ -predicate variableAddressEscapes(IRVariable var) { - automaticVariableAddressEscapes(var.(IRAutomaticVariable)) or - // All variables with static storage duration have their address escape. - not var instanceof IRAutomaticVariable -} - -/** - * Holds if the result of instruction `instr` points within variable `var`, at - * bit offset `bitOffset` within the variable. If the result points within - * `var`, but at an unknown or non-constant offset, then `bitOffset` is unknown. - */ -predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) { - ( - // The address of a variable points to that variable, at offset 0. - instr.(VariableAddressInstruction).getVariable() = var and - bitOffset = 0 - ) or - exists(OperandTag operandTag, IntValue originalBitOffset, - IntValue propagatedBitOffset | - // If an operand is propagated, then the result points to the same variable, - // offset by the bit offset from the propagation. - resultPointsTo(instr.getOperand(operandTag), var, originalBitOffset) and - operandIsPropagated(instr, operandTag, propagatedBitOffset) and - bitOffset = Ints::add(originalBitOffset, propagatedBitOffset) - ) -} +private import AliasAnalysisInternal +import cpp +private import IR +private import semmle.code.cpp.ssa.internal.IntegerConstant as Ints + +private class IntValue = Ints::IntValue; + +/** + * Converts the bit count in `bits` to a byte count and a bit count in the form + * bytes:bits. + */ +bindingset[bits] +string bitsToBytesAndBits(int bits) { + result = (bits / 8).toString() + ":" + (bits % 8).toString() +} + +/** + * Gets a printable string for a bit offset with possibly unknown value. + */ +bindingset[bitOffset] +string getBitOffsetString(IntValue bitOffset) { + if Ints::hasValue(bitOffset) then + if bitOffset >= 0 then + result = "+" + bitsToBytesAndBits(bitOffset) + else + result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset)) + else + result = "+?" +} + +/** + * Gets the offset of field `field` in bits. + */ +private IntValue getFieldBitOffset(Field field) { + if (field instanceof BitField) then ( + result = Ints::add(Ints::mul(field.getByteOffset(), 8), + field.(BitField).getBitOffset()) + ) + else ( + result = Ints::mul(field.getByteOffset(), 8) + ) +} + +/** + * Holds if the operand `tag` of instruction `instr` is used in a way that does + * not result in any address held in that operand from escaping beyond the + * instruction. + */ +predicate operandIsConsumedWithoutEscaping(Instruction instr, OperandTag tag) { + exists(instr.getOperand(tag)) and + ( + // The source/destination address of a Load/Store does not escape (but the + // loaded/stored value could). + tag instanceof LoadStoreAddressOperand or + // Neither operand of a Compare escapes. + instr instanceof CompareInstruction or + // Neither operand of a PointerDiff escapes. + instr instanceof PointerDiffInstruction or + // Converting an address to a `bool` does not escape the address. + instr.(ConvertInstruction).getResultType() instanceof BoolType + ) +} + +/** + * If the result of instruction `instr` is an integer constant, returns the + * value of that constant. Otherwise, returns unknown. + */ +IntValue getConstantValue(Instruction instr) { + if instr instanceof IntegerConstantInstruction then + result = instr.(IntegerConstantInstruction).getValue().toInt() + else + result = Ints::unknown() +} + +/** + * Computes the offset, in bits, by which the result of `instr` differs from the + * pointer argument to `instr`, if that offset is a constant. Otherwise, returns + * unknown. + */ +IntValue getPointerBitOffset(PointerOffsetInstruction instr) { + exists(IntValue bitOffset | + ( + bitOffset = Ints::mul(Ints::mul(getConstantValue(instr.getRightOperand()), + instr.getElementSize()), 8) + ) and + ( + instr instanceof PointerAddInstruction and result = bitOffset or + instr instanceof PointerSubInstruction and result = Ints::neg(bitOffset) + ) + ) +} + +/** + * Holds if any address held in operand `tag` of instruction `instr` is + * propagated to the result of `instr`, offset by the number of bits in + * `bitOffset`. If the address is propagated, but the offset is not known to be + * a constant, then `bitOffset` is unknown. + */ +predicate operandIsPropagated(Instruction instr, OperandTag tag, + IntValue bitOffset) { + exists(instr.getOperand(tag)) and + ( + // Converting to a non-virtual base class adds the offset of the base class. + exists(ConvertToBaseInstruction convert | + convert = instr and + bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) + ) or + // Converting to a derived class subtracts the offset of the base class. + exists(ConvertToDerivedInstruction convert | + convert = instr and + bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8)) + ) or + // Converting to a virtual base class adds an unknown offset. + ( + instr instanceof ConvertToVirtualBaseInstruction and + bitOffset = Ints::unknown() + ) or + // Conversion to another pointer type propagates the source address. + exists(ConvertInstruction convert, Type resultType | + convert = instr and + resultType = convert.getResultType() and + ( + resultType instanceof PointerType or + resultType instanceof Class //REVIEW: Remove when all glvalues are pointers + ) and + bitOffset = 0 + ) or + // Adding an integer to or subtracting an integer from a pointer propagates + // the address with an offset. + bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or + // Computing a field address from a pointer propagates the address plus the + // offset of the field. + bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or + // A copy propagates the source value. + tag instanceof CopySourceOperand and bitOffset = 0 + ) +} + +/** + * Holds if any address held in operand number `tag` of instruction `instr` + * escapes outside the domain of the analysis. + */ +predicate operandEscapes(Instruction instr, OperandTag tag) { + exists(instr.getOperand(tag)) and + // Conservatively assume that the address escapes unless one of the following + // holds: + not ( + // The operand is used in a way that does not escape the instruction + operandIsConsumedWithoutEscaping(instr, tag) or + // The address is propagated to the result of the instruction, but that + // result does not itself escape. + operandIsPropagated(instr, tag, _) and not resultEscapes(instr) + ) +} + +/** + * Holds if any address held in the result of instruction `instr` escapes + * outside the domain of the analysis. + */ +predicate resultEscapes(Instruction instr) { + // The result escapes if it has at least one use that escapes. + exists(Instruction useInstr, OperandTag useOperandTag | + useInstr.getOperand(useOperandTag) = instr and + operandEscapes(useInstr, useOperandTag) + ) +} + +/** + * Holds if the address of the specified local variable or parameter escapes the + * domain of the analysis. + */ +private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) { + exists(FunctionIR funcIR | + funcIR = var.getFunctionIR() and + // The variable's address escapes if the result of any + // VariableAddressInstruction that computes the variable's address escapes. + exists(VariableAddressInstruction instr | + instr.getFunctionIR() = funcIR and + instr.getVariable() = var and + resultEscapes(instr) + ) + ) +} + +/** + * Holds if the address of the specified variable escapes the domain of the + * analysis. + */ +predicate variableAddressEscapes(IRVariable var) { + automaticVariableAddressEscapes(var.(IRAutomaticVariable)) or + // All variables with static storage duration have their address escape. + not var instanceof IRAutomaticVariable +} + +/** + * Holds if the result of instruction `instr` points within variable `var`, at + * bit offset `bitOffset` within the variable. If the result points within + * `var`, but at an unknown or non-constant offset, then `bitOffset` is unknown. + */ +predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) { + ( + // The address of a variable points to that variable, at offset 0. + instr.(VariableAddressInstruction).getVariable() = var and + bitOffset = 0 + ) or + exists(OperandTag operandTag, IntValue originalBitOffset, + IntValue propagatedBitOffset | + // If an operand is propagated, then the result points to the same variable, + // offset by the bit offset from the propagation. + resultPointsTo(instr.getOperand(operandTag), var, originalBitOffset) and + operandIsPropagated(instr, operandTag, propagatedBitOffset) and + bitOffset = Ints::add(originalBitOffset, propagatedBitOffset) + ) +} diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/AliasAnalysisInternal.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/AliasAnalysisInternal.qll index 13f43d1d1f4..02e8979ae8e 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/AliasAnalysisInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/AliasAnalysisInternal.qll @@ -1 +1 @@ -import semmle.code.cpp.ssa.SSAIR as IR +import semmle.code.cpp.ssa.SSAIR as IR diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/FunctionIR.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/FunctionIR.qll index 4568ae7ceb2..3e918fd3b49 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/FunctionIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/FunctionIR.qll @@ -1,97 +1,97 @@ -private import IRInternal -import Instruction -import cpp - -private newtype TFunctionIR = - MkFunctionIR(Function func) { - Construction::functionHasIR(func) - } - -/** - * Represents the IR for a function. - */ -class FunctionIR extends TFunctionIR { - Function func; - - FunctionIR() { - this = MkFunctionIR(func) - } - - final string toString() { - result = "IR: " + func.toString() - } - - /** - * Gets the function whose IR is represented. - */ - final Function getFunction() { - result = func - } - - /** - * Gets the location of the function. - */ - final Location getLocation() { - result = func.getLocation() - } - - /** - * Gets the entry point for this function. - */ - pragma[noinline] - final EnterFunctionInstruction getEnterFunctionInstruction() { - result.getFunctionIR() = this - } - - /** - * Gets the exit point for this function. - */ - pragma[noinline] - final ExitFunctionInstruction getExitFunctionInstruction() { - result.getFunctionIR() = this - } - - pragma[noinline] - final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() { - result.getFunctionIR() = this - } - - /** - * Gets the single return instruction for this function. - */ - pragma[noinline] - final ReturnInstruction getReturnInstruction() { - result.getFunctionIR() = this - } - - /** - * Gets the variable used to hold the return value of this function. If this - * function does not return a value, this predicate does not hold. - */ - pragma[noinline] - final IRReturnVariable getReturnVariable() { - result.getFunctionIR() = this - } - - /** - * Gets the block containing the entry point of this function. - */ - pragma[noinline] - final IRBlock getEntryBlock() { - result.getFirstInstruction() = getEnterFunctionInstruction() - } - - /** - * Gets all instructions in this function. - */ - final Instruction getAnInstruction() { - result.getFunctionIR() = this - } - - /** - * Gets all blocks in this function. - */ - final IRBlock getABlock() { - result.getFunctionIR() = this - } -} +private import IRInternal +import Instruction +import cpp + +private newtype TFunctionIR = + MkFunctionIR(Function func) { + Construction::functionHasIR(func) + } + +/** + * Represents the IR for a function. + */ +class FunctionIR extends TFunctionIR { + Function func; + + FunctionIR() { + this = MkFunctionIR(func) + } + + final string toString() { + result = "IR: " + func.toString() + } + + /** + * Gets the function whose IR is represented. + */ + final Function getFunction() { + result = func + } + + /** + * Gets the location of the function. + */ + final Location getLocation() { + result = func.getLocation() + } + + /** + * Gets the entry point for this function. + */ + pragma[noinline] + final EnterFunctionInstruction getEnterFunctionInstruction() { + result.getFunctionIR() = this + } + + /** + * Gets the exit point for this function. + */ + pragma[noinline] + final ExitFunctionInstruction getExitFunctionInstruction() { + result.getFunctionIR() = this + } + + pragma[noinline] + final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() { + result.getFunctionIR() = this + } + + /** + * Gets the single return instruction for this function. + */ + pragma[noinline] + final ReturnInstruction getReturnInstruction() { + result.getFunctionIR() = this + } + + /** + * Gets the variable used to hold the return value of this function. If this + * function does not return a value, this predicate does not hold. + */ + pragma[noinline] + final IRReturnVariable getReturnVariable() { + result.getFunctionIR() = this + } + + /** + * Gets the block containing the entry point of this function. + */ + pragma[noinline] + final IRBlock getEntryBlock() { + result.getFirstInstruction() = getEnterFunctionInstruction() + } + + /** + * Gets all instructions in this function. + */ + final Instruction getAnInstruction() { + result.getFunctionIR() = this + } + + /** + * Gets all blocks in this function. + */ + final IRBlock getABlock() { + result.getFunctionIR() = this + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/IRInternal.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/IRInternal.qll index 7517660a58f..940cc3df356 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/IRInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/IRInternal.qll @@ -1 +1 @@ -import SSAConstruction as Construction +import SSAConstruction as Construction diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/IRSanityImpl.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/IRSanityImpl.qll index 744b2870460..f4a1d12de89 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/IRSanityImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/IRSanityImpl.qll @@ -1,3 +1,3 @@ -private import IRImpl -import InstructionSanity - +private import IRImpl +import InstructionSanity + diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/IRVariable.qll index a903e227b26..2eae3dc7c17 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/IRVariable.qll @@ -1,202 +1,202 @@ -private import IRInternal -import FunctionIR -import cpp -import semmle.code.cpp.ir.TempVariableTag -private import semmle.code.cpp.ir.internal.TempVariableTag - -private newtype TIRVariable = - TIRAutomaticUserVariable(LocalScopeVariable var, FunctionIR funcIR) { - exists(Function func | - func = funcIR.getFunction() and - ( - var.getFunction() = func or - var.(Parameter).getCatchBlock().getEnclosingFunction() = func - ) - ) - } or - TIRStaticUserVariable(Variable var, FunctionIR funcIR) { - ( - var instanceof GlobalOrNamespaceVariable or - var instanceof MemberVariable and not var instanceof Field - ) and - exists(VariableAccess access | - access.getTarget() = var and - access.getEnclosingFunction() = funcIR.getFunction() - ) - } or - TIRTempVariable(FunctionIR funcIR, Locatable ast, TempVariableTag tag, - Type type) { - Construction::hasTempVariable(funcIR.getFunction(), ast, tag, type) - } - -IRUserVariable getIRUserVariable(Function func, Variable var) { - result.getVariable() = var and - result.getFunction() = func -} - -/** - * Represents a variable referenced by the IR for a function. The variable may - * be a user-declared variable (`IRUserVariable`) or a temporary variable - * generated by the AST-to-IR translation (`IRTempVariable`). - */ -abstract class IRVariable extends TIRVariable { - FunctionIR funcIR; - - abstract string toString(); - - /** - * Gets the type of the variable. - */ - abstract Type getType(); - - /** - * Gets the AST node that declared this variable, or that introduced this - * variable as part of the AST-to-IR translation. - */ - abstract Locatable getAST(); - - /** - * Gets an identifier string for the variable. This identifier is unique - * within the function. - */ - abstract string getUniqueId(); - - /** - * Gets the source location of this variable. - */ - final Location getLocation() { - result = getAST().getLocation() - } - - /** - * Gets the IR for the function that references this variable. - */ - final FunctionIR getFunctionIR() { - result = funcIR - } - - /** - * Gets the function that references this variable. - */ - final Function getFunction() { - result = funcIR.getFunction() - } -} - -/** - * Represents a user-declared variable referenced by the IR for a function. - */ -abstract class IRUserVariable extends IRVariable { - Variable var; - - override final string toString() { - result = var.toString() - } - - override final Type getType() { - result = var.getType().getUnspecifiedType() - } - - override final Locatable getAST() { - result = var - } - - override final string getUniqueId() { - result = var.toString() + " " + var.getLocation().toString() - } - - /** - * Gets the original user-declared variable. - */ - final Variable getVariable() { - result = var - } -} - -/** - * Represents a variable (user-declared or temporary) that is allocated on the - * stack. This includes all parameters, non-static local variables, and - * temporary variables. - */ -abstract class IRAutomaticVariable extends IRVariable { -} - -class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable, - TIRAutomaticUserVariable { - LocalScopeVariable localVar; - - IRAutomaticUserVariable() { - this = TIRAutomaticUserVariable(localVar, funcIR) and - var = localVar - } - - final LocalScopeVariable getLocalVariable() { - result = localVar - } -} - -class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable { - IRStaticUserVariable() { - this = TIRStaticUserVariable(var, funcIR) - } -} - -IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) { - result.getAST() = ast and - result.getTag() = tag -} - -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Locatable ast; - TempVariableTag tag; - Type type; - - IRTempVariable() { - this = TIRTempVariable(funcIR, ast, tag, type) - } - - override final Type getType() { - result = type - } - - override final Locatable getAST() { - result = ast - } - - override final string getUniqueId() { - result = "Temp: " + Construction::getTempVariableUniqueId(this) - } - - final TempVariableTag getTag() { - result = tag - } - - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { - result = "#temp" - } -} - -class IRReturnVariable extends IRTempVariable { - IRReturnVariable() { - tag = ReturnValueTempVar() - } - - override final string toString() { - result = "#return" - } -} - -class IRThrowVariable extends IRTempVariable { - IRThrowVariable() { - tag = ThrowTempVar() - } - - override string getBaseString() { - result = "#throw" - } -} +private import IRInternal +import FunctionIR +import cpp +import semmle.code.cpp.ir.TempVariableTag +private import semmle.code.cpp.ir.internal.TempVariableTag + +private newtype TIRVariable = + TIRAutomaticUserVariable(LocalScopeVariable var, FunctionIR funcIR) { + exists(Function func | + func = funcIR.getFunction() and + ( + var.getFunction() = func or + var.(Parameter).getCatchBlock().getEnclosingFunction() = func + ) + ) + } or + TIRStaticUserVariable(Variable var, FunctionIR funcIR) { + ( + var instanceof GlobalOrNamespaceVariable or + var instanceof MemberVariable and not var instanceof Field + ) and + exists(VariableAccess access | + access.getTarget() = var and + access.getEnclosingFunction() = funcIR.getFunction() + ) + } or + TIRTempVariable(FunctionIR funcIR, Locatable ast, TempVariableTag tag, + Type type) { + Construction::hasTempVariable(funcIR.getFunction(), ast, tag, type) + } + +IRUserVariable getIRUserVariable(Function func, Variable var) { + result.getVariable() = var and + result.getFunction() = func +} + +/** + * Represents a variable referenced by the IR for a function. The variable may + * be a user-declared variable (`IRUserVariable`) or a temporary variable + * generated by the AST-to-IR translation (`IRTempVariable`). + */ +abstract class IRVariable extends TIRVariable { + FunctionIR funcIR; + + abstract string toString(); + + /** + * Gets the type of the variable. + */ + abstract Type getType(); + + /** + * Gets the AST node that declared this variable, or that introduced this + * variable as part of the AST-to-IR translation. + */ + abstract Locatable getAST(); + + /** + * Gets an identifier string for the variable. This identifier is unique + * within the function. + */ + abstract string getUniqueId(); + + /** + * Gets the source location of this variable. + */ + final Location getLocation() { + result = getAST().getLocation() + } + + /** + * Gets the IR for the function that references this variable. + */ + final FunctionIR getFunctionIR() { + result = funcIR + } + + /** + * Gets the function that references this variable. + */ + final Function getFunction() { + result = funcIR.getFunction() + } +} + +/** + * Represents a user-declared variable referenced by the IR for a function. + */ +abstract class IRUserVariable extends IRVariable { + Variable var; + + override final string toString() { + result = var.toString() + } + + override final Type getType() { + result = var.getType().getUnspecifiedType() + } + + override final Locatable getAST() { + result = var + } + + override final string getUniqueId() { + result = var.toString() + " " + var.getLocation().toString() + } + + /** + * Gets the original user-declared variable. + */ + final Variable getVariable() { + result = var + } +} + +/** + * Represents a variable (user-declared or temporary) that is allocated on the + * stack. This includes all parameters, non-static local variables, and + * temporary variables. + */ +abstract class IRAutomaticVariable extends IRVariable { +} + +class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable, + TIRAutomaticUserVariable { + LocalScopeVariable localVar; + + IRAutomaticUserVariable() { + this = TIRAutomaticUserVariable(localVar, funcIR) and + var = localVar + } + + final LocalScopeVariable getLocalVariable() { + result = localVar + } +} + +class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable { + IRStaticUserVariable() { + this = TIRStaticUserVariable(var, funcIR) + } +} + +IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) { + result.getAST() = ast and + result.getTag() = tag +} + +class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { + Locatable ast; + TempVariableTag tag; + Type type; + + IRTempVariable() { + this = TIRTempVariable(funcIR, ast, tag, type) + } + + override final Type getType() { + result = type + } + + override final Locatable getAST() { + result = ast + } + + override final string getUniqueId() { + result = "Temp: " + Construction::getTempVariableUniqueId(this) + } + + final TempVariableTag getTag() { + result = tag + } + + override string toString() { + result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { + result = "#temp" + } +} + +class IRReturnVariable extends IRTempVariable { + IRReturnVariable() { + tag = ReturnValueTempVar() + } + + override final string toString() { + result = "#return" + } +} + +class IRThrowVariable extends IRTempVariable { + IRThrowVariable() { + tag = ThrowTempVar() + } + + override string getBaseString() { + result = "#throw" + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SSAConstruction.qll index b413532281e..e2760489439 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SSAConstruction.qll @@ -1,424 +1,424 @@ -import SSAConstructionInternal -import cpp -private import semmle.code.cpp.ir.internal.Opcode -import NewIR - -import Cached -cached private module Cached { - - private OldIR::OperandTag getOldOperandTag(OperandTag newTag) { - newTag instanceof LoadStoreAddressOperand and result instanceof OldIR::LoadStoreAddressOperand or - newTag instanceof CopySourceOperand and result instanceof OldIR::CopySourceOperand or - newTag instanceof UnaryOperand and result instanceof OldIR::UnaryOperand or - newTag instanceof LeftOperand and result instanceof OldIR::LeftOperand or - newTag instanceof RightOperand and result instanceof OldIR::RightOperand or - newTag instanceof ReturnValueOperand and result instanceof OldIR::ReturnValueOperand or - newTag instanceof ExceptionOperand and result instanceof OldIR::ExceptionOperand or - newTag instanceof ConditionOperand and result instanceof OldIR::ConditionOperand or - newTag instanceof UnmodeledUseOperand and result instanceof OldIR::UnmodeledUseOperand or - newTag instanceof CallTargetOperand and result instanceof OldIR::CallTargetOperand or - newTag instanceof ThisArgumentOperand and result instanceof OldIR::ThisArgumentOperand or - exists(PositionalArgumentOperand newArg | - newArg = newTag and - result.(OldIR::PositionalArgumentOperand).getArgIndex() = newArg.getArgIndex() - ) - } - - private IRBlock getNewBlock(OldIR::IRBlock oldBlock) { - result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction()) - } - - cached newtype TInstructionTag = - WrappedInstructionTag(OldIR::Instruction oldInstruction) or - PhiTag(Alias::VirtualVariable vvar, OldIR::IRBlock block) { - hasPhiNode(vvar, block) - } - - cached class InstructionTagType extends TInstructionTag { - cached final string toString() { - result = "Tag" - } - } - - cached predicate functionHasIR(Function func) { - exists(OldIR::FunctionIR funcIR | - funcIR.getFunction() = func - ) - } - - cached int getMaxCallArgIndex() { - result = max(int argIndex | - exists(OldIR::PositionalArgumentOperand oldOperand | - argIndex = oldOperand.getArgIndex() - ) - ) - } - - cached OldIR::Instruction getOldInstruction(Instruction instr) { - instr.getTag() = WrappedInstructionTag(result) - } - - private Instruction getNewInstruction(OldIR::Instruction instr) { - getOldInstruction(result) = instr - } - - private PhiInstruction getPhiInstruction(Function func, OldIR::IRBlock oldBlock, - Alias::VirtualVariable vvar) { - result.getFunction() = func and - result.getAST() = oldBlock.getFirstInstruction().getAST() and - result.getTag() = PhiTag(vvar, oldBlock) - } - - private IRVariable getNewIRVariable(OldIR::IRVariable var) { - result.getFunction() = var.getFunction() and - ( - exists(OldIR::IRUserVariable userVar, IRUserVariable newUserVar | - userVar = var and - newUserVar.getVariable() = userVar.getVariable() and - result = newUserVar - ) or - exists(OldIR::IRTempVariable tempVar, IRTempVariable newTempVar | - tempVar = var and - newTempVar.getAST() = tempVar.getAST() and - newTempVar.getTag() = tempVar.getTag() and - result = newTempVar - ) - ) - } - - cached newtype TInstruction = - MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast, - InstructionTag tag, Type resultType, boolean isGLValue) { - hasInstruction(funcIR.getFunction(), opcode, ast, tag, - resultType, isGLValue) - } - - private predicate hasInstruction(Function func, Opcode opcode, Locatable ast, - InstructionTag tag, Type resultType, boolean isGLValue) { - exists(OldIR::Instruction instr | - instr.getFunction() = func and - instr.getOpcode() = opcode and - instr.getAST() = ast and - WrappedInstructionTag(instr) = tag and - instr.getResultType() = resultType and - if instr.isGLValue() then - isGLValue = true - else - isGLValue = false - ) or - exists(OldIR::IRBlock block, Alias::VirtualVariable vvar | - hasPhiNode(vvar, block) and - block.getFunction() = func and - opcode instanceof Opcode::Phi and - ast = block.getFirstInstruction().getAST() and - tag = PhiTag(vvar, block) and - resultType = vvar.getType() and - isGLValue = false - ) - } - - cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, - Type type) { - exists(OldIR::IRTempVariable var | - var.getFunction() = func and - var.getAST() = ast and - var.getTag() = tag and - var.getType() = type - ) - } - - cached predicate hasModeledMemoryResult(Instruction instruction) { - exists(Alias::getResultMemoryAccess(getOldInstruction(instruction))) or - instruction instanceof PhiInstruction // Phis always have modeled results - } - - cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) { - exists(OldIR::Instruction oldUse, OldIR::OperandTag oldTag | - oldUse = getOldInstruction(instruction) and - oldTag = getOldOperandTag(tag) and - if oldUse.isMemoryOperand(oldTag) then ( - ( - if exists(Alias::getOperandMemoryAccess(oldUse, oldTag)) then ( - exists(OldIR::IRBlock useBlock, int useRank, Alias::VirtualVariable vvar, - OldIR::IRBlock defBlock, int defRank, int defIndex | - vvar = Alias::getOperandMemoryAccess(oldUse, oldTag).getVirtualVariable() and - hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and - hasUseAtRank(vvar, useBlock, useRank, oldUse) and - definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and - if defIndex >= 0 then - result = getNewInstruction(defBlock.getInstruction(defIndex)) - else - result = getPhiInstruction(instruction.getFunction(), defBlock, vvar) - ) - ) - else ( - result = instruction.getFunctionIR().getUnmodeledDefinitionInstruction() - ) - ) or - // Connect any definitions that are not being modeled in SSA to the - // `UnmodeledUse` instruction. - exists(OldIR::Instruction oldDefinition | - instruction instanceof UnmodeledUseInstruction and - tag instanceof UnmodeledUseOperand and - oldDefinition = oldUse.getOperand(oldTag) and - not exists(Alias::getResultMemoryAccess(oldDefinition)) and - result = getNewInstruction(oldDefinition) - ) - ) - else - result = getNewInstruction(oldUse.getOperand(oldTag)) - ) or - result = getPhiInstructionOperand(instruction.(PhiInstruction), tag.(PhiOperand)) - } - - cached Instruction getPhiInstructionOperand(PhiInstruction instr, PhiOperand tag) { - exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock, - OldIR::IRBlock defBlock, int defRank, int defIndex, OldIR::IRBlock predBlock | - hasPhiNode(vvar, phiBlock) and - predBlock = phiBlock.getAPredecessor() and - instr.getTag() = PhiTag(vvar, phiBlock) and - tag.getPredecessorBlock() = getNewBlock(predBlock) and - hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and - definitionReachesEndOfBlock(vvar, defBlock, defRank, predBlock) and - if defIndex >= 0 then - result = getNewInstruction(defBlock.getInstruction(defIndex)) - else - result = getPhiInstruction(instr.getFunction(), defBlock, vvar) - ) - } - - cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) { - exists(OldIR::IRBlock oldBlock | - instr.getTag() = PhiTag(_, oldBlock) and - result = getNewInstruction(oldBlock.getFirstInstruction()) - ) - } - - cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) { - result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind)) - } - - cached IRVariable getInstructionVariable(Instruction instruction) { - result = getNewIRVariable(getOldInstruction(instruction).(OldIR::VariableInstruction).getVariable()) - } - - cached Field getInstructionField(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField() - } - - cached Function getInstructionFunction(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol() - } - - cached string getInstructionConstantValue(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() - } - - cached StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() - } - - cached Type getInstructionExceptionType(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType() - } - - cached int getInstructionElementSize(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::PointerArithmeticInstruction).getElementSize() - } - - cached int getInstructionResultSize(Instruction instruction) { - // Only return a result for instructions that needed an explicit result size. - instruction.getResultType() instanceof UnknownType and - result = getOldInstruction(instruction).getResultSize() - } - - cached predicate getInstructionInheritance(Instruction instruction, Class baseClass, - Class derivedClass) { - exists(OldIR::InheritanceConversionInstruction oldInstr | - oldInstr = getOldInstruction(instruction) and - baseClass = oldInstr.getBaseClass() and - derivedClass = oldInstr.getDerivedClass() - ) - } - - private predicate ssa_variableUpdate(Alias::VirtualVariable vvar, - OldIR::Instruction instr, OldIR::IRBlock block, int index) { - block.getInstruction(index) = instr and - Alias::getResultMemoryAccess(instr).getVirtualVariable() = vvar - } - - private predicate hasDefinition(Alias::VirtualVariable vvar, OldIR::IRBlock block, int index) { - ( - hasPhiNode(vvar, block) and - index = -1 - ) or - exists(Alias::MemoryAccess access, OldIR::Instruction def | - access = Alias::getResultMemoryAccess(def) and - block.getInstruction(index) = def and - vvar = access.getVirtualVariable() - ) - } - - private predicate defUseRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, int rankIndex, int index) { - index = rank[rankIndex](int j | hasDefinition(vvar, block, j) or hasUse(vvar, _, block, j)) - } - - private predicate hasUse(Alias::VirtualVariable vvar, - OldIR::Instruction use, OldIR::IRBlock block, int index) { - exists(Alias::MemoryAccess access | - access = Alias::getOperandMemoryAccess(use, _) and - block.getInstruction(index) = use and - vvar = access.getVirtualVariable() - ) - } - - private predicate variableLiveOnEntryToBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) { - exists (int index | hasUse(vvar, _, block, index) | - not exists (int j | ssa_variableUpdate(vvar, _, block, j) | j < index) - ) or - (variableLiveOnExitFromBlock(vvar, block) and not ssa_variableUpdate(vvar, _, block, _)) - } - - pragma[noinline] - private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) { - variableLiveOnEntryToBlock(vvar, block.getASuccessor()) - } - - /** - * Gets the rank index of a hyphothetical use one instruction past the end of - * the block. This index can be used to determine if a definition reaches the - * end of the block, even if the definition is the last instruction in the - * block. - */ - private int exitRank(Alias::VirtualVariable vvar, OldIR::IRBlock block) { - result = max(int rankIndex | defUseRank(vvar, block, rankIndex, _)) + 1 - } - - private predicate hasDefinitionAtRank(Alias::VirtualVariable vvar, - OldIR::IRBlock block, int rankIndex, int instructionIndex) { - hasDefinition(vvar, block, instructionIndex) and - defUseRank(vvar, block, rankIndex, instructionIndex) - } - - private predicate hasUseAtRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, - int rankIndex, OldIR::Instruction use) { - exists(int index | - hasUse(vvar, use, block, index) and - defUseRank(vvar, block, rankIndex, index) - ) - } - - /** - * Holds if the definition of `vvar` at `(block, defRank)` reaches the rank - * index `reachesRank` in block `block`. - */ - private predicate definitionReachesRank(Alias::VirtualVariable vvar, - OldIR::IRBlock block, int defRank, int reachesRank) { - hasDefinitionAtRank(vvar, block, defRank, _) and - reachesRank <= exitRank(vvar, block) and // Without this, the predicate would be infinite. - ( - // The def always reaches the next use, even if there is also a def on the - // use instruction. - reachesRank = defRank + 1 or - ( - // If the def reached the previous rank, it also reaches the current rank, - // unless there was another def at the previous rank. - definitionReachesRank(vvar, block, defRank, reachesRank - 1) and - not hasDefinitionAtRank(vvar, block, reachesRank - 1, _) - ) - ) - } - - /** - * Holds if the definition of `vvar` at `(defBlock, defRank)` reaches the end of - * block `block`. - */ - private predicate definitionReachesEndOfBlock(Alias::VirtualVariable vvar, - OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock block) { - hasDefinitionAtRank(vvar, defBlock, defRank, _) and - ( - ( - // If we're looking at the def's own block, just see if it reaches the exit - // rank of the block. - block = defBlock and - variableLiveOnExitFromBlock(vvar, defBlock) and - definitionReachesRank(vvar, defBlock, defRank, exitRank(vvar, defBlock)) - ) or - exists(OldIR::IRBlock idom | - definitionReachesEndOfBlock(vvar, defBlock, defRank, idom) and - noDefinitionsSinceIDominator(vvar, idom, block) - ) - ) - } - - pragma[noinline] - private predicate noDefinitionsSinceIDominator(Alias::VirtualVariable vvar, - OldIR::IRBlock idom, OldIR::IRBlock block) { - idom.immediatelyDominates(block) and // It is sufficient to traverse the dominator graph, cf. discussion above. - variableLiveOnExitFromBlock(vvar, block) and - not hasDefinition(vvar, block, _) - } - - private predicate definitionReachesUseWithinBlock( - Alias::VirtualVariable vvar, OldIR::IRBlock defBlock, int defRank, - OldIR::IRBlock useBlock, int useRank) { - defBlock = useBlock and - hasDefinitionAtRank(vvar, defBlock, defRank, _) and - hasUseAtRank(vvar, useBlock, useRank, _) and - definitionReachesRank(vvar, defBlock, defRank, useRank) - } - - private predicate definitionReachesUse(Alias::VirtualVariable vvar, - OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock useBlock, int useRank) { - hasUseAtRank(vvar, useBlock, useRank, _) and - ( - definitionReachesUseWithinBlock(vvar, defBlock, defRank, useBlock, - useRank) or - ( - definitionReachesEndOfBlock(vvar, defBlock, defRank, - useBlock.getAPredecessor()) and - not definitionReachesUseWithinBlock(vvar, useBlock, _, useBlock, useRank) - ) - ) - } - - private predicate hasFrontierPhiNode(Alias::VirtualVariable vvar, - OldIR::IRBlock phiBlock) { - exists(OldIR::IRBlock defBlock | - phiBlock = defBlock.dominanceFrontier() and - hasDefinition(vvar, defBlock, _) and - /* We can also eliminate those nodes where the variable is not live on any incoming edge */ - variableLiveOnEntryToBlock(vvar, phiBlock) - ) - } - - private predicate hasPhiNode(Alias::VirtualVariable vvar, - OldIR::IRBlock phiBlock) { - hasFrontierPhiNode(vvar, phiBlock) - //or ssa_sanitized_custom_phi_node(vvar, block) - } -} - -import CachedForDebugging -cached private module CachedForDebugging { - cached string getTempVariableUniqueId(IRTempVariable var) { - result = getOldTempVariable(var).getUniqueId() - } - - cached string getInstructionUniqueId(Instruction instr) { - exists(OldIR::Instruction oldInstr | - oldInstr = getOldInstruction(instr) and - result = "NonSSA: " + oldInstr.getUniqueId() - ) or - exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock | - instr.getTag() = PhiTag(vvar, phiBlock) and - result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId() - ) - } - - private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) { - result.getFunction() = var.getFunction() and - result.getAST() = var.getAST() and - result.getTag() = var.getTag() - } -} +import SSAConstructionInternal +import cpp +private import semmle.code.cpp.ir.internal.Opcode +import NewIR + +import Cached +cached private module Cached { + + private OldIR::OperandTag getOldOperandTag(OperandTag newTag) { + newTag instanceof LoadStoreAddressOperand and result instanceof OldIR::LoadStoreAddressOperand or + newTag instanceof CopySourceOperand and result instanceof OldIR::CopySourceOperand or + newTag instanceof UnaryOperand and result instanceof OldIR::UnaryOperand or + newTag instanceof LeftOperand and result instanceof OldIR::LeftOperand or + newTag instanceof RightOperand and result instanceof OldIR::RightOperand or + newTag instanceof ReturnValueOperand and result instanceof OldIR::ReturnValueOperand or + newTag instanceof ExceptionOperand and result instanceof OldIR::ExceptionOperand or + newTag instanceof ConditionOperand and result instanceof OldIR::ConditionOperand or + newTag instanceof UnmodeledUseOperand and result instanceof OldIR::UnmodeledUseOperand or + newTag instanceof CallTargetOperand and result instanceof OldIR::CallTargetOperand or + newTag instanceof ThisArgumentOperand and result instanceof OldIR::ThisArgumentOperand or + exists(PositionalArgumentOperand newArg | + newArg = newTag and + result.(OldIR::PositionalArgumentOperand).getArgIndex() = newArg.getArgIndex() + ) + } + + private IRBlock getNewBlock(OldIR::IRBlock oldBlock) { + result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction()) + } + + cached newtype TInstructionTag = + WrappedInstructionTag(OldIR::Instruction oldInstruction) or + PhiTag(Alias::VirtualVariable vvar, OldIR::IRBlock block) { + hasPhiNode(vvar, block) + } + + cached class InstructionTagType extends TInstructionTag { + cached final string toString() { + result = "Tag" + } + } + + cached predicate functionHasIR(Function func) { + exists(OldIR::FunctionIR funcIR | + funcIR.getFunction() = func + ) + } + + cached int getMaxCallArgIndex() { + result = max(int argIndex | + exists(OldIR::PositionalArgumentOperand oldOperand | + argIndex = oldOperand.getArgIndex() + ) + ) + } + + cached OldIR::Instruction getOldInstruction(Instruction instr) { + instr.getTag() = WrappedInstructionTag(result) + } + + private Instruction getNewInstruction(OldIR::Instruction instr) { + getOldInstruction(result) = instr + } + + private PhiInstruction getPhiInstruction(Function func, OldIR::IRBlock oldBlock, + Alias::VirtualVariable vvar) { + result.getFunction() = func and + result.getAST() = oldBlock.getFirstInstruction().getAST() and + result.getTag() = PhiTag(vvar, oldBlock) + } + + private IRVariable getNewIRVariable(OldIR::IRVariable var) { + result.getFunction() = var.getFunction() and + ( + exists(OldIR::IRUserVariable userVar, IRUserVariable newUserVar | + userVar = var and + newUserVar.getVariable() = userVar.getVariable() and + result = newUserVar + ) or + exists(OldIR::IRTempVariable tempVar, IRTempVariable newTempVar | + tempVar = var and + newTempVar.getAST() = tempVar.getAST() and + newTempVar.getTag() = tempVar.getTag() and + result = newTempVar + ) + ) + } + + cached newtype TInstruction = + MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast, + InstructionTag tag, Type resultType, boolean isGLValue) { + hasInstruction(funcIR.getFunction(), opcode, ast, tag, + resultType, isGLValue) + } + + private predicate hasInstruction(Function func, Opcode opcode, Locatable ast, + InstructionTag tag, Type resultType, boolean isGLValue) { + exists(OldIR::Instruction instr | + instr.getFunction() = func and + instr.getOpcode() = opcode and + instr.getAST() = ast and + WrappedInstructionTag(instr) = tag and + instr.getResultType() = resultType and + if instr.isGLValue() then + isGLValue = true + else + isGLValue = false + ) or + exists(OldIR::IRBlock block, Alias::VirtualVariable vvar | + hasPhiNode(vvar, block) and + block.getFunction() = func and + opcode instanceof Opcode::Phi and + ast = block.getFirstInstruction().getAST() and + tag = PhiTag(vvar, block) and + resultType = vvar.getType() and + isGLValue = false + ) + } + + cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, + Type type) { + exists(OldIR::IRTempVariable var | + var.getFunction() = func and + var.getAST() = ast and + var.getTag() = tag and + var.getType() = type + ) + } + + cached predicate hasModeledMemoryResult(Instruction instruction) { + exists(Alias::getResultMemoryAccess(getOldInstruction(instruction))) or + instruction instanceof PhiInstruction // Phis always have modeled results + } + + cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) { + exists(OldIR::Instruction oldUse, OldIR::OperandTag oldTag | + oldUse = getOldInstruction(instruction) and + oldTag = getOldOperandTag(tag) and + if oldUse.isMemoryOperand(oldTag) then ( + ( + if exists(Alias::getOperandMemoryAccess(oldUse, oldTag)) then ( + exists(OldIR::IRBlock useBlock, int useRank, Alias::VirtualVariable vvar, + OldIR::IRBlock defBlock, int defRank, int defIndex | + vvar = Alias::getOperandMemoryAccess(oldUse, oldTag).getVirtualVariable() and + hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and + hasUseAtRank(vvar, useBlock, useRank, oldUse) and + definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and + if defIndex >= 0 then + result = getNewInstruction(defBlock.getInstruction(defIndex)) + else + result = getPhiInstruction(instruction.getFunction(), defBlock, vvar) + ) + ) + else ( + result = instruction.getFunctionIR().getUnmodeledDefinitionInstruction() + ) + ) or + // Connect any definitions that are not being modeled in SSA to the + // `UnmodeledUse` instruction. + exists(OldIR::Instruction oldDefinition | + instruction instanceof UnmodeledUseInstruction and + tag instanceof UnmodeledUseOperand and + oldDefinition = oldUse.getOperand(oldTag) and + not exists(Alias::getResultMemoryAccess(oldDefinition)) and + result = getNewInstruction(oldDefinition) + ) + ) + else + result = getNewInstruction(oldUse.getOperand(oldTag)) + ) or + result = getPhiInstructionOperand(instruction.(PhiInstruction), tag.(PhiOperand)) + } + + cached Instruction getPhiInstructionOperand(PhiInstruction instr, PhiOperand tag) { + exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock, + OldIR::IRBlock defBlock, int defRank, int defIndex, OldIR::IRBlock predBlock | + hasPhiNode(vvar, phiBlock) and + predBlock = phiBlock.getAPredecessor() and + instr.getTag() = PhiTag(vvar, phiBlock) and + tag.getPredecessorBlock() = getNewBlock(predBlock) and + hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and + definitionReachesEndOfBlock(vvar, defBlock, defRank, predBlock) and + if defIndex >= 0 then + result = getNewInstruction(defBlock.getInstruction(defIndex)) + else + result = getPhiInstruction(instr.getFunction(), defBlock, vvar) + ) + } + + cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) { + exists(OldIR::IRBlock oldBlock | + instr.getTag() = PhiTag(_, oldBlock) and + result = getNewInstruction(oldBlock.getFirstInstruction()) + ) + } + + cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) { + result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind)) + } + + cached IRVariable getInstructionVariable(Instruction instruction) { + result = getNewIRVariable(getOldInstruction(instruction).(OldIR::VariableInstruction).getVariable()) + } + + cached Field getInstructionField(Instruction instruction) { + result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField() + } + + cached Function getInstructionFunction(Instruction instruction) { + result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol() + } + + cached string getInstructionConstantValue(Instruction instruction) { + result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() + } + + cached StringLiteral getInstructionStringLiteral(Instruction instruction) { + result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() + } + + cached Type getInstructionExceptionType(Instruction instruction) { + result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType() + } + + cached int getInstructionElementSize(Instruction instruction) { + result = getOldInstruction(instruction).(OldIR::PointerArithmeticInstruction).getElementSize() + } + + cached int getInstructionResultSize(Instruction instruction) { + // Only return a result for instructions that needed an explicit result size. + instruction.getResultType() instanceof UnknownType and + result = getOldInstruction(instruction).getResultSize() + } + + cached predicate getInstructionInheritance(Instruction instruction, Class baseClass, + Class derivedClass) { + exists(OldIR::InheritanceConversionInstruction oldInstr | + oldInstr = getOldInstruction(instruction) and + baseClass = oldInstr.getBaseClass() and + derivedClass = oldInstr.getDerivedClass() + ) + } + + private predicate ssa_variableUpdate(Alias::VirtualVariable vvar, + OldIR::Instruction instr, OldIR::IRBlock block, int index) { + block.getInstruction(index) = instr and + Alias::getResultMemoryAccess(instr).getVirtualVariable() = vvar + } + + private predicate hasDefinition(Alias::VirtualVariable vvar, OldIR::IRBlock block, int index) { + ( + hasPhiNode(vvar, block) and + index = -1 + ) or + exists(Alias::MemoryAccess access, OldIR::Instruction def | + access = Alias::getResultMemoryAccess(def) and + block.getInstruction(index) = def and + vvar = access.getVirtualVariable() + ) + } + + private predicate defUseRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, int rankIndex, int index) { + index = rank[rankIndex](int j | hasDefinition(vvar, block, j) or hasUse(vvar, _, block, j)) + } + + private predicate hasUse(Alias::VirtualVariable vvar, + OldIR::Instruction use, OldIR::IRBlock block, int index) { + exists(Alias::MemoryAccess access | + access = Alias::getOperandMemoryAccess(use, _) and + block.getInstruction(index) = use and + vvar = access.getVirtualVariable() + ) + } + + private predicate variableLiveOnEntryToBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) { + exists (int index | hasUse(vvar, _, block, index) | + not exists (int j | ssa_variableUpdate(vvar, _, block, j) | j < index) + ) or + (variableLiveOnExitFromBlock(vvar, block) and not ssa_variableUpdate(vvar, _, block, _)) + } + + pragma[noinline] + private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) { + variableLiveOnEntryToBlock(vvar, block.getASuccessor()) + } + + /** + * Gets the rank index of a hyphothetical use one instruction past the end of + * the block. This index can be used to determine if a definition reaches the + * end of the block, even if the definition is the last instruction in the + * block. + */ + private int exitRank(Alias::VirtualVariable vvar, OldIR::IRBlock block) { + result = max(int rankIndex | defUseRank(vvar, block, rankIndex, _)) + 1 + } + + private predicate hasDefinitionAtRank(Alias::VirtualVariable vvar, + OldIR::IRBlock block, int rankIndex, int instructionIndex) { + hasDefinition(vvar, block, instructionIndex) and + defUseRank(vvar, block, rankIndex, instructionIndex) + } + + private predicate hasUseAtRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, + int rankIndex, OldIR::Instruction use) { + exists(int index | + hasUse(vvar, use, block, index) and + defUseRank(vvar, block, rankIndex, index) + ) + } + + /** + * Holds if the definition of `vvar` at `(block, defRank)` reaches the rank + * index `reachesRank` in block `block`. + */ + private predicate definitionReachesRank(Alias::VirtualVariable vvar, + OldIR::IRBlock block, int defRank, int reachesRank) { + hasDefinitionAtRank(vvar, block, defRank, _) and + reachesRank <= exitRank(vvar, block) and // Without this, the predicate would be infinite. + ( + // The def always reaches the next use, even if there is also a def on the + // use instruction. + reachesRank = defRank + 1 or + ( + // If the def reached the previous rank, it also reaches the current rank, + // unless there was another def at the previous rank. + definitionReachesRank(vvar, block, defRank, reachesRank - 1) and + not hasDefinitionAtRank(vvar, block, reachesRank - 1, _) + ) + ) + } + + /** + * Holds if the definition of `vvar` at `(defBlock, defRank)` reaches the end of + * block `block`. + */ + private predicate definitionReachesEndOfBlock(Alias::VirtualVariable vvar, + OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock block) { + hasDefinitionAtRank(vvar, defBlock, defRank, _) and + ( + ( + // If we're looking at the def's own block, just see if it reaches the exit + // rank of the block. + block = defBlock and + variableLiveOnExitFromBlock(vvar, defBlock) and + definitionReachesRank(vvar, defBlock, defRank, exitRank(vvar, defBlock)) + ) or + exists(OldIR::IRBlock idom | + definitionReachesEndOfBlock(vvar, defBlock, defRank, idom) and + noDefinitionsSinceIDominator(vvar, idom, block) + ) + ) + } + + pragma[noinline] + private predicate noDefinitionsSinceIDominator(Alias::VirtualVariable vvar, + OldIR::IRBlock idom, OldIR::IRBlock block) { + idom.immediatelyDominates(block) and // It is sufficient to traverse the dominator graph, cf. discussion above. + variableLiveOnExitFromBlock(vvar, block) and + not hasDefinition(vvar, block, _) + } + + private predicate definitionReachesUseWithinBlock( + Alias::VirtualVariable vvar, OldIR::IRBlock defBlock, int defRank, + OldIR::IRBlock useBlock, int useRank) { + defBlock = useBlock and + hasDefinitionAtRank(vvar, defBlock, defRank, _) and + hasUseAtRank(vvar, useBlock, useRank, _) and + definitionReachesRank(vvar, defBlock, defRank, useRank) + } + + private predicate definitionReachesUse(Alias::VirtualVariable vvar, + OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock useBlock, int useRank) { + hasUseAtRank(vvar, useBlock, useRank, _) and + ( + definitionReachesUseWithinBlock(vvar, defBlock, defRank, useBlock, + useRank) or + ( + definitionReachesEndOfBlock(vvar, defBlock, defRank, + useBlock.getAPredecessor()) and + not definitionReachesUseWithinBlock(vvar, useBlock, _, useBlock, useRank) + ) + ) + } + + private predicate hasFrontierPhiNode(Alias::VirtualVariable vvar, + OldIR::IRBlock phiBlock) { + exists(OldIR::IRBlock defBlock | + phiBlock = defBlock.dominanceFrontier() and + hasDefinition(vvar, defBlock, _) and + /* We can also eliminate those nodes where the variable is not live on any incoming edge */ + variableLiveOnEntryToBlock(vvar, phiBlock) + ) + } + + private predicate hasPhiNode(Alias::VirtualVariable vvar, + OldIR::IRBlock phiBlock) { + hasFrontierPhiNode(vvar, phiBlock) + //or ssa_sanitized_custom_phi_node(vvar, block) + } +} + +import CachedForDebugging +cached private module CachedForDebugging { + cached string getTempVariableUniqueId(IRTempVariable var) { + result = getOldTempVariable(var).getUniqueId() + } + + cached string getInstructionUniqueId(Instruction instr) { + exists(OldIR::Instruction oldInstr | + oldInstr = getOldInstruction(instr) and + result = "NonSSA: " + oldInstr.getUniqueId() + ) or + exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock | + instr.getTag() = PhiTag(vvar, phiBlock) and + result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId() + ) + } + + private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) { + result.getFunction() = var.getFunction() and + result.getAST() = var.getAST() and + result.getTag() = var.getTag() + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SSAConstructionInternal.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SSAConstructionInternal.qll index 32b79304b11..7ceb3b2572d 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SSAConstructionInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SSAConstructionInternal.qll @@ -1,3 +1,3 @@ -import semmle.code.cpp.ssa.SSAIR as OldIR -import semmle.code.cpp.ssa.AliasedSSAIR as NewIR -import SimpleSSA as Alias +import semmle.code.cpp.ssa.SSAIR as OldIR +import semmle.code.cpp.ssa.AliasedSSAIR as NewIR +import SimpleSSA as Alias diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SimpleSSA.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SimpleSSA.qll index 27287312f16..7f1fe39b4b2 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SimpleSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SimpleSSA.qll @@ -1,83 +1,83 @@ -import SimpleSSAInternal -import cpp -import Alias -import IR -import semmle.code.cpp.ssa.internal.Overlap - -private newtype TVirtualVariable = - MkVirtualVariable(IRVariable var) { - not variableAddressEscapes(var) - } - -private VirtualVariable getVirtualVariable(IRVariable var) { - result.getIRVariable() = var -} - -class VirtualVariable extends TVirtualVariable { - IRVariable var; - - VirtualVariable() { - this = MkVirtualVariable(var) - } - - final string toString() { - result = var.toString() - } - - final IRVariable getIRVariable() { - result = var - } - - // REVIEW: This should just be on MemoryAccess - final Type getType() { - result = var.getType() - } - - final string getUniqueId() { - result = var.getUniqueId() - } -} - -private newtype TMemoryAccess = - MkMemoryAccess(VirtualVariable vvar) - -private MemoryAccess getMemoryAccess(IRVariable var) { - result.getVirtualVariable() = getVirtualVariable(var) -} - -class MemoryAccess extends TMemoryAccess { - VirtualVariable vvar; - - MemoryAccess() { - this = MkMemoryAccess(vvar) - } - - string toString() { - result = vvar.toString() - } - - VirtualVariable getVirtualVariable() { - result = vvar - } -} - -Overlap getOverlap(MemoryAccess def, MemoryAccess use) { - def.getVirtualVariable() = use.getVirtualVariable() and - result instanceof MustExactlyOverlap -} - -MemoryAccess getResultMemoryAccess(Instruction instr) { - exists(IRVariable var | - instr.getResultMemoryAccess() instanceof IndirectMemoryAccess and - resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and - result = getMemoryAccess(var) - ) -} - -MemoryAccess getOperandMemoryAccess(Instruction instr, OperandTag tag) { - exists(IRVariable var | - instr.getOperandMemoryAccess(tag) instanceof IndirectMemoryAccess and - resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and - result = getMemoryAccess(var) - ) -} +import SimpleSSAInternal +import cpp +import Alias +import IR +import semmle.code.cpp.ssa.internal.Overlap + +private newtype TVirtualVariable = + MkVirtualVariable(IRVariable var) { + not variableAddressEscapes(var) + } + +private VirtualVariable getVirtualVariable(IRVariable var) { + result.getIRVariable() = var +} + +class VirtualVariable extends TVirtualVariable { + IRVariable var; + + VirtualVariable() { + this = MkVirtualVariable(var) + } + + final string toString() { + result = var.toString() + } + + final IRVariable getIRVariable() { + result = var + } + + // REVIEW: This should just be on MemoryAccess + final Type getType() { + result = var.getType() + } + + final string getUniqueId() { + result = var.getUniqueId() + } +} + +private newtype TMemoryAccess = + MkMemoryAccess(VirtualVariable vvar) + +private MemoryAccess getMemoryAccess(IRVariable var) { + result.getVirtualVariable() = getVirtualVariable(var) +} + +class MemoryAccess extends TMemoryAccess { + VirtualVariable vvar; + + MemoryAccess() { + this = MkMemoryAccess(vvar) + } + + string toString() { + result = vvar.toString() + } + + VirtualVariable getVirtualVariable() { + result = vvar + } +} + +Overlap getOverlap(MemoryAccess def, MemoryAccess use) { + def.getVirtualVariable() = use.getVirtualVariable() and + result instanceof MustExactlyOverlap +} + +MemoryAccess getResultMemoryAccess(Instruction instr) { + exists(IRVariable var | + instr.getResultMemoryAccess() instanceof IndirectMemoryAccess and + resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and + result = getMemoryAccess(var) + ) +} + +MemoryAccess getOperandMemoryAccess(Instruction instr, OperandTag tag) { + exists(IRVariable var | + instr.getOperandMemoryAccess(tag) instanceof IndirectMemoryAccess and + resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and + result = getMemoryAccess(var) + ) +} diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SimpleSSAInternal.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SimpleSSAInternal.qll index c3dfbc26594..48651bf3978 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SimpleSSAInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/aliased_ssa/SimpleSSAInternal.qll @@ -1,3 +1,3 @@ -import AliasAnalysis as Alias -import semmle.code.cpp.ssa.SSAIR as IR - +import AliasAnalysis as Alias +import semmle.code.cpp.ssa.SSAIR as IR + diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/AliasAnalysis.qll index cc42ce1c96e..6d40ee0f66b 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/AliasAnalysis.qll @@ -1,214 +1,214 @@ -private import AliasAnalysisInternal -import cpp -private import IR -private import semmle.code.cpp.ssa.internal.IntegerConstant as Ints - -private class IntValue = Ints::IntValue; - -/** - * Converts the bit count in `bits` to a byte count and a bit count in the form - * bytes:bits. - */ -bindingset[bits] -string bitsToBytesAndBits(int bits) { - result = (bits / 8).toString() + ":" + (bits % 8).toString() -} - -/** - * Gets a printable string for a bit offset with possibly unknown value. - */ -bindingset[bitOffset] -string getBitOffsetString(IntValue bitOffset) { - if Ints::hasValue(bitOffset) then - if bitOffset >= 0 then - result = "+" + bitsToBytesAndBits(bitOffset) - else - result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset)) - else - result = "+?" -} - -/** - * Gets the offset of field `field` in bits. - */ -private IntValue getFieldBitOffset(Field field) { - if (field instanceof BitField) then ( - result = Ints::add(Ints::mul(field.getByteOffset(), 8), - field.(BitField).getBitOffset()) - ) - else ( - result = Ints::mul(field.getByteOffset(), 8) - ) -} - -/** - * Holds if the operand `tag` of instruction `instr` is used in a way that does - * not result in any address held in that operand from escaping beyond the - * instruction. - */ -predicate operandIsConsumedWithoutEscaping(Instruction instr, OperandTag tag) { - exists(instr.getOperand(tag)) and - ( - // The source/destination address of a Load/Store does not escape (but the - // loaded/stored value could). - tag instanceof LoadStoreAddressOperand or - // Neither operand of a Compare escapes. - instr instanceof CompareInstruction or - // Neither operand of a PointerDiff escapes. - instr instanceof PointerDiffInstruction or - // Converting an address to a `bool` does not escape the address. - instr.(ConvertInstruction).getResultType() instanceof BoolType - ) -} - -/** - * If the result of instruction `instr` is an integer constant, returns the - * value of that constant. Otherwise, returns unknown. - */ -IntValue getConstantValue(Instruction instr) { - if instr instanceof IntegerConstantInstruction then - result = instr.(IntegerConstantInstruction).getValue().toInt() - else - result = Ints::unknown() -} - -/** - * Computes the offset, in bits, by which the result of `instr` differs from the - * pointer argument to `instr`, if that offset is a constant. Otherwise, returns - * unknown. - */ -IntValue getPointerBitOffset(PointerOffsetInstruction instr) { - exists(IntValue bitOffset | - ( - bitOffset = Ints::mul(Ints::mul(getConstantValue(instr.getRightOperand()), - instr.getElementSize()), 8) - ) and - ( - instr instanceof PointerAddInstruction and result = bitOffset or - instr instanceof PointerSubInstruction and result = Ints::neg(bitOffset) - ) - ) -} - -/** - * Holds if any address held in operand `tag` of instruction `instr` is - * propagated to the result of `instr`, offset by the number of bits in - * `bitOffset`. If the address is propagated, but the offset is not known to be - * a constant, then `bitOffset` is unknown. - */ -predicate operandIsPropagated(Instruction instr, OperandTag tag, - IntValue bitOffset) { - exists(instr.getOperand(tag)) and - ( - // Converting to a non-virtual base class adds the offset of the base class. - exists(ConvertToBaseInstruction convert | - convert = instr and - bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) - ) or - // Converting to a derived class subtracts the offset of the base class. - exists(ConvertToDerivedInstruction convert | - convert = instr and - bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8)) - ) or - // Converting to a virtual base class adds an unknown offset. - ( - instr instanceof ConvertToVirtualBaseInstruction and - bitOffset = Ints::unknown() - ) or - // Conversion to another pointer type propagates the source address. - exists(ConvertInstruction convert, Type resultType | - convert = instr and - resultType = convert.getResultType() and - ( - resultType instanceof PointerType or - resultType instanceof Class //REVIEW: Remove when all glvalues are pointers - ) and - bitOffset = 0 - ) or - // Adding an integer to or subtracting an integer from a pointer propagates - // the address with an offset. - bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or - // Computing a field address from a pointer propagates the address plus the - // offset of the field. - bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or - // A copy propagates the source value. - tag instanceof CopySourceOperand and bitOffset = 0 - ) -} - -/** - * Holds if any address held in operand number `tag` of instruction `instr` - * escapes outside the domain of the analysis. - */ -predicate operandEscapes(Instruction instr, OperandTag tag) { - exists(instr.getOperand(tag)) and - // Conservatively assume that the address escapes unless one of the following - // holds: - not ( - // The operand is used in a way that does not escape the instruction - operandIsConsumedWithoutEscaping(instr, tag) or - // The address is propagated to the result of the instruction, but that - // result does not itself escape. - operandIsPropagated(instr, tag, _) and not resultEscapes(instr) - ) -} - -/** - * Holds if any address held in the result of instruction `instr` escapes - * outside the domain of the analysis. - */ -predicate resultEscapes(Instruction instr) { - // The result escapes if it has at least one use that escapes. - exists(Instruction useInstr, OperandTag useOperandTag | - useInstr.getOperand(useOperandTag) = instr and - operandEscapes(useInstr, useOperandTag) - ) -} - -/** - * Holds if the address of the specified local variable or parameter escapes the - * domain of the analysis. - */ -private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) { - exists(FunctionIR funcIR | - funcIR = var.getFunctionIR() and - // The variable's address escapes if the result of any - // VariableAddressInstruction that computes the variable's address escapes. - exists(VariableAddressInstruction instr | - instr.getFunctionIR() = funcIR and - instr.getVariable() = var and - resultEscapes(instr) - ) - ) -} - -/** - * Holds if the address of the specified variable escapes the domain of the - * analysis. - */ -predicate variableAddressEscapes(IRVariable var) { - automaticVariableAddressEscapes(var.(IRAutomaticVariable)) or - // All variables with static storage duration have their address escape. - not var instanceof IRAutomaticVariable -} - -/** - * Holds if the result of instruction `instr` points within variable `var`, at - * bit offset `bitOffset` within the variable. If the result points within - * `var`, but at an unknown or non-constant offset, then `bitOffset` is unknown. - */ -predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) { - ( - // The address of a variable points to that variable, at offset 0. - instr.(VariableAddressInstruction).getVariable() = var and - bitOffset = 0 - ) or - exists(OperandTag operandTag, IntValue originalBitOffset, - IntValue propagatedBitOffset | - // If an operand is propagated, then the result points to the same variable, - // offset by the bit offset from the propagation. - resultPointsTo(instr.getOperand(operandTag), var, originalBitOffset) and - operandIsPropagated(instr, operandTag, propagatedBitOffset) and - bitOffset = Ints::add(originalBitOffset, propagatedBitOffset) - ) -} +private import AliasAnalysisInternal +import cpp +private import IR +private import semmle.code.cpp.ssa.internal.IntegerConstant as Ints + +private class IntValue = Ints::IntValue; + +/** + * Converts the bit count in `bits` to a byte count and a bit count in the form + * bytes:bits. + */ +bindingset[bits] +string bitsToBytesAndBits(int bits) { + result = (bits / 8).toString() + ":" + (bits % 8).toString() +} + +/** + * Gets a printable string for a bit offset with possibly unknown value. + */ +bindingset[bitOffset] +string getBitOffsetString(IntValue bitOffset) { + if Ints::hasValue(bitOffset) then + if bitOffset >= 0 then + result = "+" + bitsToBytesAndBits(bitOffset) + else + result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset)) + else + result = "+?" +} + +/** + * Gets the offset of field `field` in bits. + */ +private IntValue getFieldBitOffset(Field field) { + if (field instanceof BitField) then ( + result = Ints::add(Ints::mul(field.getByteOffset(), 8), + field.(BitField).getBitOffset()) + ) + else ( + result = Ints::mul(field.getByteOffset(), 8) + ) +} + +/** + * Holds if the operand `tag` of instruction `instr` is used in a way that does + * not result in any address held in that operand from escaping beyond the + * instruction. + */ +predicate operandIsConsumedWithoutEscaping(Instruction instr, OperandTag tag) { + exists(instr.getOperand(tag)) and + ( + // The source/destination address of a Load/Store does not escape (but the + // loaded/stored value could). + tag instanceof LoadStoreAddressOperand or + // Neither operand of a Compare escapes. + instr instanceof CompareInstruction or + // Neither operand of a PointerDiff escapes. + instr instanceof PointerDiffInstruction or + // Converting an address to a `bool` does not escape the address. + instr.(ConvertInstruction).getResultType() instanceof BoolType + ) +} + +/** + * If the result of instruction `instr` is an integer constant, returns the + * value of that constant. Otherwise, returns unknown. + */ +IntValue getConstantValue(Instruction instr) { + if instr instanceof IntegerConstantInstruction then + result = instr.(IntegerConstantInstruction).getValue().toInt() + else + result = Ints::unknown() +} + +/** + * Computes the offset, in bits, by which the result of `instr` differs from the + * pointer argument to `instr`, if that offset is a constant. Otherwise, returns + * unknown. + */ +IntValue getPointerBitOffset(PointerOffsetInstruction instr) { + exists(IntValue bitOffset | + ( + bitOffset = Ints::mul(Ints::mul(getConstantValue(instr.getRightOperand()), + instr.getElementSize()), 8) + ) and + ( + instr instanceof PointerAddInstruction and result = bitOffset or + instr instanceof PointerSubInstruction and result = Ints::neg(bitOffset) + ) + ) +} + +/** + * Holds if any address held in operand `tag` of instruction `instr` is + * propagated to the result of `instr`, offset by the number of bits in + * `bitOffset`. If the address is propagated, but the offset is not known to be + * a constant, then `bitOffset` is unknown. + */ +predicate operandIsPropagated(Instruction instr, OperandTag tag, + IntValue bitOffset) { + exists(instr.getOperand(tag)) and + ( + // Converting to a non-virtual base class adds the offset of the base class. + exists(ConvertToBaseInstruction convert | + convert = instr and + bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) + ) or + // Converting to a derived class subtracts the offset of the base class. + exists(ConvertToDerivedInstruction convert | + convert = instr and + bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8)) + ) or + // Converting to a virtual base class adds an unknown offset. + ( + instr instanceof ConvertToVirtualBaseInstruction and + bitOffset = Ints::unknown() + ) or + // Conversion to another pointer type propagates the source address. + exists(ConvertInstruction convert, Type resultType | + convert = instr and + resultType = convert.getResultType() and + ( + resultType instanceof PointerType or + resultType instanceof Class //REVIEW: Remove when all glvalues are pointers + ) and + bitOffset = 0 + ) or + // Adding an integer to or subtracting an integer from a pointer propagates + // the address with an offset. + bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or + // Computing a field address from a pointer propagates the address plus the + // offset of the field. + bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or + // A copy propagates the source value. + tag instanceof CopySourceOperand and bitOffset = 0 + ) +} + +/** + * Holds if any address held in operand number `tag` of instruction `instr` + * escapes outside the domain of the analysis. + */ +predicate operandEscapes(Instruction instr, OperandTag tag) { + exists(instr.getOperand(tag)) and + // Conservatively assume that the address escapes unless one of the following + // holds: + not ( + // The operand is used in a way that does not escape the instruction + operandIsConsumedWithoutEscaping(instr, tag) or + // The address is propagated to the result of the instruction, but that + // result does not itself escape. + operandIsPropagated(instr, tag, _) and not resultEscapes(instr) + ) +} + +/** + * Holds if any address held in the result of instruction `instr` escapes + * outside the domain of the analysis. + */ +predicate resultEscapes(Instruction instr) { + // The result escapes if it has at least one use that escapes. + exists(Instruction useInstr, OperandTag useOperandTag | + useInstr.getOperand(useOperandTag) = instr and + operandEscapes(useInstr, useOperandTag) + ) +} + +/** + * Holds if the address of the specified local variable or parameter escapes the + * domain of the analysis. + */ +private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) { + exists(FunctionIR funcIR | + funcIR = var.getFunctionIR() and + // The variable's address escapes if the result of any + // VariableAddressInstruction that computes the variable's address escapes. + exists(VariableAddressInstruction instr | + instr.getFunctionIR() = funcIR and + instr.getVariable() = var and + resultEscapes(instr) + ) + ) +} + +/** + * Holds if the address of the specified variable escapes the domain of the + * analysis. + */ +predicate variableAddressEscapes(IRVariable var) { + automaticVariableAddressEscapes(var.(IRAutomaticVariable)) or + // All variables with static storage duration have their address escape. + not var instanceof IRAutomaticVariable +} + +/** + * Holds if the result of instruction `instr` points within variable `var`, at + * bit offset `bitOffset` within the variable. If the result points within + * `var`, but at an unknown or non-constant offset, then `bitOffset` is unknown. + */ +predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) { + ( + // The address of a variable points to that variable, at offset 0. + instr.(VariableAddressInstruction).getVariable() = var and + bitOffset = 0 + ) or + exists(OperandTag operandTag, IntValue originalBitOffset, + IntValue propagatedBitOffset | + // If an operand is propagated, then the result points to the same variable, + // offset by the bit offset from the propagation. + resultPointsTo(instr.getOperand(operandTag), var, originalBitOffset) and + operandIsPropagated(instr, operandTag, propagatedBitOffset) and + bitOffset = Ints::add(originalBitOffset, propagatedBitOffset) + ) +} diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/AliasAnalysisInternal.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/AliasAnalysisInternal.qll index b7541fac50e..b6bb6445150 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/AliasAnalysisInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/AliasAnalysisInternal.qll @@ -1 +1 @@ -import semmle.code.cpp.ir.IR as IR +import semmle.code.cpp.ir.IR as IR diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/FunctionIR.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/FunctionIR.qll index 4568ae7ceb2..3e918fd3b49 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/FunctionIR.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/FunctionIR.qll @@ -1,97 +1,97 @@ -private import IRInternal -import Instruction -import cpp - -private newtype TFunctionIR = - MkFunctionIR(Function func) { - Construction::functionHasIR(func) - } - -/** - * Represents the IR for a function. - */ -class FunctionIR extends TFunctionIR { - Function func; - - FunctionIR() { - this = MkFunctionIR(func) - } - - final string toString() { - result = "IR: " + func.toString() - } - - /** - * Gets the function whose IR is represented. - */ - final Function getFunction() { - result = func - } - - /** - * Gets the location of the function. - */ - final Location getLocation() { - result = func.getLocation() - } - - /** - * Gets the entry point for this function. - */ - pragma[noinline] - final EnterFunctionInstruction getEnterFunctionInstruction() { - result.getFunctionIR() = this - } - - /** - * Gets the exit point for this function. - */ - pragma[noinline] - final ExitFunctionInstruction getExitFunctionInstruction() { - result.getFunctionIR() = this - } - - pragma[noinline] - final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() { - result.getFunctionIR() = this - } - - /** - * Gets the single return instruction for this function. - */ - pragma[noinline] - final ReturnInstruction getReturnInstruction() { - result.getFunctionIR() = this - } - - /** - * Gets the variable used to hold the return value of this function. If this - * function does not return a value, this predicate does not hold. - */ - pragma[noinline] - final IRReturnVariable getReturnVariable() { - result.getFunctionIR() = this - } - - /** - * Gets the block containing the entry point of this function. - */ - pragma[noinline] - final IRBlock getEntryBlock() { - result.getFirstInstruction() = getEnterFunctionInstruction() - } - - /** - * Gets all instructions in this function. - */ - final Instruction getAnInstruction() { - result.getFunctionIR() = this - } - - /** - * Gets all blocks in this function. - */ - final IRBlock getABlock() { - result.getFunctionIR() = this - } -} +private import IRInternal +import Instruction +import cpp + +private newtype TFunctionIR = + MkFunctionIR(Function func) { + Construction::functionHasIR(func) + } + +/** + * Represents the IR for a function. + */ +class FunctionIR extends TFunctionIR { + Function func; + + FunctionIR() { + this = MkFunctionIR(func) + } + + final string toString() { + result = "IR: " + func.toString() + } + + /** + * Gets the function whose IR is represented. + */ + final Function getFunction() { + result = func + } + + /** + * Gets the location of the function. + */ + final Location getLocation() { + result = func.getLocation() + } + + /** + * Gets the entry point for this function. + */ + pragma[noinline] + final EnterFunctionInstruction getEnterFunctionInstruction() { + result.getFunctionIR() = this + } + + /** + * Gets the exit point for this function. + */ + pragma[noinline] + final ExitFunctionInstruction getExitFunctionInstruction() { + result.getFunctionIR() = this + } + + pragma[noinline] + final UnmodeledDefinitionInstruction getUnmodeledDefinitionInstruction() { + result.getFunctionIR() = this + } + + /** + * Gets the single return instruction for this function. + */ + pragma[noinline] + final ReturnInstruction getReturnInstruction() { + result.getFunctionIR() = this + } + + /** + * Gets the variable used to hold the return value of this function. If this + * function does not return a value, this predicate does not hold. + */ + pragma[noinline] + final IRReturnVariable getReturnVariable() { + result.getFunctionIR() = this + } + + /** + * Gets the block containing the entry point of this function. + */ + pragma[noinline] + final IRBlock getEntryBlock() { + result.getFirstInstruction() = getEnterFunctionInstruction() + } + + /** + * Gets all instructions in this function. + */ + final Instruction getAnInstruction() { + result.getFunctionIR() = this + } + + /** + * Gets all blocks in this function. + */ + final IRBlock getABlock() { + result.getFunctionIR() = this + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/IRInternal.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/IRInternal.qll index 7517660a58f..940cc3df356 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/IRInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/IRInternal.qll @@ -1 +1 @@ -import SSAConstruction as Construction +import SSAConstruction as Construction diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/IRSanityImpl.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/IRSanityImpl.qll index 744b2870460..f4a1d12de89 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/IRSanityImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/IRSanityImpl.qll @@ -1,3 +1,3 @@ -private import IRImpl -import InstructionSanity - +private import IRImpl +import InstructionSanity + diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/IRVariable.qll index a903e227b26..2eae3dc7c17 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/IRVariable.qll @@ -1,202 +1,202 @@ -private import IRInternal -import FunctionIR -import cpp -import semmle.code.cpp.ir.TempVariableTag -private import semmle.code.cpp.ir.internal.TempVariableTag - -private newtype TIRVariable = - TIRAutomaticUserVariable(LocalScopeVariable var, FunctionIR funcIR) { - exists(Function func | - func = funcIR.getFunction() and - ( - var.getFunction() = func or - var.(Parameter).getCatchBlock().getEnclosingFunction() = func - ) - ) - } or - TIRStaticUserVariable(Variable var, FunctionIR funcIR) { - ( - var instanceof GlobalOrNamespaceVariable or - var instanceof MemberVariable and not var instanceof Field - ) and - exists(VariableAccess access | - access.getTarget() = var and - access.getEnclosingFunction() = funcIR.getFunction() - ) - } or - TIRTempVariable(FunctionIR funcIR, Locatable ast, TempVariableTag tag, - Type type) { - Construction::hasTempVariable(funcIR.getFunction(), ast, tag, type) - } - -IRUserVariable getIRUserVariable(Function func, Variable var) { - result.getVariable() = var and - result.getFunction() = func -} - -/** - * Represents a variable referenced by the IR for a function. The variable may - * be a user-declared variable (`IRUserVariable`) or a temporary variable - * generated by the AST-to-IR translation (`IRTempVariable`). - */ -abstract class IRVariable extends TIRVariable { - FunctionIR funcIR; - - abstract string toString(); - - /** - * Gets the type of the variable. - */ - abstract Type getType(); - - /** - * Gets the AST node that declared this variable, or that introduced this - * variable as part of the AST-to-IR translation. - */ - abstract Locatable getAST(); - - /** - * Gets an identifier string for the variable. This identifier is unique - * within the function. - */ - abstract string getUniqueId(); - - /** - * Gets the source location of this variable. - */ - final Location getLocation() { - result = getAST().getLocation() - } - - /** - * Gets the IR for the function that references this variable. - */ - final FunctionIR getFunctionIR() { - result = funcIR - } - - /** - * Gets the function that references this variable. - */ - final Function getFunction() { - result = funcIR.getFunction() - } -} - -/** - * Represents a user-declared variable referenced by the IR for a function. - */ -abstract class IRUserVariable extends IRVariable { - Variable var; - - override final string toString() { - result = var.toString() - } - - override final Type getType() { - result = var.getType().getUnspecifiedType() - } - - override final Locatable getAST() { - result = var - } - - override final string getUniqueId() { - result = var.toString() + " " + var.getLocation().toString() - } - - /** - * Gets the original user-declared variable. - */ - final Variable getVariable() { - result = var - } -} - -/** - * Represents a variable (user-declared or temporary) that is allocated on the - * stack. This includes all parameters, non-static local variables, and - * temporary variables. - */ -abstract class IRAutomaticVariable extends IRVariable { -} - -class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable, - TIRAutomaticUserVariable { - LocalScopeVariable localVar; - - IRAutomaticUserVariable() { - this = TIRAutomaticUserVariable(localVar, funcIR) and - var = localVar - } - - final LocalScopeVariable getLocalVariable() { - result = localVar - } -} - -class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable { - IRStaticUserVariable() { - this = TIRStaticUserVariable(var, funcIR) - } -} - -IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) { - result.getAST() = ast and - result.getTag() = tag -} - -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Locatable ast; - TempVariableTag tag; - Type type; - - IRTempVariable() { - this = TIRTempVariable(funcIR, ast, tag, type) - } - - override final Type getType() { - result = type - } - - override final Locatable getAST() { - result = ast - } - - override final string getUniqueId() { - result = "Temp: " + Construction::getTempVariableUniqueId(this) - } - - final TempVariableTag getTag() { - result = tag - } - - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { - result = "#temp" - } -} - -class IRReturnVariable extends IRTempVariable { - IRReturnVariable() { - tag = ReturnValueTempVar() - } - - override final string toString() { - result = "#return" - } -} - -class IRThrowVariable extends IRTempVariable { - IRThrowVariable() { - tag = ThrowTempVar() - } - - override string getBaseString() { - result = "#throw" - } -} +private import IRInternal +import FunctionIR +import cpp +import semmle.code.cpp.ir.TempVariableTag +private import semmle.code.cpp.ir.internal.TempVariableTag + +private newtype TIRVariable = + TIRAutomaticUserVariable(LocalScopeVariable var, FunctionIR funcIR) { + exists(Function func | + func = funcIR.getFunction() and + ( + var.getFunction() = func or + var.(Parameter).getCatchBlock().getEnclosingFunction() = func + ) + ) + } or + TIRStaticUserVariable(Variable var, FunctionIR funcIR) { + ( + var instanceof GlobalOrNamespaceVariable or + var instanceof MemberVariable and not var instanceof Field + ) and + exists(VariableAccess access | + access.getTarget() = var and + access.getEnclosingFunction() = funcIR.getFunction() + ) + } or + TIRTempVariable(FunctionIR funcIR, Locatable ast, TempVariableTag tag, + Type type) { + Construction::hasTempVariable(funcIR.getFunction(), ast, tag, type) + } + +IRUserVariable getIRUserVariable(Function func, Variable var) { + result.getVariable() = var and + result.getFunction() = func +} + +/** + * Represents a variable referenced by the IR for a function. The variable may + * be a user-declared variable (`IRUserVariable`) or a temporary variable + * generated by the AST-to-IR translation (`IRTempVariable`). + */ +abstract class IRVariable extends TIRVariable { + FunctionIR funcIR; + + abstract string toString(); + + /** + * Gets the type of the variable. + */ + abstract Type getType(); + + /** + * Gets the AST node that declared this variable, or that introduced this + * variable as part of the AST-to-IR translation. + */ + abstract Locatable getAST(); + + /** + * Gets an identifier string for the variable. This identifier is unique + * within the function. + */ + abstract string getUniqueId(); + + /** + * Gets the source location of this variable. + */ + final Location getLocation() { + result = getAST().getLocation() + } + + /** + * Gets the IR for the function that references this variable. + */ + final FunctionIR getFunctionIR() { + result = funcIR + } + + /** + * Gets the function that references this variable. + */ + final Function getFunction() { + result = funcIR.getFunction() + } +} + +/** + * Represents a user-declared variable referenced by the IR for a function. + */ +abstract class IRUserVariable extends IRVariable { + Variable var; + + override final string toString() { + result = var.toString() + } + + override final Type getType() { + result = var.getType().getUnspecifiedType() + } + + override final Locatable getAST() { + result = var + } + + override final string getUniqueId() { + result = var.toString() + " " + var.getLocation().toString() + } + + /** + * Gets the original user-declared variable. + */ + final Variable getVariable() { + result = var + } +} + +/** + * Represents a variable (user-declared or temporary) that is allocated on the + * stack. This includes all parameters, non-static local variables, and + * temporary variables. + */ +abstract class IRAutomaticVariable extends IRVariable { +} + +class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable, + TIRAutomaticUserVariable { + LocalScopeVariable localVar; + + IRAutomaticUserVariable() { + this = TIRAutomaticUserVariable(localVar, funcIR) and + var = localVar + } + + final LocalScopeVariable getLocalVariable() { + result = localVar + } +} + +class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable { + IRStaticUserVariable() { + this = TIRStaticUserVariable(var, funcIR) + } +} + +IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) { + result.getAST() = ast and + result.getTag() = tag +} + +class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { + Locatable ast; + TempVariableTag tag; + Type type; + + IRTempVariable() { + this = TIRTempVariable(funcIR, ast, tag, type) + } + + override final Type getType() { + result = type + } + + override final Locatable getAST() { + result = ast + } + + override final string getUniqueId() { + result = "Temp: " + Construction::getTempVariableUniqueId(this) + } + + final TempVariableTag getTag() { + result = tag + } + + override string toString() { + result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { + result = "#temp" + } +} + +class IRReturnVariable extends IRTempVariable { + IRReturnVariable() { + tag = ReturnValueTempVar() + } + + override final string toString() { + result = "#return" + } +} + +class IRThrowVariable extends IRTempVariable { + IRThrowVariable() { + tag = ThrowTempVar() + } + + override string getBaseString() { + result = "#throw" + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SSAConstruction.qll index b413532281e..e2760489439 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SSAConstruction.qll @@ -1,424 +1,424 @@ -import SSAConstructionInternal -import cpp -private import semmle.code.cpp.ir.internal.Opcode -import NewIR - -import Cached -cached private module Cached { - - private OldIR::OperandTag getOldOperandTag(OperandTag newTag) { - newTag instanceof LoadStoreAddressOperand and result instanceof OldIR::LoadStoreAddressOperand or - newTag instanceof CopySourceOperand and result instanceof OldIR::CopySourceOperand or - newTag instanceof UnaryOperand and result instanceof OldIR::UnaryOperand or - newTag instanceof LeftOperand and result instanceof OldIR::LeftOperand or - newTag instanceof RightOperand and result instanceof OldIR::RightOperand or - newTag instanceof ReturnValueOperand and result instanceof OldIR::ReturnValueOperand or - newTag instanceof ExceptionOperand and result instanceof OldIR::ExceptionOperand or - newTag instanceof ConditionOperand and result instanceof OldIR::ConditionOperand or - newTag instanceof UnmodeledUseOperand and result instanceof OldIR::UnmodeledUseOperand or - newTag instanceof CallTargetOperand and result instanceof OldIR::CallTargetOperand or - newTag instanceof ThisArgumentOperand and result instanceof OldIR::ThisArgumentOperand or - exists(PositionalArgumentOperand newArg | - newArg = newTag and - result.(OldIR::PositionalArgumentOperand).getArgIndex() = newArg.getArgIndex() - ) - } - - private IRBlock getNewBlock(OldIR::IRBlock oldBlock) { - result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction()) - } - - cached newtype TInstructionTag = - WrappedInstructionTag(OldIR::Instruction oldInstruction) or - PhiTag(Alias::VirtualVariable vvar, OldIR::IRBlock block) { - hasPhiNode(vvar, block) - } - - cached class InstructionTagType extends TInstructionTag { - cached final string toString() { - result = "Tag" - } - } - - cached predicate functionHasIR(Function func) { - exists(OldIR::FunctionIR funcIR | - funcIR.getFunction() = func - ) - } - - cached int getMaxCallArgIndex() { - result = max(int argIndex | - exists(OldIR::PositionalArgumentOperand oldOperand | - argIndex = oldOperand.getArgIndex() - ) - ) - } - - cached OldIR::Instruction getOldInstruction(Instruction instr) { - instr.getTag() = WrappedInstructionTag(result) - } - - private Instruction getNewInstruction(OldIR::Instruction instr) { - getOldInstruction(result) = instr - } - - private PhiInstruction getPhiInstruction(Function func, OldIR::IRBlock oldBlock, - Alias::VirtualVariable vvar) { - result.getFunction() = func and - result.getAST() = oldBlock.getFirstInstruction().getAST() and - result.getTag() = PhiTag(vvar, oldBlock) - } - - private IRVariable getNewIRVariable(OldIR::IRVariable var) { - result.getFunction() = var.getFunction() and - ( - exists(OldIR::IRUserVariable userVar, IRUserVariable newUserVar | - userVar = var and - newUserVar.getVariable() = userVar.getVariable() and - result = newUserVar - ) or - exists(OldIR::IRTempVariable tempVar, IRTempVariable newTempVar | - tempVar = var and - newTempVar.getAST() = tempVar.getAST() and - newTempVar.getTag() = tempVar.getTag() and - result = newTempVar - ) - ) - } - - cached newtype TInstruction = - MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast, - InstructionTag tag, Type resultType, boolean isGLValue) { - hasInstruction(funcIR.getFunction(), opcode, ast, tag, - resultType, isGLValue) - } - - private predicate hasInstruction(Function func, Opcode opcode, Locatable ast, - InstructionTag tag, Type resultType, boolean isGLValue) { - exists(OldIR::Instruction instr | - instr.getFunction() = func and - instr.getOpcode() = opcode and - instr.getAST() = ast and - WrappedInstructionTag(instr) = tag and - instr.getResultType() = resultType and - if instr.isGLValue() then - isGLValue = true - else - isGLValue = false - ) or - exists(OldIR::IRBlock block, Alias::VirtualVariable vvar | - hasPhiNode(vvar, block) and - block.getFunction() = func and - opcode instanceof Opcode::Phi and - ast = block.getFirstInstruction().getAST() and - tag = PhiTag(vvar, block) and - resultType = vvar.getType() and - isGLValue = false - ) - } - - cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, - Type type) { - exists(OldIR::IRTempVariable var | - var.getFunction() = func and - var.getAST() = ast and - var.getTag() = tag and - var.getType() = type - ) - } - - cached predicate hasModeledMemoryResult(Instruction instruction) { - exists(Alias::getResultMemoryAccess(getOldInstruction(instruction))) or - instruction instanceof PhiInstruction // Phis always have modeled results - } - - cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) { - exists(OldIR::Instruction oldUse, OldIR::OperandTag oldTag | - oldUse = getOldInstruction(instruction) and - oldTag = getOldOperandTag(tag) and - if oldUse.isMemoryOperand(oldTag) then ( - ( - if exists(Alias::getOperandMemoryAccess(oldUse, oldTag)) then ( - exists(OldIR::IRBlock useBlock, int useRank, Alias::VirtualVariable vvar, - OldIR::IRBlock defBlock, int defRank, int defIndex | - vvar = Alias::getOperandMemoryAccess(oldUse, oldTag).getVirtualVariable() and - hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and - hasUseAtRank(vvar, useBlock, useRank, oldUse) and - definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and - if defIndex >= 0 then - result = getNewInstruction(defBlock.getInstruction(defIndex)) - else - result = getPhiInstruction(instruction.getFunction(), defBlock, vvar) - ) - ) - else ( - result = instruction.getFunctionIR().getUnmodeledDefinitionInstruction() - ) - ) or - // Connect any definitions that are not being modeled in SSA to the - // `UnmodeledUse` instruction. - exists(OldIR::Instruction oldDefinition | - instruction instanceof UnmodeledUseInstruction and - tag instanceof UnmodeledUseOperand and - oldDefinition = oldUse.getOperand(oldTag) and - not exists(Alias::getResultMemoryAccess(oldDefinition)) and - result = getNewInstruction(oldDefinition) - ) - ) - else - result = getNewInstruction(oldUse.getOperand(oldTag)) - ) or - result = getPhiInstructionOperand(instruction.(PhiInstruction), tag.(PhiOperand)) - } - - cached Instruction getPhiInstructionOperand(PhiInstruction instr, PhiOperand tag) { - exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock, - OldIR::IRBlock defBlock, int defRank, int defIndex, OldIR::IRBlock predBlock | - hasPhiNode(vvar, phiBlock) and - predBlock = phiBlock.getAPredecessor() and - instr.getTag() = PhiTag(vvar, phiBlock) and - tag.getPredecessorBlock() = getNewBlock(predBlock) and - hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and - definitionReachesEndOfBlock(vvar, defBlock, defRank, predBlock) and - if defIndex >= 0 then - result = getNewInstruction(defBlock.getInstruction(defIndex)) - else - result = getPhiInstruction(instr.getFunction(), defBlock, vvar) - ) - } - - cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) { - exists(OldIR::IRBlock oldBlock | - instr.getTag() = PhiTag(_, oldBlock) and - result = getNewInstruction(oldBlock.getFirstInstruction()) - ) - } - - cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) { - result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind)) - } - - cached IRVariable getInstructionVariable(Instruction instruction) { - result = getNewIRVariable(getOldInstruction(instruction).(OldIR::VariableInstruction).getVariable()) - } - - cached Field getInstructionField(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField() - } - - cached Function getInstructionFunction(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol() - } - - cached string getInstructionConstantValue(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() - } - - cached StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() - } - - cached Type getInstructionExceptionType(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType() - } - - cached int getInstructionElementSize(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::PointerArithmeticInstruction).getElementSize() - } - - cached int getInstructionResultSize(Instruction instruction) { - // Only return a result for instructions that needed an explicit result size. - instruction.getResultType() instanceof UnknownType and - result = getOldInstruction(instruction).getResultSize() - } - - cached predicate getInstructionInheritance(Instruction instruction, Class baseClass, - Class derivedClass) { - exists(OldIR::InheritanceConversionInstruction oldInstr | - oldInstr = getOldInstruction(instruction) and - baseClass = oldInstr.getBaseClass() and - derivedClass = oldInstr.getDerivedClass() - ) - } - - private predicate ssa_variableUpdate(Alias::VirtualVariable vvar, - OldIR::Instruction instr, OldIR::IRBlock block, int index) { - block.getInstruction(index) = instr and - Alias::getResultMemoryAccess(instr).getVirtualVariable() = vvar - } - - private predicate hasDefinition(Alias::VirtualVariable vvar, OldIR::IRBlock block, int index) { - ( - hasPhiNode(vvar, block) and - index = -1 - ) or - exists(Alias::MemoryAccess access, OldIR::Instruction def | - access = Alias::getResultMemoryAccess(def) and - block.getInstruction(index) = def and - vvar = access.getVirtualVariable() - ) - } - - private predicate defUseRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, int rankIndex, int index) { - index = rank[rankIndex](int j | hasDefinition(vvar, block, j) or hasUse(vvar, _, block, j)) - } - - private predicate hasUse(Alias::VirtualVariable vvar, - OldIR::Instruction use, OldIR::IRBlock block, int index) { - exists(Alias::MemoryAccess access | - access = Alias::getOperandMemoryAccess(use, _) and - block.getInstruction(index) = use and - vvar = access.getVirtualVariable() - ) - } - - private predicate variableLiveOnEntryToBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) { - exists (int index | hasUse(vvar, _, block, index) | - not exists (int j | ssa_variableUpdate(vvar, _, block, j) | j < index) - ) or - (variableLiveOnExitFromBlock(vvar, block) and not ssa_variableUpdate(vvar, _, block, _)) - } - - pragma[noinline] - private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) { - variableLiveOnEntryToBlock(vvar, block.getASuccessor()) - } - - /** - * Gets the rank index of a hyphothetical use one instruction past the end of - * the block. This index can be used to determine if a definition reaches the - * end of the block, even if the definition is the last instruction in the - * block. - */ - private int exitRank(Alias::VirtualVariable vvar, OldIR::IRBlock block) { - result = max(int rankIndex | defUseRank(vvar, block, rankIndex, _)) + 1 - } - - private predicate hasDefinitionAtRank(Alias::VirtualVariable vvar, - OldIR::IRBlock block, int rankIndex, int instructionIndex) { - hasDefinition(vvar, block, instructionIndex) and - defUseRank(vvar, block, rankIndex, instructionIndex) - } - - private predicate hasUseAtRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, - int rankIndex, OldIR::Instruction use) { - exists(int index | - hasUse(vvar, use, block, index) and - defUseRank(vvar, block, rankIndex, index) - ) - } - - /** - * Holds if the definition of `vvar` at `(block, defRank)` reaches the rank - * index `reachesRank` in block `block`. - */ - private predicate definitionReachesRank(Alias::VirtualVariable vvar, - OldIR::IRBlock block, int defRank, int reachesRank) { - hasDefinitionAtRank(vvar, block, defRank, _) and - reachesRank <= exitRank(vvar, block) and // Without this, the predicate would be infinite. - ( - // The def always reaches the next use, even if there is also a def on the - // use instruction. - reachesRank = defRank + 1 or - ( - // If the def reached the previous rank, it also reaches the current rank, - // unless there was another def at the previous rank. - definitionReachesRank(vvar, block, defRank, reachesRank - 1) and - not hasDefinitionAtRank(vvar, block, reachesRank - 1, _) - ) - ) - } - - /** - * Holds if the definition of `vvar` at `(defBlock, defRank)` reaches the end of - * block `block`. - */ - private predicate definitionReachesEndOfBlock(Alias::VirtualVariable vvar, - OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock block) { - hasDefinitionAtRank(vvar, defBlock, defRank, _) and - ( - ( - // If we're looking at the def's own block, just see if it reaches the exit - // rank of the block. - block = defBlock and - variableLiveOnExitFromBlock(vvar, defBlock) and - definitionReachesRank(vvar, defBlock, defRank, exitRank(vvar, defBlock)) - ) or - exists(OldIR::IRBlock idom | - definitionReachesEndOfBlock(vvar, defBlock, defRank, idom) and - noDefinitionsSinceIDominator(vvar, idom, block) - ) - ) - } - - pragma[noinline] - private predicate noDefinitionsSinceIDominator(Alias::VirtualVariable vvar, - OldIR::IRBlock idom, OldIR::IRBlock block) { - idom.immediatelyDominates(block) and // It is sufficient to traverse the dominator graph, cf. discussion above. - variableLiveOnExitFromBlock(vvar, block) and - not hasDefinition(vvar, block, _) - } - - private predicate definitionReachesUseWithinBlock( - Alias::VirtualVariable vvar, OldIR::IRBlock defBlock, int defRank, - OldIR::IRBlock useBlock, int useRank) { - defBlock = useBlock and - hasDefinitionAtRank(vvar, defBlock, defRank, _) and - hasUseAtRank(vvar, useBlock, useRank, _) and - definitionReachesRank(vvar, defBlock, defRank, useRank) - } - - private predicate definitionReachesUse(Alias::VirtualVariable vvar, - OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock useBlock, int useRank) { - hasUseAtRank(vvar, useBlock, useRank, _) and - ( - definitionReachesUseWithinBlock(vvar, defBlock, defRank, useBlock, - useRank) or - ( - definitionReachesEndOfBlock(vvar, defBlock, defRank, - useBlock.getAPredecessor()) and - not definitionReachesUseWithinBlock(vvar, useBlock, _, useBlock, useRank) - ) - ) - } - - private predicate hasFrontierPhiNode(Alias::VirtualVariable vvar, - OldIR::IRBlock phiBlock) { - exists(OldIR::IRBlock defBlock | - phiBlock = defBlock.dominanceFrontier() and - hasDefinition(vvar, defBlock, _) and - /* We can also eliminate those nodes where the variable is not live on any incoming edge */ - variableLiveOnEntryToBlock(vvar, phiBlock) - ) - } - - private predicate hasPhiNode(Alias::VirtualVariable vvar, - OldIR::IRBlock phiBlock) { - hasFrontierPhiNode(vvar, phiBlock) - //or ssa_sanitized_custom_phi_node(vvar, block) - } -} - -import CachedForDebugging -cached private module CachedForDebugging { - cached string getTempVariableUniqueId(IRTempVariable var) { - result = getOldTempVariable(var).getUniqueId() - } - - cached string getInstructionUniqueId(Instruction instr) { - exists(OldIR::Instruction oldInstr | - oldInstr = getOldInstruction(instr) and - result = "NonSSA: " + oldInstr.getUniqueId() - ) or - exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock | - instr.getTag() = PhiTag(vvar, phiBlock) and - result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId() - ) - } - - private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) { - result.getFunction() = var.getFunction() and - result.getAST() = var.getAST() and - result.getTag() = var.getTag() - } -} +import SSAConstructionInternal +import cpp +private import semmle.code.cpp.ir.internal.Opcode +import NewIR + +import Cached +cached private module Cached { + + private OldIR::OperandTag getOldOperandTag(OperandTag newTag) { + newTag instanceof LoadStoreAddressOperand and result instanceof OldIR::LoadStoreAddressOperand or + newTag instanceof CopySourceOperand and result instanceof OldIR::CopySourceOperand or + newTag instanceof UnaryOperand and result instanceof OldIR::UnaryOperand or + newTag instanceof LeftOperand and result instanceof OldIR::LeftOperand or + newTag instanceof RightOperand and result instanceof OldIR::RightOperand or + newTag instanceof ReturnValueOperand and result instanceof OldIR::ReturnValueOperand or + newTag instanceof ExceptionOperand and result instanceof OldIR::ExceptionOperand or + newTag instanceof ConditionOperand and result instanceof OldIR::ConditionOperand or + newTag instanceof UnmodeledUseOperand and result instanceof OldIR::UnmodeledUseOperand or + newTag instanceof CallTargetOperand and result instanceof OldIR::CallTargetOperand or + newTag instanceof ThisArgumentOperand and result instanceof OldIR::ThisArgumentOperand or + exists(PositionalArgumentOperand newArg | + newArg = newTag and + result.(OldIR::PositionalArgumentOperand).getArgIndex() = newArg.getArgIndex() + ) + } + + private IRBlock getNewBlock(OldIR::IRBlock oldBlock) { + result.getFirstInstruction() = getNewInstruction(oldBlock.getFirstInstruction()) + } + + cached newtype TInstructionTag = + WrappedInstructionTag(OldIR::Instruction oldInstruction) or + PhiTag(Alias::VirtualVariable vvar, OldIR::IRBlock block) { + hasPhiNode(vvar, block) + } + + cached class InstructionTagType extends TInstructionTag { + cached final string toString() { + result = "Tag" + } + } + + cached predicate functionHasIR(Function func) { + exists(OldIR::FunctionIR funcIR | + funcIR.getFunction() = func + ) + } + + cached int getMaxCallArgIndex() { + result = max(int argIndex | + exists(OldIR::PositionalArgumentOperand oldOperand | + argIndex = oldOperand.getArgIndex() + ) + ) + } + + cached OldIR::Instruction getOldInstruction(Instruction instr) { + instr.getTag() = WrappedInstructionTag(result) + } + + private Instruction getNewInstruction(OldIR::Instruction instr) { + getOldInstruction(result) = instr + } + + private PhiInstruction getPhiInstruction(Function func, OldIR::IRBlock oldBlock, + Alias::VirtualVariable vvar) { + result.getFunction() = func and + result.getAST() = oldBlock.getFirstInstruction().getAST() and + result.getTag() = PhiTag(vvar, oldBlock) + } + + private IRVariable getNewIRVariable(OldIR::IRVariable var) { + result.getFunction() = var.getFunction() and + ( + exists(OldIR::IRUserVariable userVar, IRUserVariable newUserVar | + userVar = var and + newUserVar.getVariable() = userVar.getVariable() and + result = newUserVar + ) or + exists(OldIR::IRTempVariable tempVar, IRTempVariable newTempVar | + tempVar = var and + newTempVar.getAST() = tempVar.getAST() and + newTempVar.getTag() = tempVar.getTag() and + result = newTempVar + ) + ) + } + + cached newtype TInstruction = + MkInstruction(FunctionIR funcIR, Opcode opcode, Locatable ast, + InstructionTag tag, Type resultType, boolean isGLValue) { + hasInstruction(funcIR.getFunction(), opcode, ast, tag, + resultType, isGLValue) + } + + private predicate hasInstruction(Function func, Opcode opcode, Locatable ast, + InstructionTag tag, Type resultType, boolean isGLValue) { + exists(OldIR::Instruction instr | + instr.getFunction() = func and + instr.getOpcode() = opcode and + instr.getAST() = ast and + WrappedInstructionTag(instr) = tag and + instr.getResultType() = resultType and + if instr.isGLValue() then + isGLValue = true + else + isGLValue = false + ) or + exists(OldIR::IRBlock block, Alias::VirtualVariable vvar | + hasPhiNode(vvar, block) and + block.getFunction() = func and + opcode instanceof Opcode::Phi and + ast = block.getFirstInstruction().getAST() and + tag = PhiTag(vvar, block) and + resultType = vvar.getType() and + isGLValue = false + ) + } + + cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, + Type type) { + exists(OldIR::IRTempVariable var | + var.getFunction() = func and + var.getAST() = ast and + var.getTag() = tag and + var.getType() = type + ) + } + + cached predicate hasModeledMemoryResult(Instruction instruction) { + exists(Alias::getResultMemoryAccess(getOldInstruction(instruction))) or + instruction instanceof PhiInstruction // Phis always have modeled results + } + + cached Instruction getInstructionOperand(Instruction instruction, OperandTag tag) { + exists(OldIR::Instruction oldUse, OldIR::OperandTag oldTag | + oldUse = getOldInstruction(instruction) and + oldTag = getOldOperandTag(tag) and + if oldUse.isMemoryOperand(oldTag) then ( + ( + if exists(Alias::getOperandMemoryAccess(oldUse, oldTag)) then ( + exists(OldIR::IRBlock useBlock, int useRank, Alias::VirtualVariable vvar, + OldIR::IRBlock defBlock, int defRank, int defIndex | + vvar = Alias::getOperandMemoryAccess(oldUse, oldTag).getVirtualVariable() and + hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and + hasUseAtRank(vvar, useBlock, useRank, oldUse) and + definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and + if defIndex >= 0 then + result = getNewInstruction(defBlock.getInstruction(defIndex)) + else + result = getPhiInstruction(instruction.getFunction(), defBlock, vvar) + ) + ) + else ( + result = instruction.getFunctionIR().getUnmodeledDefinitionInstruction() + ) + ) or + // Connect any definitions that are not being modeled in SSA to the + // `UnmodeledUse` instruction. + exists(OldIR::Instruction oldDefinition | + instruction instanceof UnmodeledUseInstruction and + tag instanceof UnmodeledUseOperand and + oldDefinition = oldUse.getOperand(oldTag) and + not exists(Alias::getResultMemoryAccess(oldDefinition)) and + result = getNewInstruction(oldDefinition) + ) + ) + else + result = getNewInstruction(oldUse.getOperand(oldTag)) + ) or + result = getPhiInstructionOperand(instruction.(PhiInstruction), tag.(PhiOperand)) + } + + cached Instruction getPhiInstructionOperand(PhiInstruction instr, PhiOperand tag) { + exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock, + OldIR::IRBlock defBlock, int defRank, int defIndex, OldIR::IRBlock predBlock | + hasPhiNode(vvar, phiBlock) and + predBlock = phiBlock.getAPredecessor() and + instr.getTag() = PhiTag(vvar, phiBlock) and + tag.getPredecessorBlock() = getNewBlock(predBlock) and + hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and + definitionReachesEndOfBlock(vvar, defBlock, defRank, predBlock) and + if defIndex >= 0 then + result = getNewInstruction(defBlock.getInstruction(defIndex)) + else + result = getPhiInstruction(instr.getFunction(), defBlock, vvar) + ) + } + + cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) { + exists(OldIR::IRBlock oldBlock | + instr.getTag() = PhiTag(_, oldBlock) and + result = getNewInstruction(oldBlock.getFirstInstruction()) + ) + } + + cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) { + result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind)) + } + + cached IRVariable getInstructionVariable(Instruction instruction) { + result = getNewIRVariable(getOldInstruction(instruction).(OldIR::VariableInstruction).getVariable()) + } + + cached Field getInstructionField(Instruction instruction) { + result = getOldInstruction(instruction).(OldIR::FieldInstruction).getField() + } + + cached Function getInstructionFunction(Instruction instruction) { + result = getOldInstruction(instruction).(OldIR::FunctionInstruction).getFunctionSymbol() + } + + cached string getInstructionConstantValue(Instruction instruction) { + result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() + } + + cached StringLiteral getInstructionStringLiteral(Instruction instruction) { + result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() + } + + cached Type getInstructionExceptionType(Instruction instruction) { + result = getOldInstruction(instruction).(OldIR::CatchByTypeInstruction).getExceptionType() + } + + cached int getInstructionElementSize(Instruction instruction) { + result = getOldInstruction(instruction).(OldIR::PointerArithmeticInstruction).getElementSize() + } + + cached int getInstructionResultSize(Instruction instruction) { + // Only return a result for instructions that needed an explicit result size. + instruction.getResultType() instanceof UnknownType and + result = getOldInstruction(instruction).getResultSize() + } + + cached predicate getInstructionInheritance(Instruction instruction, Class baseClass, + Class derivedClass) { + exists(OldIR::InheritanceConversionInstruction oldInstr | + oldInstr = getOldInstruction(instruction) and + baseClass = oldInstr.getBaseClass() and + derivedClass = oldInstr.getDerivedClass() + ) + } + + private predicate ssa_variableUpdate(Alias::VirtualVariable vvar, + OldIR::Instruction instr, OldIR::IRBlock block, int index) { + block.getInstruction(index) = instr and + Alias::getResultMemoryAccess(instr).getVirtualVariable() = vvar + } + + private predicate hasDefinition(Alias::VirtualVariable vvar, OldIR::IRBlock block, int index) { + ( + hasPhiNode(vvar, block) and + index = -1 + ) or + exists(Alias::MemoryAccess access, OldIR::Instruction def | + access = Alias::getResultMemoryAccess(def) and + block.getInstruction(index) = def and + vvar = access.getVirtualVariable() + ) + } + + private predicate defUseRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, int rankIndex, int index) { + index = rank[rankIndex](int j | hasDefinition(vvar, block, j) or hasUse(vvar, _, block, j)) + } + + private predicate hasUse(Alias::VirtualVariable vvar, + OldIR::Instruction use, OldIR::IRBlock block, int index) { + exists(Alias::MemoryAccess access | + access = Alias::getOperandMemoryAccess(use, _) and + block.getInstruction(index) = use and + vvar = access.getVirtualVariable() + ) + } + + private predicate variableLiveOnEntryToBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) { + exists (int index | hasUse(vvar, _, block, index) | + not exists (int j | ssa_variableUpdate(vvar, _, block, j) | j < index) + ) or + (variableLiveOnExitFromBlock(vvar, block) and not ssa_variableUpdate(vvar, _, block, _)) + } + + pragma[noinline] + private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldIR::IRBlock block) { + variableLiveOnEntryToBlock(vvar, block.getASuccessor()) + } + + /** + * Gets the rank index of a hyphothetical use one instruction past the end of + * the block. This index can be used to determine if a definition reaches the + * end of the block, even if the definition is the last instruction in the + * block. + */ + private int exitRank(Alias::VirtualVariable vvar, OldIR::IRBlock block) { + result = max(int rankIndex | defUseRank(vvar, block, rankIndex, _)) + 1 + } + + private predicate hasDefinitionAtRank(Alias::VirtualVariable vvar, + OldIR::IRBlock block, int rankIndex, int instructionIndex) { + hasDefinition(vvar, block, instructionIndex) and + defUseRank(vvar, block, rankIndex, instructionIndex) + } + + private predicate hasUseAtRank(Alias::VirtualVariable vvar, OldIR::IRBlock block, + int rankIndex, OldIR::Instruction use) { + exists(int index | + hasUse(vvar, use, block, index) and + defUseRank(vvar, block, rankIndex, index) + ) + } + + /** + * Holds if the definition of `vvar` at `(block, defRank)` reaches the rank + * index `reachesRank` in block `block`. + */ + private predicate definitionReachesRank(Alias::VirtualVariable vvar, + OldIR::IRBlock block, int defRank, int reachesRank) { + hasDefinitionAtRank(vvar, block, defRank, _) and + reachesRank <= exitRank(vvar, block) and // Without this, the predicate would be infinite. + ( + // The def always reaches the next use, even if there is also a def on the + // use instruction. + reachesRank = defRank + 1 or + ( + // If the def reached the previous rank, it also reaches the current rank, + // unless there was another def at the previous rank. + definitionReachesRank(vvar, block, defRank, reachesRank - 1) and + not hasDefinitionAtRank(vvar, block, reachesRank - 1, _) + ) + ) + } + + /** + * Holds if the definition of `vvar` at `(defBlock, defRank)` reaches the end of + * block `block`. + */ + private predicate definitionReachesEndOfBlock(Alias::VirtualVariable vvar, + OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock block) { + hasDefinitionAtRank(vvar, defBlock, defRank, _) and + ( + ( + // If we're looking at the def's own block, just see if it reaches the exit + // rank of the block. + block = defBlock and + variableLiveOnExitFromBlock(vvar, defBlock) and + definitionReachesRank(vvar, defBlock, defRank, exitRank(vvar, defBlock)) + ) or + exists(OldIR::IRBlock idom | + definitionReachesEndOfBlock(vvar, defBlock, defRank, idom) and + noDefinitionsSinceIDominator(vvar, idom, block) + ) + ) + } + + pragma[noinline] + private predicate noDefinitionsSinceIDominator(Alias::VirtualVariable vvar, + OldIR::IRBlock idom, OldIR::IRBlock block) { + idom.immediatelyDominates(block) and // It is sufficient to traverse the dominator graph, cf. discussion above. + variableLiveOnExitFromBlock(vvar, block) and + not hasDefinition(vvar, block, _) + } + + private predicate definitionReachesUseWithinBlock( + Alias::VirtualVariable vvar, OldIR::IRBlock defBlock, int defRank, + OldIR::IRBlock useBlock, int useRank) { + defBlock = useBlock and + hasDefinitionAtRank(vvar, defBlock, defRank, _) and + hasUseAtRank(vvar, useBlock, useRank, _) and + definitionReachesRank(vvar, defBlock, defRank, useRank) + } + + private predicate definitionReachesUse(Alias::VirtualVariable vvar, + OldIR::IRBlock defBlock, int defRank, OldIR::IRBlock useBlock, int useRank) { + hasUseAtRank(vvar, useBlock, useRank, _) and + ( + definitionReachesUseWithinBlock(vvar, defBlock, defRank, useBlock, + useRank) or + ( + definitionReachesEndOfBlock(vvar, defBlock, defRank, + useBlock.getAPredecessor()) and + not definitionReachesUseWithinBlock(vvar, useBlock, _, useBlock, useRank) + ) + ) + } + + private predicate hasFrontierPhiNode(Alias::VirtualVariable vvar, + OldIR::IRBlock phiBlock) { + exists(OldIR::IRBlock defBlock | + phiBlock = defBlock.dominanceFrontier() and + hasDefinition(vvar, defBlock, _) and + /* We can also eliminate those nodes where the variable is not live on any incoming edge */ + variableLiveOnEntryToBlock(vvar, phiBlock) + ) + } + + private predicate hasPhiNode(Alias::VirtualVariable vvar, + OldIR::IRBlock phiBlock) { + hasFrontierPhiNode(vvar, phiBlock) + //or ssa_sanitized_custom_phi_node(vvar, block) + } +} + +import CachedForDebugging +cached private module CachedForDebugging { + cached string getTempVariableUniqueId(IRTempVariable var) { + result = getOldTempVariable(var).getUniqueId() + } + + cached string getInstructionUniqueId(Instruction instr) { + exists(OldIR::Instruction oldInstr | + oldInstr = getOldInstruction(instr) and + result = "NonSSA: " + oldInstr.getUniqueId() + ) or + exists(Alias::VirtualVariable vvar, OldIR::IRBlock phiBlock | + instr.getTag() = PhiTag(vvar, phiBlock) and + result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId() + ) + } + + private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) { + result.getFunction() = var.getFunction() and + result.getAST() = var.getAST() and + result.getTag() = var.getTag() + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SSAConstructionInternal.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SSAConstructionInternal.qll index 4bdc7fb0461..84ab4e1ae53 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SSAConstructionInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SSAConstructionInternal.qll @@ -1,3 +1,3 @@ -import semmle.code.cpp.ir.IR as OldIR -import semmle.code.cpp.ssa.SSAIR as NewIR -import SimpleSSA as Alias +import semmle.code.cpp.ir.IR as OldIR +import semmle.code.cpp.ssa.SSAIR as NewIR +import SimpleSSA as Alias diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SimpleSSA.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SimpleSSA.qll index 27287312f16..7f1fe39b4b2 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SimpleSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SimpleSSA.qll @@ -1,83 +1,83 @@ -import SimpleSSAInternal -import cpp -import Alias -import IR -import semmle.code.cpp.ssa.internal.Overlap - -private newtype TVirtualVariable = - MkVirtualVariable(IRVariable var) { - not variableAddressEscapes(var) - } - -private VirtualVariable getVirtualVariable(IRVariable var) { - result.getIRVariable() = var -} - -class VirtualVariable extends TVirtualVariable { - IRVariable var; - - VirtualVariable() { - this = MkVirtualVariable(var) - } - - final string toString() { - result = var.toString() - } - - final IRVariable getIRVariable() { - result = var - } - - // REVIEW: This should just be on MemoryAccess - final Type getType() { - result = var.getType() - } - - final string getUniqueId() { - result = var.getUniqueId() - } -} - -private newtype TMemoryAccess = - MkMemoryAccess(VirtualVariable vvar) - -private MemoryAccess getMemoryAccess(IRVariable var) { - result.getVirtualVariable() = getVirtualVariable(var) -} - -class MemoryAccess extends TMemoryAccess { - VirtualVariable vvar; - - MemoryAccess() { - this = MkMemoryAccess(vvar) - } - - string toString() { - result = vvar.toString() - } - - VirtualVariable getVirtualVariable() { - result = vvar - } -} - -Overlap getOverlap(MemoryAccess def, MemoryAccess use) { - def.getVirtualVariable() = use.getVirtualVariable() and - result instanceof MustExactlyOverlap -} - -MemoryAccess getResultMemoryAccess(Instruction instr) { - exists(IRVariable var | - instr.getResultMemoryAccess() instanceof IndirectMemoryAccess and - resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and - result = getMemoryAccess(var) - ) -} - -MemoryAccess getOperandMemoryAccess(Instruction instr, OperandTag tag) { - exists(IRVariable var | - instr.getOperandMemoryAccess(tag) instanceof IndirectMemoryAccess and - resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and - result = getMemoryAccess(var) - ) -} +import SimpleSSAInternal +import cpp +import Alias +import IR +import semmle.code.cpp.ssa.internal.Overlap + +private newtype TVirtualVariable = + MkVirtualVariable(IRVariable var) { + not variableAddressEscapes(var) + } + +private VirtualVariable getVirtualVariable(IRVariable var) { + result.getIRVariable() = var +} + +class VirtualVariable extends TVirtualVariable { + IRVariable var; + + VirtualVariable() { + this = MkVirtualVariable(var) + } + + final string toString() { + result = var.toString() + } + + final IRVariable getIRVariable() { + result = var + } + + // REVIEW: This should just be on MemoryAccess + final Type getType() { + result = var.getType() + } + + final string getUniqueId() { + result = var.getUniqueId() + } +} + +private newtype TMemoryAccess = + MkMemoryAccess(VirtualVariable vvar) + +private MemoryAccess getMemoryAccess(IRVariable var) { + result.getVirtualVariable() = getVirtualVariable(var) +} + +class MemoryAccess extends TMemoryAccess { + VirtualVariable vvar; + + MemoryAccess() { + this = MkMemoryAccess(vvar) + } + + string toString() { + result = vvar.toString() + } + + VirtualVariable getVirtualVariable() { + result = vvar + } +} + +Overlap getOverlap(MemoryAccess def, MemoryAccess use) { + def.getVirtualVariable() = use.getVirtualVariable() and + result instanceof MustExactlyOverlap +} + +MemoryAccess getResultMemoryAccess(Instruction instr) { + exists(IRVariable var | + instr.getResultMemoryAccess() instanceof IndirectMemoryAccess and + resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and + result = getMemoryAccess(var) + ) +} + +MemoryAccess getOperandMemoryAccess(Instruction instr, OperandTag tag) { + exists(IRVariable var | + instr.getOperandMemoryAccess(tag) instanceof IndirectMemoryAccess and + resultPointsTo(instr.getOperand(loadStoreAddressOperand()), var, 0) and + result = getMemoryAccess(var) + ) +} diff --git a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SimpleSSAInternal.qll b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SimpleSSAInternal.qll index c71f5acdf79..bb12750f197 100644 --- a/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SimpleSSAInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ssa/internal/ssa/SimpleSSAInternal.qll @@ -1,3 +1,3 @@ -import AliasAnalysis as Alias -import semmle.code.cpp.ir.IR as IR - +import AliasAnalysis as Alias +import semmle.code.cpp.ir.IR as IR + diff --git a/cpp/ql/test/library-tests/aliased_ssa/constants/constants.ql b/cpp/ql/test/library-tests/aliased_ssa/constants/constants.ql index eb11adc2286..519e0d3db0f 100644 --- a/cpp/ql/test/library-tests/aliased_ssa/constants/constants.ql +++ b/cpp/ql/test/library-tests/aliased_ssa/constants/constants.ql @@ -1,49 +1,49 @@ -import cpp -import semmle.code.cpp.ssa.internal.IntegerConstant as Ints - -bindingset[n] -string resultString(int n) { - if Ints::hasValue(n) then - result = n.toString() - else - result = "unknown" -} - -from string expr, int res -where - expr = "0 + 0" and res = Ints::add(0, 0) or - expr = "0 + INT_MAX" and res = Ints::add(0, Ints::maxValue()) or - expr = "0 + -INT_MAX" and res = Ints::add(0, Ints::minValue()) or - expr = "1 + INT_MAX" and res = Ints::add(1, Ints::maxValue()) or - expr = "1 + -INT_MAX" and res = Ints::add(1, Ints::minValue()) or - expr = "unknown + unknown" and res = Ints::add(Ints::unknown(), Ints::unknown()) or - expr = "5 + unknown" and res = Ints::add(5, Ints::unknown()) or - expr = "unknown + 5" and res = Ints::add(Ints::unknown(), 5) or - expr = "0 - INT_MAX" and res = Ints::sub(0, Ints::maxValue()) or - expr = "0 - -INT_MAX" and res = Ints::sub(0, Ints::minValue()) or - expr = "-1 - INT_MAX" and res = Ints::sub(-1, Ints::maxValue()) or - expr = "-1 - -INT_MAX" and res = Ints::sub(-1, Ints::minValue()) or - expr = "unknown - unknown" and res = Ints::sub(Ints::unknown(), Ints::unknown()) or - expr = "5 - unknown" and res = Ints::sub(5, Ints::unknown()) or - expr = "unknown - 5" and res = Ints::sub(Ints::unknown(), 5) or - expr = "0 * 0" and res = Ints::mul(0, 0) or - expr = "5 * 7" and res = Ints::mul(5, 7) or - expr = "0 * INT_MAX" and res = Ints::mul(0, Ints::maxValue()) or - expr = "2 * INT_MAX" and res = Ints::mul(2, Ints::maxValue()) or - expr = "-1 * -INT_MAX" and res = Ints::mul(-1, Ints::minValue()) or - expr = "INT_MAX * INT_MAX" and res = Ints::mul(Ints::maxValue(), Ints::maxValue()) or - expr = "0 * unknown" and res = Ints::mul(0, Ints::unknown()) or - expr = "35 / 7" and res = Ints::div(35, 7) or - expr = "35 / 8" and res = Ints::div(35, 8) or - expr = "35 / -7" and res = Ints::div(35, -7) or - expr = "35 / -8" and res = Ints::div(35, -8) or - expr = "-35 / 7" and res = Ints::div(-35, 7) or - expr = "-35 / 8" and res = Ints::div(-35, 8) or - expr = "-35 / -7" and res = Ints::div(-35, -7) or - expr = "-35 / -8" and res = Ints::div(-35, -8) or - expr = "0 / -INT_MAX" and res = Ints::div(0, Ints::minValue()) or - expr = "INT_MAX / 0" and res = Ints::div(Ints::maxValue(), 0) or - expr = "0 / unknown" and res = Ints::div(0, Ints::unknown()) or - expr = "unknown / 3" and res = Ints::div(Ints::unknown(), 3) or - expr = "unknown / unknown" and res = Ints::div(Ints::unknown(), Ints::unknown()) -select expr, resultString(res) +import cpp +import semmle.code.cpp.ssa.internal.IntegerConstant as Ints + +bindingset[n] +string resultString(int n) { + if Ints::hasValue(n) then + result = n.toString() + else + result = "unknown" +} + +from string expr, int res +where + expr = "0 + 0" and res = Ints::add(0, 0) or + expr = "0 + INT_MAX" and res = Ints::add(0, Ints::maxValue()) or + expr = "0 + -INT_MAX" and res = Ints::add(0, Ints::minValue()) or + expr = "1 + INT_MAX" and res = Ints::add(1, Ints::maxValue()) or + expr = "1 + -INT_MAX" and res = Ints::add(1, Ints::minValue()) or + expr = "unknown + unknown" and res = Ints::add(Ints::unknown(), Ints::unknown()) or + expr = "5 + unknown" and res = Ints::add(5, Ints::unknown()) or + expr = "unknown + 5" and res = Ints::add(Ints::unknown(), 5) or + expr = "0 - INT_MAX" and res = Ints::sub(0, Ints::maxValue()) or + expr = "0 - -INT_MAX" and res = Ints::sub(0, Ints::minValue()) or + expr = "-1 - INT_MAX" and res = Ints::sub(-1, Ints::maxValue()) or + expr = "-1 - -INT_MAX" and res = Ints::sub(-1, Ints::minValue()) or + expr = "unknown - unknown" and res = Ints::sub(Ints::unknown(), Ints::unknown()) or + expr = "5 - unknown" and res = Ints::sub(5, Ints::unknown()) or + expr = "unknown - 5" and res = Ints::sub(Ints::unknown(), 5) or + expr = "0 * 0" and res = Ints::mul(0, 0) or + expr = "5 * 7" and res = Ints::mul(5, 7) or + expr = "0 * INT_MAX" and res = Ints::mul(0, Ints::maxValue()) or + expr = "2 * INT_MAX" and res = Ints::mul(2, Ints::maxValue()) or + expr = "-1 * -INT_MAX" and res = Ints::mul(-1, Ints::minValue()) or + expr = "INT_MAX * INT_MAX" and res = Ints::mul(Ints::maxValue(), Ints::maxValue()) or + expr = "0 * unknown" and res = Ints::mul(0, Ints::unknown()) or + expr = "35 / 7" and res = Ints::div(35, 7) or + expr = "35 / 8" and res = Ints::div(35, 8) or + expr = "35 / -7" and res = Ints::div(35, -7) or + expr = "35 / -8" and res = Ints::div(35, -8) or + expr = "-35 / 7" and res = Ints::div(-35, 7) or + expr = "-35 / 8" and res = Ints::div(-35, 8) or + expr = "-35 / -7" and res = Ints::div(-35, -7) or + expr = "-35 / -8" and res = Ints::div(-35, -8) or + expr = "0 / -INT_MAX" and res = Ints::div(0, Ints::minValue()) or + expr = "INT_MAX / 0" and res = Ints::div(Ints::maxValue(), 0) or + expr = "0 / unknown" and res = Ints::div(0, Ints::unknown()) or + expr = "unknown / 3" and res = Ints::div(Ints::unknown(), 3) or + expr = "unknown / unknown" and res = Ints::div(Ints::unknown(), Ints::unknown()) +select expr, resultString(res) diff --git a/cpp/ql/test/library-tests/aliased_ssa/escape/escape.ql b/cpp/ql/test/library-tests/aliased_ssa/escape/escape.ql index 6dcedf72db7..7d9b8cb1e34 100644 --- a/cpp/ql/test/library-tests/aliased_ssa/escape/escape.ql +++ b/cpp/ql/test/library-tests/aliased_ssa/escape/escape.ql @@ -1,22 +1,22 @@ -import default -import semmle.code.cpp.ssa.internal.ssa.AliasAnalysis -import semmle.code.cpp.ir.IR - -predicate shouldEscape(IRAutomaticUserVariable var) { - exists(string name | - name = var.getVariable().getName() and - name.matches("no_%") and - not name.matches("no_ssa_%") - ) -} - -from IRAutomaticUserVariable var -where - exists(FunctionIR funcIR | - funcIR = var.getFunctionIR() and - ( - (shouldEscape(var) and variableAddressEscapes(var)) or - (not shouldEscape(var) and not variableAddressEscapes(var)) - ) - ) -select var +import default +import semmle.code.cpp.ssa.internal.ssa.AliasAnalysis +import semmle.code.cpp.ir.IR + +predicate shouldEscape(IRAutomaticUserVariable var) { + exists(string name | + name = var.getVariable().getName() and + name.matches("no_%") and + not name.matches("no_ssa_%") + ) +} + +from IRAutomaticUserVariable var +where + exists(FunctionIR funcIR | + funcIR = var.getFunctionIR() and + ( + (shouldEscape(var) and variableAddressEscapes(var)) or + (not shouldEscape(var) and not variableAddressEscapes(var)) + ) + ) +select var diff --git a/cpp/ql/test/library-tests/aliased_ssa/escape/points_to.ql b/cpp/ql/test/library-tests/aliased_ssa/escape/points_to.ql index 0b2361e8e35..7858323571b 100644 --- a/cpp/ql/test/library-tests/aliased_ssa/escape/points_to.ql +++ b/cpp/ql/test/library-tests/aliased_ssa/escape/points_to.ql @@ -1,11 +1,11 @@ -import default -import semmle.code.cpp.ssa.internal.ssa.AliasAnalysis -import semmle.code.cpp.ir.IR - -from Instruction instr, string pointsTo -where - exists(IRVariable var, int bitOffset | - resultPointsTo(instr, var, bitOffset) and - pointsTo = var.toString() + getBitOffsetString(bitOffset) - ) -select instr.getLocation().toString(), instr.getOperationString(), pointsTo +import default +import semmle.code.cpp.ssa.internal.ssa.AliasAnalysis +import semmle.code.cpp.ir.IR + +from Instruction instr, string pointsTo +where + exists(IRVariable var, int bitOffset | + resultPointsTo(instr, var, bitOffset) and + pointsTo = var.toString() + getBitOffsetString(bitOffset) + ) +select instr.getLocation().toString(), instr.getOperationString(), pointsTo diff --git a/cpp/ql/test/library-tests/aliased_ssa/escape/ssa_escape.ql b/cpp/ql/test/library-tests/aliased_ssa/escape/ssa_escape.ql index f38fab30740..687f1f4a208 100644 --- a/cpp/ql/test/library-tests/aliased_ssa/escape/ssa_escape.ql +++ b/cpp/ql/test/library-tests/aliased_ssa/escape/ssa_escape.ql @@ -1,21 +1,21 @@ -import default -import semmle.code.cpp.ssa.internal.aliased_ssa.AliasAnalysis -import semmle.code.cpp.ssa.SSAIR - -predicate shouldEscape(IRAutomaticUserVariable var) { - exists(string name | - name = var.getVariable().getName() and - name.matches("no_%") - ) -} - -from IRAutomaticUserVariable var -where - exists(FunctionIR funcIR | - funcIR = var.getFunctionIR() and - ( - (shouldEscape(var) and variableAddressEscapes(var)) or - (not shouldEscape(var) and not variableAddressEscapes(var)) - ) - ) -select var +import default +import semmle.code.cpp.ssa.internal.aliased_ssa.AliasAnalysis +import semmle.code.cpp.ssa.SSAIR + +predicate shouldEscape(IRAutomaticUserVariable var) { + exists(string name | + name = var.getVariable().getName() and + name.matches("no_%") + ) +} + +from IRAutomaticUserVariable var +where + exists(FunctionIR funcIR | + funcIR = var.getFunctionIR() and + ( + (shouldEscape(var) and variableAddressEscapes(var)) or + (not shouldEscape(var) and not variableAddressEscapes(var)) + ) + ) +select var diff --git a/cpp/ql/test/library-tests/allocators/allocators.ql b/cpp/ql/test/library-tests/allocators/allocators.ql index 66c8d20b3f4..4c0cceb23be 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.ql +++ b/cpp/ql/test/library-tests/allocators/allocators.ql @@ -1,89 +1,89 @@ -import default - -query predicate newExprs(NewExpr expr, string type, string sig, int size, int alignment, string form) { - exists(Function allocator, Type allocatedType | - expr.getAllocator() = allocator and - sig = allocator.getFullSignature() and - allocatedType = expr.getAllocatedType() and - type = allocatedType.toString() and - size = allocatedType.getSize() and - alignment = allocatedType.getAlignment() and - if expr.hasAlignedAllocation() then form = "aligned" else form = "" - ) -} - -query predicate newArrayExprs(NewArrayExpr expr, string type, string sig, int size, int alignment, string form) { - exists(Function allocator, Type elementType | - expr.getAllocator() = allocator and - sig = allocator.getFullSignature() and - elementType = expr.getAllocatedElementType() and - type = elementType.toString() and - size = elementType.getSize() and - alignment = elementType.getAlignment() and - if expr.hasAlignedAllocation() then form = "aligned" else form = "" - ) -} - -query predicate newExprDeallocators(NewExpr expr, string type, string sig, int size, int alignment, string form) { - exists(Function deallocator, Type allocatedType | - expr.getDeallocator() = deallocator and - sig = deallocator.getFullSignature() and - allocatedType = expr.getAllocatedType() and - type = allocatedType.toString() and - size = allocatedType.getSize() and - alignment = allocatedType.getAlignment() and - exists(string sized, string aligned | - (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and - (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and - form = sized + " " + aligned - ) - ) -} - -query predicate newArrayExprDeallocators(NewArrayExpr expr, string type, string sig, int size, int alignment, string form) { - exists(Function deallocator, Type elementType | - expr.getDeallocator() = deallocator and - sig = deallocator.getFullSignature() and - elementType = expr.getAllocatedElementType() and - type = elementType.toString() and - size = elementType.getSize() and - alignment = elementType.getAlignment() and - exists(string sized, string aligned | - (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and - (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and - form = sized + " " + aligned - ) - ) -} - -query predicate deleteExprs(DeleteExpr expr, string type, string sig, int size, int alignment, string form) { - exists(Function deallocator, Type deletedType | - expr.getDeallocator() = deallocator and - sig = deallocator.getFullSignature() and - deletedType = expr.getDeletedObjectType() and - type = deletedType.toString() and - size = deletedType.getSize() and - alignment = deletedType.getAlignment() and - exists(string sized, string aligned | - (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and - (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and - form = sized + " " + aligned - ) - ) -} - -query predicate deleteArrayExprs(DeleteArrayExpr expr, string type, string sig, int size, int alignment, string form) { - exists(Function deallocator, Type elementType | - expr.getDeallocator() = deallocator and - sig = deallocator.getFullSignature() and - elementType = expr.getDeletedElementType() and - type = elementType.toString() and - size = elementType.getSize() and - alignment = elementType.getAlignment() and - exists(string sized, string aligned | - (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and - (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and - form = sized + " " + aligned - ) - ) -} +import default + +query predicate newExprs(NewExpr expr, string type, string sig, int size, int alignment, string form) { + exists(Function allocator, Type allocatedType | + expr.getAllocator() = allocator and + sig = allocator.getFullSignature() and + allocatedType = expr.getAllocatedType() and + type = allocatedType.toString() and + size = allocatedType.getSize() and + alignment = allocatedType.getAlignment() and + if expr.hasAlignedAllocation() then form = "aligned" else form = "" + ) +} + +query predicate newArrayExprs(NewArrayExpr expr, string type, string sig, int size, int alignment, string form) { + exists(Function allocator, Type elementType | + expr.getAllocator() = allocator and + sig = allocator.getFullSignature() and + elementType = expr.getAllocatedElementType() and + type = elementType.toString() and + size = elementType.getSize() and + alignment = elementType.getAlignment() and + if expr.hasAlignedAllocation() then form = "aligned" else form = "" + ) +} + +query predicate newExprDeallocators(NewExpr expr, string type, string sig, int size, int alignment, string form) { + exists(Function deallocator, Type allocatedType | + expr.getDeallocator() = deallocator and + sig = deallocator.getFullSignature() and + allocatedType = expr.getAllocatedType() and + type = allocatedType.toString() and + size = allocatedType.getSize() and + alignment = allocatedType.getAlignment() and + exists(string sized, string aligned | + (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and + (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and + form = sized + " " + aligned + ) + ) +} + +query predicate newArrayExprDeallocators(NewArrayExpr expr, string type, string sig, int size, int alignment, string form) { + exists(Function deallocator, Type elementType | + expr.getDeallocator() = deallocator and + sig = deallocator.getFullSignature() and + elementType = expr.getAllocatedElementType() and + type = elementType.toString() and + size = elementType.getSize() and + alignment = elementType.getAlignment() and + exists(string sized, string aligned | + (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and + (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and + form = sized + " " + aligned + ) + ) +} + +query predicate deleteExprs(DeleteExpr expr, string type, string sig, int size, int alignment, string form) { + exists(Function deallocator, Type deletedType | + expr.getDeallocator() = deallocator and + sig = deallocator.getFullSignature() and + deletedType = expr.getDeletedObjectType() and + type = deletedType.toString() and + size = deletedType.getSize() and + alignment = deletedType.getAlignment() and + exists(string sized, string aligned | + (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and + (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and + form = sized + " " + aligned + ) + ) +} + +query predicate deleteArrayExprs(DeleteArrayExpr expr, string type, string sig, int size, int alignment, string form) { + exists(Function deallocator, Type elementType | + expr.getDeallocator() = deallocator and + sig = deallocator.getFullSignature() and + elementType = expr.getDeletedElementType() and + type = elementType.toString() and + size = elementType.getSize() and + alignment = elementType.getAlignment() and + exists(string sized, string aligned | + (if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and + (if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and + form = sized + " " + aligned + ) + ) +} diff --git a/cpp/ql/test/library-tests/controlflow/guards/Guards.ql b/cpp/ql/test/library-tests/controlflow/guards/Guards.ql index 822bf0d1770..b205a16034b 100644 --- a/cpp/ql/test/library-tests/controlflow/guards/Guards.ql +++ b/cpp/ql/test/library-tests/controlflow/guards/Guards.ql @@ -1,5 +1,5 @@ -import cpp -import semmle.code.cpp.controlflow.Guards - -from GuardCondition guard +import cpp +import semmle.code.cpp.controlflow.Guards + +from GuardCondition guard select guard \ No newline at end of file diff --git a/cpp/ql/test/library-tests/conversions/conversions.ql b/cpp/ql/test/library-tests/conversions/conversions.ql index 78af6ed17f0..2216f6f0b1c 100644 --- a/cpp/ql/test/library-tests/conversions/conversions.ql +++ b/cpp/ql/test/library-tests/conversions/conversions.ql @@ -1,15 +1,15 @@ -import default - -string getValueCategoryString(Expr expr) { - if expr.isLValueCategory() then - result = "lval" - else if expr.isXValueCategory() then - result = "xval" - else if expr.hasLValueToRValueConversion() then - result = "prval(load)" - else - result = "prval" -} - -from Cast cast -select cast, cast.getSemanticConversionString(), getValueCategoryString(cast), cast.getType().toString(), cast.getExpr().getType().toString() +import default + +string getValueCategoryString(Expr expr) { + if expr.isLValueCategory() then + result = "lval" + else if expr.isXValueCategory() then + result = "xval" + else if expr.hasLValueToRValueConversion() then + result = "prval(load)" + else + result = "prval" +} + +from Cast cast +select cast, cast.getSemanticConversionString(), getValueCategoryString(cast), cast.getType().toString(), cast.getExpr().getType().toString() diff --git a/cpp/ql/test/library-tests/conversions/sanity.qlref b/cpp/ql/test/library-tests/conversions/sanity.qlref index fb9c931e224..50d6aaf2188 100644 --- a/cpp/ql/test/library-tests/conversions/sanity.qlref +++ b/cpp/ql/test/library-tests/conversions/sanity.qlref @@ -1 +1 @@ -semmle/code/cpp/ASTSanity.ql +semmle/code/cpp/ASTSanity.ql diff --git a/cpp/ql/test/library-tests/depends_addressable/DependsAddressable1.ql b/cpp/ql/test/library-tests/depends_addressable/DependsAddressable1.ql index 81d75165c15..b56a564ce95 100644 --- a/cpp/ql/test/library-tests/depends_addressable/DependsAddressable1.ql +++ b/cpp/ql/test/library-tests/depends_addressable/DependsAddressable1.ql @@ -1,5 +1,5 @@ -import cpp - -from Expr e, Variable v -where varbind(unresolveElement(e), unresolveElement(v)) -select e, v +import cpp + +from Expr e, Variable v +where varbind(unresolveElement(e), unresolveElement(v)) +select e, v diff --git a/cpp/ql/test/library-tests/depends_initializers/InitializerAccesses.ql b/cpp/ql/test/library-tests/depends_initializers/InitializerAccesses.ql index e085d37c7a2..4548c28525d 100644 --- a/cpp/ql/test/library-tests/depends_initializers/InitializerAccesses.ql +++ b/cpp/ql/test/library-tests/depends_initializers/InitializerAccesses.ql @@ -1,7 +1,7 @@ /** * @name InitializerAccesses */ -import cpp +import cpp from Initializer i, VariableAccess va where i.getExpr().getAChild*() = va diff --git a/cpp/ql/test/library-tests/derived_types/DerivedTypesBaseType.ql b/cpp/ql/test/library-tests/derived_types/DerivedTypesBaseType.ql index bcc7ae9fdc6..53db8f9f22c 100644 --- a/cpp/ql/test/library-tests/derived_types/DerivedTypesBaseType.ql +++ b/cpp/ql/test/library-tests/derived_types/DerivedTypesBaseType.ql @@ -1,6 +1,6 @@ -import cpp - -//this query should find the baseType of CC* to be CC, not C. -from DerivedType t, Type baseType -where t.getBaseType() = baseType -select t, baseType +import cpp + +//this query should find the baseType of CC* to be CC, not C. +from DerivedType t, Type baseType +where t.getBaseType() = baseType +select t, baseType diff --git a/cpp/ql/test/library-tests/exprs/comparison_operation/comparison_operation.ql b/cpp/ql/test/library-tests/exprs/comparison_operation/comparison_operation.ql index 0039f8da903..0721c873275 100644 --- a/cpp/ql/test/library-tests/exprs/comparison_operation/comparison_operation.ql +++ b/cpp/ql/test/library-tests/exprs/comparison_operation/comparison_operation.ql @@ -1,26 +1,26 @@ -import cpp - -from ComparisonOperation co, string s -where - ( - co instanceof EqualityOperation and s = "EqualityOperation" - ) or ( - co instanceof EQExpr and s = "EQExpr" - ) or ( - co instanceof NEExpr and s = "NEExpr" - ) or ( - co instanceof RelationalOperation and s = "RelationalOperation" - ) or ( - s = "getGreaterOperand() = " + co.(RelationalOperation).getGreaterOperand().toString() - ) or ( - s = "getLesserOperand() = " + co.(RelationalOperation).getLesserOperand().toString() - ) or ( - co instanceof GTExpr and s = "GTExpr" - ) or ( - co instanceof LTExpr and s = "LTExpr" - ) or ( - co instanceof GEExpr and s = "GEExpr" - ) or ( - co instanceof LEExpr and s = "LEExpr" - ) -select co, s +import cpp + +from ComparisonOperation co, string s +where + ( + co instanceof EqualityOperation and s = "EqualityOperation" + ) or ( + co instanceof EQExpr and s = "EQExpr" + ) or ( + co instanceof NEExpr and s = "NEExpr" + ) or ( + co instanceof RelationalOperation and s = "RelationalOperation" + ) or ( + s = "getGreaterOperand() = " + co.(RelationalOperation).getGreaterOperand().toString() + ) or ( + s = "getLesserOperand() = " + co.(RelationalOperation).getLesserOperand().toString() + ) or ( + co instanceof GTExpr and s = "GTExpr" + ) or ( + co instanceof LTExpr and s = "LTExpr" + ) or ( + co instanceof GEExpr and s = "GEExpr" + ) or ( + co instanceof LEExpr and s = "LEExpr" + ) +select co, s diff --git a/cpp/ql/test/library-tests/exprs/unary_operation/unary_operation.ql b/cpp/ql/test/library-tests/exprs/unary_operation/unary_operation.ql index 5ffeebd7155..6d39dae47bd 100644 --- a/cpp/ql/test/library-tests/exprs/unary_operation/unary_operation.ql +++ b/cpp/ql/test/library-tests/exprs/unary_operation/unary_operation.ql @@ -1,37 +1,37 @@ -import cpp - -predicate describe(UnaryOperation uo, string s) -{ - ( - uo instanceof UnaryArithmeticOperation and s = "UnaryArithmeticOperation" - ) or ( - uo instanceof UnaryMinusExpr and s = "UnaryMinusExpr" - ) or ( - uo instanceof UnaryPlusExpr and s = "UnaryPlusExpr" - ) or ( - uo instanceof ConjugationExpr and s = "ConjugationExpr" - ) or ( - uo instanceof CrementOperation and s = "CrementOperation" - ) or ( - uo instanceof IncrementOperation and s = "IncrementOperation" - ) or ( - uo instanceof DecrementOperation and s = "DecrementOperation" - ) or ( - uo instanceof PrefixCrementOperation and s = "PrefixCrementOperation" - ) or ( - uo instanceof PostfixCrementOperation and s = "PostfixCrementOperation" - ) or ( - uo instanceof AddressOfExpr and s = "AddressOfExpr" - ) or ( - s = "getAddressable() = " + uo.(AddressOfExpr).getAddressable().toString() - ) or ( - uo instanceof PointerDereferenceExpr and s = "PointerDereferenceExpr" - ) or ( - uo instanceof UnaryLogicalOperation and s = "UnaryLogicalOperation" - ) or ( - uo instanceof NotExpr and s = "NotExpr" - ) -} - -from UnaryOperation uo -select uo, uo.getOperator(), concat(string s | describe(uo, s) | s, ", ") +import cpp + +predicate describe(UnaryOperation uo, string s) +{ + ( + uo instanceof UnaryArithmeticOperation and s = "UnaryArithmeticOperation" + ) or ( + uo instanceof UnaryMinusExpr and s = "UnaryMinusExpr" + ) or ( + uo instanceof UnaryPlusExpr and s = "UnaryPlusExpr" + ) or ( + uo instanceof ConjugationExpr and s = "ConjugationExpr" + ) or ( + uo instanceof CrementOperation and s = "CrementOperation" + ) or ( + uo instanceof IncrementOperation and s = "IncrementOperation" + ) or ( + uo instanceof DecrementOperation and s = "DecrementOperation" + ) or ( + uo instanceof PrefixCrementOperation and s = "PrefixCrementOperation" + ) or ( + uo instanceof PostfixCrementOperation and s = "PostfixCrementOperation" + ) or ( + uo instanceof AddressOfExpr and s = "AddressOfExpr" + ) or ( + s = "getAddressable() = " + uo.(AddressOfExpr).getAddressable().toString() + ) or ( + uo instanceof PointerDereferenceExpr and s = "PointerDereferenceExpr" + ) or ( + uo instanceof UnaryLogicalOperation and s = "UnaryLogicalOperation" + ) or ( + uo instanceof NotExpr and s = "NotExpr" + ) +} + +from UnaryOperation uo +select uo, uo.getOperator(), concat(string s | describe(uo, s) | s, ", ") diff --git a/cpp/ql/test/library-tests/exprs/unevaluated/unevaluated.ql b/cpp/ql/test/library-tests/exprs/unevaluated/unevaluated.ql index 914707401a1..1a64f310097 100644 --- a/cpp/ql/test/library-tests/exprs/unevaluated/unevaluated.ql +++ b/cpp/ql/test/library-tests/exprs/unevaluated/unevaluated.ql @@ -1,5 +1,5 @@ -import cpp - -from Expr e -where e.isUnevaluated() -select e +import cpp + +from Expr e +where e.isUnevaluated() +select e diff --git a/cpp/ql/test/library-tests/exprs/value_categories/loads.ql b/cpp/ql/test/library-tests/exprs/value_categories/loads.ql index dcc4f4b4c2e..78d617f6337 100644 --- a/cpp/ql/test/library-tests/exprs/value_categories/loads.ql +++ b/cpp/ql/test/library-tests/exprs/value_categories/loads.ql @@ -1,5 +1,5 @@ -import cpp - -from Expr e -where e.hasLValueToRValueConversion() -select e +import cpp + +from Expr e +where e.hasLValueToRValueConversion() +select e diff --git a/cpp/ql/test/library-tests/exprs/value_categories/value_categories.ql b/cpp/ql/test/library-tests/exprs/value_categories/value_categories.ql index 12a1048263a..8bc52c55022 100644 --- a/cpp/ql/test/library-tests/exprs/value_categories/value_categories.ql +++ b/cpp/ql/test/library-tests/exprs/value_categories/value_categories.ql @@ -1,7 +1,7 @@ -import cpp - -from Expr e, string valcat -where - e.isLValueCategory() and valcat = "lvalue" or - e.isXValueCategory() and valcat = "xvalue" -select e, e.getType().toString(), valcat +import cpp + +from Expr e, string valcat +where + e.isLValueCategory() and valcat = "lvalue" or + e.isXValueCategory() and valcat = "xvalue" +select e, e.getType().toString(), valcat diff --git a/cpp/ql/test/library-tests/fields/fields/EnumConst.ql b/cpp/ql/test/library-tests/fields/fields/EnumConst.ql index 9d4e56c0093..5a7bf1686c0 100644 --- a/cpp/ql/test/library-tests/fields/fields/EnumConst.ql +++ b/cpp/ql/test/library-tests/fields/fields/EnumConst.ql @@ -1,11 +1,11 @@ -/** - * @name EnumConst - * @kind table - */ -import cpp - -from Enum e, Declaration c, string reason -where (c.(EnumConstant).getDeclaringEnum() = e and reason = "getDeclaringEnum()") or - (c.(EnumConstant).getType() = e and reason = "getType()") or - (c.(Field).getDeclaringType() = e and reason = "getDeclaringType()") -select e, c, reason +/** + * @name EnumConst + * @kind table + */ +import cpp + +from Enum e, Declaration c, string reason +where (c.(EnumConstant).getDeclaringEnum() = e and reason = "getDeclaringEnum()") or + (c.(EnumConstant).getType() = e and reason = "getType()") or + (c.(Field).getDeclaringType() = e and reason = "getDeclaringType()") +select e, c, reason diff --git a/cpp/ql/test/library-tests/fields/fields/Fields.ql b/cpp/ql/test/library-tests/fields/fields/Fields.ql index c64409d55fb..3908ee876ad 100644 --- a/cpp/ql/test/library-tests/fields/fields/Fields.ql +++ b/cpp/ql/test/library-tests/fields/fields/Fields.ql @@ -1,40 +1,40 @@ -/** - * @name Fields - * @kind table - */ -import cpp - -predicate nameCheck(Declaration d) { - count(d.toString()) = 1 and - count(string s | d.hasName(s)) = 1 and - d.hasName(d.toString()) -} - -string accessType(Field f) { - (f.isPublic() and result = "public") or - (f.isProtected() and result = "protected") or - (f.isPrivate() and result = "private") -} - -string fieldType(Field f) { - result = f.getType().getAQlClass() and - ( - result.matches("%Type") or - result = "Enum" - ) -} - -string pointedType(Field f) { - if f.getType() instanceof PointerType then ( - result = f.getType().(PointerType).getBaseType().toString() - ) else ( - result = "" - ) -} - -from Class c, Field f -where f.getDeclaringType() = c and - c.getAField() = f and - nameCheck(c) and - nameCheck(f) -select c, f, accessType(f), fieldType(f), pointedType(f) +/** + * @name Fields + * @kind table + */ +import cpp + +predicate nameCheck(Declaration d) { + count(d.toString()) = 1 and + count(string s | d.hasName(s)) = 1 and + d.hasName(d.toString()) +} + +string accessType(Field f) { + (f.isPublic() and result = "public") or + (f.isProtected() and result = "protected") or + (f.isPrivate() and result = "private") +} + +string fieldType(Field f) { + result = f.getType().getAQlClass() and + ( + result.matches("%Type") or + result = "Enum" + ) +} + +string pointedType(Field f) { + if f.getType() instanceof PointerType then ( + result = f.getType().(PointerType).getBaseType().toString() + ) else ( + result = "" + ) +} + +from Class c, Field f +where f.getDeclaringType() = c and + c.getAField() = f and + nameCheck(c) and + nameCheck(f) +select c, f, accessType(f), fieldType(f), pointedType(f) diff --git a/cpp/ql/test/library-tests/ir/constant_func/constant_func.ql b/cpp/ql/test/library-tests/ir/constant_func/constant_func.ql index e23ac770cbe..238873c4575 100644 --- a/cpp/ql/test/library-tests/ir/constant_func/constant_func.ql +++ b/cpp/ql/test/library-tests/ir/constant_func/constant_func.ql @@ -1,30 +1,30 @@ -import default -import semmle.code.cpp.ssa.SSAIR -import semmle.code.cpp.ssa.internal.IntegerConstant - -language[monotonicAggregates] -IntValue getConstantValue(Instruction instr) { - result = instr.(IntegerConstantInstruction).getValue().toInt() or - exists(BinaryInstruction binInstr, IntValue left, IntValue right | - binInstr = instr and - left = getConstantValue(binInstr.getLeftOperand()) and - right = getConstantValue(binInstr.getRightOperand()) and - ( - binInstr instanceof AddInstruction and result = add(left, right) or - binInstr instanceof SubInstruction and result = sub(left, right) or - binInstr instanceof MulInstruction and result = mul(left, right) or - binInstr instanceof DivInstruction and result = div(left, right) - ) - ) or - result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or - exists(PhiInstruction phi | - phi = instr and - result = max(Instruction operand | operand = phi.getAnOperand() | getConstantValue(operand)) and - result = min(Instruction operand | operand = phi.getAnOperand() | getConstantValue(operand)) - ) -} - -from FunctionIR funcIR, int value -where - value = getValue(getConstantValue(funcIR.getReturnInstruction().(ReturnValueInstruction).getReturnValue())) -select funcIR, value +import default +import semmle.code.cpp.ssa.SSAIR +import semmle.code.cpp.ssa.internal.IntegerConstant + +language[monotonicAggregates] +IntValue getConstantValue(Instruction instr) { + result = instr.(IntegerConstantInstruction).getValue().toInt() or + exists(BinaryInstruction binInstr, IntValue left, IntValue right | + binInstr = instr and + left = getConstantValue(binInstr.getLeftOperand()) and + right = getConstantValue(binInstr.getRightOperand()) and + ( + binInstr instanceof AddInstruction and result = add(left, right) or + binInstr instanceof SubInstruction and result = sub(left, right) or + binInstr instanceof MulInstruction and result = mul(left, right) or + binInstr instanceof DivInstruction and result = div(left, right) + ) + ) or + result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or + exists(PhiInstruction phi | + phi = instr and + result = max(Instruction operand | operand = phi.getAnOperand() | getConstantValue(operand)) and + result = min(Instruction operand | operand = phi.getAnOperand() | getConstantValue(operand)) + ) +} + +from FunctionIR funcIR, int value +where + value = getValue(getConstantValue(funcIR.getReturnInstruction().(ReturnValueInstruction).getReturnValue())) +select funcIR, value diff --git a/cpp/ql/test/library-tests/ir/ir/ssa_block_count.ql b/cpp/ql/test/library-tests/ir/ir/ssa_block_count.ql index 859041f74e0..909e5c2adce 100644 --- a/cpp/ql/test/library-tests/ir/ir/ssa_block_count.ql +++ b/cpp/ql/test/library-tests/ir/ir/ssa_block_count.ql @@ -1,5 +1,5 @@ -import default -import semmle.code.cpp.ssa.SSAIR - -from FunctionIR funcIR -select funcIR.toString(), count(funcIR.getABlock()) +import default +import semmle.code.cpp.ssa.SSAIR + +from FunctionIR funcIR +select funcIR.toString(), count(funcIR.getABlock()) diff --git a/cpp/ql/test/library-tests/literals/aggregate_literals/arrays.ql b/cpp/ql/test/library-tests/literals/aggregate_literals/arrays.ql index 58c162b3f8d..d4d19ccfd1b 100644 --- a/cpp/ql/test/library-tests/literals/aggregate_literals/arrays.ql +++ b/cpp/ql/test/library-tests/literals/aggregate_literals/arrays.ql @@ -1,5 +1,5 @@ -import cpp - -from ArrayType a, ArrayAggregateLiteral al, int i -where a = al.getType() -select al, a, i, al.getElementExpr(i) +import cpp + +from ArrayType a, ArrayAggregateLiteral al, int i +where a = al.getType() +select al, a, i, al.getElementExpr(i) diff --git a/cpp/ql/test/library-tests/literals/aggregate_literals/arrays_value_init.ql b/cpp/ql/test/library-tests/literals/aggregate_literals/arrays_value_init.ql index 91efe690001..81e06d29a5a 100644 --- a/cpp/ql/test/library-tests/literals/aggregate_literals/arrays_value_init.ql +++ b/cpp/ql/test/library-tests/literals/aggregate_literals/arrays_value_init.ql @@ -1,6 +1,6 @@ -import cpp - -from ArrayType a, ArrayAggregateLiteral al, int i -where a = al.getType() - and al.isValueInitialized(i) -select al, a, i +import cpp + +from ArrayType a, ArrayAggregateLiteral al, int i +where a = al.getType() + and al.isValueInitialized(i) +select al, a, i diff --git a/cpp/ql/test/library-tests/literals/aggregate_literals/classes.ql b/cpp/ql/test/library-tests/literals/aggregate_literals/classes.ql index 2203251a187..1cb6b731623 100644 --- a/cpp/ql/test/library-tests/literals/aggregate_literals/classes.ql +++ b/cpp/ql/test/library-tests/literals/aggregate_literals/classes.ql @@ -1,6 +1,6 @@ -import cpp - -from Class c, ClassAggregateLiteral al, Field f -where c = al.getType() - and f = c.getAField() -select al, c, f, al.getFieldExpr(f) +import cpp + +from Class c, ClassAggregateLiteral al, Field f +where c = al.getType() + and f = c.getAField() +select al, c, f, al.getFieldExpr(f) diff --git a/cpp/ql/test/library-tests/literals/aggregate_literals/classes_value_init.ql b/cpp/ql/test/library-tests/literals/aggregate_literals/classes_value_init.ql index 01d0098ff5e..71752805b78 100644 --- a/cpp/ql/test/library-tests/literals/aggregate_literals/classes_value_init.ql +++ b/cpp/ql/test/library-tests/literals/aggregate_literals/classes_value_init.ql @@ -1,6 +1,6 @@ -import cpp - -from Class c, ClassAggregateLiteral al, Field f -where c = al.getType() - and al.isValueInitialized(f) -select al, c, f +import cpp + +from Class c, ClassAggregateLiteral al, Field f +where c = al.getType() + and al.isValueInitialized(f) +select al, c, f diff --git a/cpp/ql/test/library-tests/parameters/parameters/Parameters3.ql b/cpp/ql/test/library-tests/parameters/parameters/Parameters3.ql index b88808a132e..a346afdb931 100644 --- a/cpp/ql/test/library-tests/parameters/parameters/Parameters3.ql +++ b/cpp/ql/test/library-tests/parameters/parameters/Parameters3.ql @@ -2,13 +2,13 @@ * @name Parameters3 * @kind table */ -import cpp - -from Function f, int i, Parameter p, string pname, boolean named +import cpp + +from Function f, int i, Parameter p, string pname, boolean named where f.hasName("Dispatch") and f.getParameter(i) = p and p.getName() = pname and ( p.isNamed() and named = true - or not p.isNamed() and named = false) + or not p.isNamed() and named = false) select f, i, pname, named diff --git a/cpp/ql/test/library-tests/stmt/break/break.ql b/cpp/ql/test/library-tests/stmt/break/break.ql index d33941a0c09..70093da60f3 100644 --- a/cpp/ql/test/library-tests/stmt/break/break.ql +++ b/cpp/ql/test/library-tests/stmt/break/break.ql @@ -1,5 +1,5 @@ -import cpp - -from BreakStmt b, Stmt s -where b.getBreakable() = s -select b, s +import cpp + +from BreakStmt b, Stmt s +where b.getBreakable() = s +select b, s diff --git a/cpp/ql/test/library-tests/structs/compatible_variables/test.ql b/cpp/ql/test/library-tests/structs/compatible_variables/test.ql index 763deead9a4..d00bf751145 100644 --- a/cpp/ql/test/library-tests/structs/compatible_variables/test.ql +++ b/cpp/ql/test/library-tests/structs/compatible_variables/test.ql @@ -1,4 +1,4 @@ -import cpp - -from Variable v -select v +import cpp + +from Variable v +select v diff --git a/cpp/ql/test/library-tests/structs/incomplete_definition/pointerbasetype.ql b/cpp/ql/test/library-tests/structs/incomplete_definition/pointerbasetype.ql index 2fd5403f215..5c01213e735 100644 --- a/cpp/ql/test/library-tests/structs/incomplete_definition/pointerbasetype.ql +++ b/cpp/ql/test/library-tests/structs/incomplete_definition/pointerbasetype.ql @@ -1,5 +1,5 @@ -import cpp - -from Variable v, Class t -where t = v.getType().(PointerType).getBaseType() -select v, t, count(t.getAMember()) +import cpp + +from Variable v, Class t +where t = v.getType().(PointerType).getBaseType() +select v, t, count(t.getAMember()) diff --git a/cpp/ql/test/library-tests/synchronization/testoptions.qll b/cpp/ql/test/library-tests/synchronization/testoptions.qll index 669b6cb63ce..793a478cf37 100644 --- a/cpp/ql/test/library-tests/synchronization/testoptions.qll +++ b/cpp/ql/test/library-tests/synchronization/testoptions.qll @@ -1,29 +1,29 @@ -import cpp - -class MutexTypeForTest extends MutexType { - MutexTypeForTest() { - this.(Class).getName() = "Mutex7" - } - - override predicate mustlockAccess(FunctionCall fc, Expr arg) { - exists(Function f | - f = fc.getTarget() and - f.getName() = "custom_l" and - f.getDeclaringType() = this and - arg = fc.getQualifier() - ) - } - - override predicate trylockAccess(FunctionCall fc, Expr arg) { - none() - } - - override predicate unlockAccess(FunctionCall fc, Expr arg) { - exists(Function f | - f = fc.getTarget() and - f.getName() = "custom_ul" and - f.getDeclaringType() = this and - arg = fc.getQualifier() - ) - } -} +import cpp + +class MutexTypeForTest extends MutexType { + MutexTypeForTest() { + this.(Class).getName() = "Mutex7" + } + + override predicate mustlockAccess(FunctionCall fc, Expr arg) { + exists(Function f | + f = fc.getTarget() and + f.getName() = "custom_l" and + f.getDeclaringType() = this and + arg = fc.getQualifier() + ) + } + + override predicate trylockAccess(FunctionCall fc, Expr arg) { + none() + } + + override predicate unlockAccess(FunctionCall fc, Expr arg) { + exists(Function f | + f = fc.getTarget() and + f.getName() = "custom_ul" and + f.getDeclaringType() = this and + arg = fc.getQualifier() + ) + } +} diff --git a/cpp/ql/test/query-tests/Critical/MemoryFreed/MemoryFreed.ql b/cpp/ql/test/query-tests/Critical/MemoryFreed/MemoryFreed.ql index d62445d65a5..05f6d380ef1 100644 --- a/cpp/ql/test/query-tests/Critical/MemoryFreed/MemoryFreed.ql +++ b/cpp/ql/test/query-tests/Critical/MemoryFreed/MemoryFreed.ql @@ -1,4 +1,4 @@ -import Critical.MemoryFreed - -from FreedExpr fe -select fe +import Critical.MemoryFreed + +from FreedExpr fe +select fe diff --git a/cpp/ql/test/query-tests/Critical/NewFree/NewArrayDeleteMismatch.qlref b/cpp/ql/test/query-tests/Critical/NewFree/NewArrayDeleteMismatch.qlref index 2610dc656e8..72039b834eb 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/NewArrayDeleteMismatch.qlref +++ b/cpp/ql/test/query-tests/Critical/NewFree/NewArrayDeleteMismatch.qlref @@ -1 +1 @@ -Critical/NewArrayDeleteMismatch.ql +Critical/NewArrayDeleteMismatch.ql diff --git a/cpp/ql/test/query-tests/Critical/NewFree/NewDeleteArrayMismatch.qlref b/cpp/ql/test/query-tests/Critical/NewFree/NewDeleteArrayMismatch.qlref index 9c732423ee6..0acb486d300 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/NewDeleteArrayMismatch.qlref +++ b/cpp/ql/test/query-tests/Critical/NewFree/NewDeleteArrayMismatch.qlref @@ -1 +1 @@ -Critical/NewDeleteArrayMismatch.ql +Critical/NewDeleteArrayMismatch.ql diff --git a/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.qlref b/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.qlref index 6df9054326b..c7d3dfbdf08 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.qlref +++ b/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.qlref @@ -1 +1 @@ -Critical/NewFreeMismatch.ql +Critical/NewFreeMismatch.ql diff --git a/cpp/ql/test/successor-tests/initializer/parameterinitializer/controlflownode.ql b/cpp/ql/test/successor-tests/initializer/parameterinitializer/controlflownode.ql index f19912c6972..b5c6f07bd40 100644 --- a/cpp/ql/test/successor-tests/initializer/parameterinitializer/controlflownode.ql +++ b/cpp/ql/test/successor-tests/initializer/parameterinitializer/controlflownode.ql @@ -1,5 +1,5 @@ -import cpp - -from ControlFlowNode n -select n.getLocation().getStartLine(), n.getControlFlowScope(), n, - count(n.getAPredecessor()), count(n.getASuccessor()) +import cpp + +from ControlFlowNode n +select n.getLocation().getStartLine(), n.getControlFlowScope(), n, + count(n.getAPredecessor()), count(n.getASuccessor()) diff --git a/csharp/ql/test/query-tests/Bad Practices/Comments/CommentedOutCode/CommentedOutCode.qlref b/csharp/ql/test/query-tests/Bad Practices/Comments/CommentedOutCode/CommentedOutCode.qlref index 007bc1b4b31..99318fe478e 100644 --- a/csharp/ql/test/query-tests/Bad Practices/Comments/CommentedOutCode/CommentedOutCode.qlref +++ b/csharp/ql/test/query-tests/Bad Practices/Comments/CommentedOutCode/CommentedOutCode.qlref @@ -1 +1 @@ -Bad Practices/Comments/CommentedOutCode.ql +Bad Practices/Comments/CommentedOutCode.ql diff --git a/csharp/ql/test/query-tests/Bad Practices/Comments/TodoComments/TodoComments.qlref b/csharp/ql/test/query-tests/Bad Practices/Comments/TodoComments/TodoComments.qlref index d6ee99e4fe1..b9114382c5b 100644 --- a/csharp/ql/test/query-tests/Bad Practices/Comments/TodoComments/TodoComments.qlref +++ b/csharp/ql/test/query-tests/Bad Practices/Comments/TodoComments/TodoComments.qlref @@ -1 +1 @@ -Bad Practices/Comments/TodoComments.ql +Bad Practices/Comments/TodoComments.ql diff --git a/csharp/ql/test/query-tests/Bad Practices/Naming Conventions/ConfusingMethodNames/ConfusingMethodNames.qlref b/csharp/ql/test/query-tests/Bad Practices/Naming Conventions/ConfusingMethodNames/ConfusingMethodNames.qlref index 4e217471d78..3308ff3889e 100644 --- a/csharp/ql/test/query-tests/Bad Practices/Naming Conventions/ConfusingMethodNames/ConfusingMethodNames.qlref +++ b/csharp/ql/test/query-tests/Bad Practices/Naming Conventions/ConfusingMethodNames/ConfusingMethodNames.qlref @@ -1 +1 @@ -Bad Practices/Naming Conventions/ConfusingMethodNames.ql +Bad Practices/Naming Conventions/ConfusingMethodNames.ql diff --git a/csharp/ql/test/query-tests/Documentation/XmldocExtraParam.qlref b/csharp/ql/test/query-tests/Documentation/XmldocExtraParam.qlref index 768c5ef35eb..fd8371466b6 100644 --- a/csharp/ql/test/query-tests/Documentation/XmldocExtraParam.qlref +++ b/csharp/ql/test/query-tests/Documentation/XmldocExtraParam.qlref @@ -1 +1 @@ -Documentation/XmldocExtraParam.ql +Documentation/XmldocExtraParam.ql diff --git a/csharp/ql/test/query-tests/Documentation/XmldocMissingException.qlref b/csharp/ql/test/query-tests/Documentation/XmldocMissingException.qlref index fdde3255e65..ec059908e38 100644 --- a/csharp/ql/test/query-tests/Documentation/XmldocMissingException.qlref +++ b/csharp/ql/test/query-tests/Documentation/XmldocMissingException.qlref @@ -1 +1 @@ -Documentation/XmldocMissingException.ql +Documentation/XmldocMissingException.ql diff --git a/csharp/ql/test/query-tests/Documentation/XmldocMissingParam.qlref b/csharp/ql/test/query-tests/Documentation/XmldocMissingParam.qlref index 77fe5be68c6..9a8d6f801b7 100644 --- a/csharp/ql/test/query-tests/Documentation/XmldocMissingParam.qlref +++ b/csharp/ql/test/query-tests/Documentation/XmldocMissingParam.qlref @@ -1 +1 @@ -Documentation/XmldocMissingParam.ql +Documentation/XmldocMissingParam.ql diff --git a/csharp/ql/test/query-tests/Documentation/XmldocMissingReturn.qlref b/csharp/ql/test/query-tests/Documentation/XmldocMissingReturn.qlref index c37b2acd875..6eb8865b4b5 100644 --- a/csharp/ql/test/query-tests/Documentation/XmldocMissingReturn.qlref +++ b/csharp/ql/test/query-tests/Documentation/XmldocMissingReturn.qlref @@ -1 +1 @@ -Documentation/XmldocMissingReturn.ql +Documentation/XmldocMissingReturn.ql diff --git a/csharp/ql/test/query-tests/Documentation/XmldocMissingSummary.qlref b/csharp/ql/test/query-tests/Documentation/XmldocMissingSummary.qlref index b9f9e376e55..5046e31a3db 100644 --- a/csharp/ql/test/query-tests/Documentation/XmldocMissingSummary.qlref +++ b/csharp/ql/test/query-tests/Documentation/XmldocMissingSummary.qlref @@ -1 +1 @@ -Documentation/XmldocMissingSummary.ql +Documentation/XmldocMissingSummary.ql diff --git a/csharp/ql/test/query-tests/Documentation/XmldocMissingTypeParam.qlref b/csharp/ql/test/query-tests/Documentation/XmldocMissingTypeParam.qlref index b326839fdf1..f06bbb263d0 100644 --- a/csharp/ql/test/query-tests/Documentation/XmldocMissingTypeParam.qlref +++ b/csharp/ql/test/query-tests/Documentation/XmldocMissingTypeParam.qlref @@ -1 +1 @@ -Documentation/XmldocMissingTypeParam.ql +Documentation/XmldocMissingTypeParam.ql diff --git a/csharp/ql/test/query-tests/EmptyBlock/EmptyBlock.qlref b/csharp/ql/test/query-tests/EmptyBlock/EmptyBlock.qlref index 2f106109674..af8a3a21f8a 100644 --- a/csharp/ql/test/query-tests/EmptyBlock/EmptyBlock.qlref +++ b/csharp/ql/test/query-tests/EmptyBlock/EmptyBlock.qlref @@ -1 +1 @@ -Likely Bugs/Statements/EmptyBlock.ql +Likely Bugs/Statements/EmptyBlock.ql diff --git a/csharp/ql/test/query-tests/Language Abuse/ChainedIs/ChainedIs.qlref b/csharp/ql/test/query-tests/Language Abuse/ChainedIs/ChainedIs.qlref index 000e80ce61b..0d67fca3239 100644 --- a/csharp/ql/test/query-tests/Language Abuse/ChainedIs/ChainedIs.qlref +++ b/csharp/ql/test/query-tests/Language Abuse/ChainedIs/ChainedIs.qlref @@ -1 +1 @@ -Language Abuse/ChainedIs.ql +Language Abuse/ChainedIs.ql diff --git a/csharp/ql/test/query-tests/Language Abuse/ForeachCapture/ForeachCapture.qlref b/csharp/ql/test/query-tests/Language Abuse/ForeachCapture/ForeachCapture.qlref index de6df042ae2..733f31198af 100644 --- a/csharp/ql/test/query-tests/Language Abuse/ForeachCapture/ForeachCapture.qlref +++ b/csharp/ql/test/query-tests/Language Abuse/ForeachCapture/ForeachCapture.qlref @@ -1 +1 @@ -Language Abuse/ForeachCapture.ql +Language Abuse/ForeachCapture.ql diff --git a/csharp/ql/test/query-tests/Language Abuse/MissedReadonlyOpportunity/MissedReadonlyOpportunity.qlref b/csharp/ql/test/query-tests/Language Abuse/MissedReadonlyOpportunity/MissedReadonlyOpportunity.qlref index d64929541d7..28237dce311 100644 --- a/csharp/ql/test/query-tests/Language Abuse/MissedReadonlyOpportunity/MissedReadonlyOpportunity.qlref +++ b/csharp/ql/test/query-tests/Language Abuse/MissedReadonlyOpportunity/MissedReadonlyOpportunity.qlref @@ -1 +1 @@ -Language Abuse/MissedReadonlyOpportunity.ql +Language Abuse/MissedReadonlyOpportunity.ql diff --git a/csharp/ql/test/query-tests/Language Abuse/MissedTernaryOpportunity/MissedTernaryOpportunity.qlref b/csharp/ql/test/query-tests/Language Abuse/MissedTernaryOpportunity/MissedTernaryOpportunity.qlref index d86ede201a7..7efb97ac6fe 100644 --- a/csharp/ql/test/query-tests/Language Abuse/MissedTernaryOpportunity/MissedTernaryOpportunity.qlref +++ b/csharp/ql/test/query-tests/Language Abuse/MissedTernaryOpportunity/MissedTernaryOpportunity.qlref @@ -1 +1 @@ -Language Abuse/MissedTernaryOpportunity.ql +Language Abuse/MissedTernaryOpportunity.ql diff --git a/csharp/ql/test/query-tests/Language Abuse/UselessIsBeforeAs/UselessIsBeforeAs.qlref b/csharp/ql/test/query-tests/Language Abuse/UselessIsBeforeAs/UselessIsBeforeAs.qlref index fa7678ff3d7..9a5a7fd703c 100644 --- a/csharp/ql/test/query-tests/Language Abuse/UselessIsBeforeAs/UselessIsBeforeAs.qlref +++ b/csharp/ql/test/query-tests/Language Abuse/UselessIsBeforeAs/UselessIsBeforeAs.qlref @@ -1 +1 @@ -Language Abuse/UselessIsBeforeAs.ql +Language Abuse/UselessIsBeforeAs.ql diff --git a/csharp/ql/test/query-tests/UseBraces/UseBraces.qlref b/csharp/ql/test/query-tests/UseBraces/UseBraces.qlref index 116355e888d..5d1d4a06388 100755 --- a/csharp/ql/test/query-tests/UseBraces/UseBraces.qlref +++ b/csharp/ql/test/query-tests/UseBraces/UseBraces.qlref @@ -1 +1 @@ -Likely Bugs/Statements/UseBraces.ql +Likely Bugs/Statements/UseBraces.ql diff --git a/csharp/ql/test/query-tests/Useless Code/PointlessForwardingMethod/PointlessForwardingMethod.qlref b/csharp/ql/test/query-tests/Useless Code/PointlessForwardingMethod/PointlessForwardingMethod.qlref index 23b603d8ee4..2e42cbc7502 100644 --- a/csharp/ql/test/query-tests/Useless Code/PointlessForwardingMethod/PointlessForwardingMethod.qlref +++ b/csharp/ql/test/query-tests/Useless Code/PointlessForwardingMethod/PointlessForwardingMethod.qlref @@ -1 +1 @@ -Useless code/PointlessForwardingMethod.ql +Useless code/PointlessForwardingMethod.ql diff --git a/javascript/ql/test/library-tests/frameworks/Electron/RemoteFlowSources.ql b/javascript/ql/test/library-tests/frameworks/Electron/RemoteFlowSources.ql index 2936dc4b052..8aecd824335 100644 --- a/javascript/ql/test/library-tests/frameworks/Electron/RemoteFlowSources.ql +++ b/javascript/ql/test/library-tests/frameworks/Electron/RemoteFlowSources.ql @@ -1,4 +1,4 @@ -import javascript - -from RemoteFlowSource source -select source +import javascript + +from RemoteFlowSource source +select source diff --git a/javascript/ql/test/library-tests/frameworks/Electron/WebPreferences.ql b/javascript/ql/test/library-tests/frameworks/Electron/WebPreferences.ql index 6bd2336f1aa..417c3fe5a40 100644 --- a/javascript/ql/test/library-tests/frameworks/Electron/WebPreferences.ql +++ b/javascript/ql/test/library-tests/frameworks/Electron/WebPreferences.ql @@ -1,4 +1,4 @@ -import javascript - -from Electron::WebPreferences wp +import javascript + +from Electron::WebPreferences wp select wp \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/NodeJSLib/RemoteFlowSources.ql b/javascript/ql/test/library-tests/frameworks/NodeJSLib/RemoteFlowSources.ql index 2936dc4b052..8aecd824335 100644 --- a/javascript/ql/test/library-tests/frameworks/NodeJSLib/RemoteFlowSources.ql +++ b/javascript/ql/test/library-tests/frameworks/NodeJSLib/RemoteFlowSources.ql @@ -1,4 +1,4 @@ -import javascript - -from RemoteFlowSource source -select source +import javascript + +from RemoteFlowSource source +select source