From ccc9e09dbd7d90315409a844fb942e96858b2567 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 23 May 2023 10:00:09 -0700 Subject: [PATCH 1/5] C++: Add mechanism to hide specific instructions and operands from PrintIR. --- .../code/cpp/ir/implementation/aliased_ssa/IR.qll | 12 ++++++++++++ .../cpp/ir/implementation/aliased_ssa/PrintIR.qll | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll index c96783fe6e81..79873d8366e5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll @@ -77,4 +77,16 @@ class IRPropertyProvider extends TIRPropertyProvider { * Gets the value of the property named `key` for the specified operand. */ string getOperandProperty(Operand operand, string key) { none() } + + /** + * Holds if the instruction `instr` should be included when printing + * the IR instructions. + */ + predicate shouldPrintInstruction(Instruction instr) { any() } + + /** + * Holds if the operand `operand` should be included when printing the an + * instruction's operand list. + */ + predicate shouldPrintOperand(Operand operand) { any() } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll index 2ababa6199a6..b9106a7bfc73 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll @@ -42,6 +42,14 @@ private predicate shouldPrintFunction(Language::Declaration decl) { exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) } +private predicate shouldPrintInstruction(Instruction i) { + exists(IRPropertyProvider provider | provider.shouldPrintInstruction(i)) +} + +private predicate shouldPrintOperand(Operand operand) { + exists(IRPropertyProvider provider | provider.shouldPrintOperand(operand)) +} + private string getAdditionalInstructionProperty(Instruction instr, string key) { exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key)) } @@ -84,7 +92,9 @@ private string getOperandPropertyString(Operand operand) { private newtype TPrintableIRNode = TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or - TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) } + TPrintableInstruction(Instruction instr) { + shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction()) + } /** * A node to be emitted in the IR graph. @@ -252,7 +262,8 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio private string getOperandsString() { result = concat(Operand operand | - operand = instr.getAnOperand() + operand = instr.getAnOperand() and + shouldPrintOperand(operand) | operand.getDumpString() + getOperandPropertyString(operand), ", " order by From 0519ceeeaaa0b084412b56716df2067d5e614e73 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 23 May 2023 10:00:26 -0700 Subject: [PATCH 2/5] C++/C#: Sync identical files. --- .../semmle/code/cpp/ir/implementation/raw/IR.qll | 12 ++++++++++++ .../code/cpp/ir/implementation/raw/PrintIR.qll | 15 +++++++++++++-- .../cpp/ir/implementation/unaliased_ssa/IR.qll | 12 ++++++++++++ .../ir/implementation/unaliased_ssa/PrintIR.qll | 15 +++++++++++++-- .../src/experimental/ir/implementation/raw/IR.qll | 12 ++++++++++++ .../ir/implementation/raw/PrintIR.qll | 15 +++++++++++++-- .../ir/implementation/unaliased_ssa/IR.qll | 12 ++++++++++++ .../ir/implementation/unaliased_ssa/PrintIR.qll | 15 +++++++++++++-- 8 files changed, 100 insertions(+), 8 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IR.qll index c96783fe6e81..79873d8366e5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IR.qll @@ -77,4 +77,16 @@ class IRPropertyProvider extends TIRPropertyProvider { * Gets the value of the property named `key` for the specified operand. */ string getOperandProperty(Operand operand, string key) { none() } + + /** + * Holds if the instruction `instr` should be included when printing + * the IR instructions. + */ + predicate shouldPrintInstruction(Instruction instr) { any() } + + /** + * Holds if the operand `operand` should be included when printing the an + * instruction's operand list. + */ + predicate shouldPrintOperand(Operand operand) { any() } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll index 2ababa6199a6..b9106a7bfc73 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll @@ -42,6 +42,14 @@ private predicate shouldPrintFunction(Language::Declaration decl) { exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) } +private predicate shouldPrintInstruction(Instruction i) { + exists(IRPropertyProvider provider | provider.shouldPrintInstruction(i)) +} + +private predicate shouldPrintOperand(Operand operand) { + exists(IRPropertyProvider provider | provider.shouldPrintOperand(operand)) +} + private string getAdditionalInstructionProperty(Instruction instr, string key) { exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key)) } @@ -84,7 +92,9 @@ private string getOperandPropertyString(Operand operand) { private newtype TPrintableIRNode = TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or - TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) } + TPrintableInstruction(Instruction instr) { + shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction()) + } /** * A node to be emitted in the IR graph. @@ -252,7 +262,8 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio private string getOperandsString() { result = concat(Operand operand | - operand = instr.getAnOperand() + operand = instr.getAnOperand() and + shouldPrintOperand(operand) | operand.getDumpString() + getOperandPropertyString(operand), ", " order by diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll index c96783fe6e81..79873d8366e5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll @@ -77,4 +77,16 @@ class IRPropertyProvider extends TIRPropertyProvider { * Gets the value of the property named `key` for the specified operand. */ string getOperandProperty(Operand operand, string key) { none() } + + /** + * Holds if the instruction `instr` should be included when printing + * the IR instructions. + */ + predicate shouldPrintInstruction(Instruction instr) { any() } + + /** + * Holds if the operand `operand` should be included when printing the an + * instruction's operand list. + */ + predicate shouldPrintOperand(Operand operand) { any() } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll index 2ababa6199a6..b9106a7bfc73 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll @@ -42,6 +42,14 @@ private predicate shouldPrintFunction(Language::Declaration decl) { exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) } +private predicate shouldPrintInstruction(Instruction i) { + exists(IRPropertyProvider provider | provider.shouldPrintInstruction(i)) +} + +private predicate shouldPrintOperand(Operand operand) { + exists(IRPropertyProvider provider | provider.shouldPrintOperand(operand)) +} + private string getAdditionalInstructionProperty(Instruction instr, string key) { exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key)) } @@ -84,7 +92,9 @@ private string getOperandPropertyString(Operand operand) { private newtype TPrintableIRNode = TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or - TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) } + TPrintableInstruction(Instruction instr) { + shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction()) + } /** * A node to be emitted in the IR graph. @@ -252,7 +262,8 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio private string getOperandsString() { result = concat(Operand operand | - operand = instr.getAnOperand() + operand = instr.getAnOperand() and + shouldPrintOperand(operand) | operand.getDumpString() + getOperandPropertyString(operand), ", " order by diff --git a/csharp/ql/src/experimental/ir/implementation/raw/IR.qll b/csharp/ql/src/experimental/ir/implementation/raw/IR.qll index c96783fe6e81..79873d8366e5 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/IR.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/IR.qll @@ -77,4 +77,16 @@ class IRPropertyProvider extends TIRPropertyProvider { * Gets the value of the property named `key` for the specified operand. */ string getOperandProperty(Operand operand, string key) { none() } + + /** + * Holds if the instruction `instr` should be included when printing + * the IR instructions. + */ + predicate shouldPrintInstruction(Instruction instr) { any() } + + /** + * Holds if the operand `operand` should be included when printing the an + * instruction's operand list. + */ + predicate shouldPrintOperand(Operand operand) { any() } } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll b/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll index 2ababa6199a6..b9106a7bfc73 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll @@ -42,6 +42,14 @@ private predicate shouldPrintFunction(Language::Declaration decl) { exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) } +private predicate shouldPrintInstruction(Instruction i) { + exists(IRPropertyProvider provider | provider.shouldPrintInstruction(i)) +} + +private predicate shouldPrintOperand(Operand operand) { + exists(IRPropertyProvider provider | provider.shouldPrintOperand(operand)) +} + private string getAdditionalInstructionProperty(Instruction instr, string key) { exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key)) } @@ -84,7 +92,9 @@ private string getOperandPropertyString(Operand operand) { private newtype TPrintableIRNode = TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or - TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) } + TPrintableInstruction(Instruction instr) { + shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction()) + } /** * A node to be emitted in the IR graph. @@ -252,7 +262,8 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio private string getOperandsString() { result = concat(Operand operand | - operand = instr.getAnOperand() + operand = instr.getAnOperand() and + shouldPrintOperand(operand) | operand.getDumpString() + getOperandPropertyString(operand), ", " order by diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IR.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IR.qll index c96783fe6e81..79873d8366e5 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IR.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IR.qll @@ -77,4 +77,16 @@ class IRPropertyProvider extends TIRPropertyProvider { * Gets the value of the property named `key` for the specified operand. */ string getOperandProperty(Operand operand, string key) { none() } + + /** + * Holds if the instruction `instr` should be included when printing + * the IR instructions. + */ + predicate shouldPrintInstruction(Instruction instr) { any() } + + /** + * Holds if the operand `operand` should be included when printing the an + * instruction's operand list. + */ + predicate shouldPrintOperand(Operand operand) { any() } } diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll index 2ababa6199a6..b9106a7bfc73 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll @@ -42,6 +42,14 @@ private predicate shouldPrintFunction(Language::Declaration decl) { exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) } +private predicate shouldPrintInstruction(Instruction i) { + exists(IRPropertyProvider provider | provider.shouldPrintInstruction(i)) +} + +private predicate shouldPrintOperand(Operand operand) { + exists(IRPropertyProvider provider | provider.shouldPrintOperand(operand)) +} + private string getAdditionalInstructionProperty(Instruction instr, string key) { exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key)) } @@ -84,7 +92,9 @@ private string getOperandPropertyString(Operand operand) { private newtype TPrintableIRNode = TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or - TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) } + TPrintableInstruction(Instruction instr) { + shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction()) + } /** * A node to be emitted in the IR graph. @@ -252,7 +262,8 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio private string getOperandsString() { result = concat(Operand operand | - operand = instr.getAnOperand() + operand = instr.getAnOperand() and + shouldPrintOperand(operand) | operand.getDumpString() + getOperandPropertyString(operand), ", " order by From 8ee7694e7dcb30d792a6476fff75a76d705cdfcf Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 23 May 2023 10:02:30 -0700 Subject: [PATCH 3/5] C++: Modernize the PrintIRLocalFlow after the use-use flow changes. --- .../ir/dataflow/internal/PrintIRLocalFlow.qll | 112 ++++-------------- .../ir/dataflow/internal/PrintIRUtilities.qll | 54 ++++++--- 2 files changed, 59 insertions(+), 107 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll index bbe236311fb1..e92a4a8933e9 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll @@ -1,119 +1,44 @@ private import cpp -// The `ValueNumbering` library has to be imported right after `cpp` to ensure -// that the cached IR gets the same checksum here as it does in queries that use -// `ValueNumbering` without `DataFlow`. -private import semmle.code.cpp.ir.ValueNumbering private import semmle.code.cpp.ir.IR -private import semmle.code.cpp.ir.dataflow.DataFlow private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil +private import SsaInternals as Ssa private import PrintIRUtilities /** * Gets the local dataflow from other nodes in the same function to this node. */ -private string getFromFlow(DataFlow::Node useNode, int order1, int order2) { - exists(DataFlow::Node defNode, string prefix | - ( - simpleLocalFlowStep(defNode, useNode) and prefix = "" - or - any(DataFlow::Configuration cfg).isAdditionalFlowStep(defNode, useNode) and - defNode.getEnclosingCallable() = useNode.getEnclosingCallable() and - prefix = "+" - ) and - if defNode.asInstruction() = useNode.asOperand().getAnyDef() - then - // Shorthand for flow from the def of this operand. - result = prefix + "def" and - order1 = -1 and - order2 = 0 - else - if defNode.asOperand().getUse() = useNode.asInstruction() - then - // Shorthand for flow from an operand of this instruction - result = prefix + defNode.asOperand().getDumpId() and - order1 = -1 and - order2 = defNode.asOperand().getDumpSortOrder() - else result = prefix + nodeId(defNode, order1, order2) +private string getFromFlow(Node node2, int order1, int order2) { + exists(Node node1 | + simpleLocalFlowStep(node1, node2) and + result = nodeId(node1, order1, order2) ) } /** * Gets the local dataflow from this node to other nodes in the same function. */ -private string getToFlow(DataFlow::Node defNode, int order1, int order2) { - exists(DataFlow::Node useNode, string prefix | - ( - simpleLocalFlowStep(defNode, useNode) and prefix = "" - or - any(DataFlow::Configuration cfg).isAdditionalFlowStep(defNode, useNode) and - defNode.getEnclosingCallable() = useNode.getEnclosingCallable() and - prefix = "+" - ) and - if useNode.asInstruction() = defNode.asOperand().getUse() - then - // Shorthand for flow to this operand's instruction. - result = prefix + "result" and - order1 = -1 and - order2 = 0 - else result = prefix + nodeId(useNode, order1, order2) +private string getToFlow(Node node1, int order1, int order2) { + exists(Node node2 | + simpleLocalFlowStep(node1, node2) and + result = nodeId(node2, order1, order2) ) } /** * Gets the properties of the dataflow node `node`. */ -private string getNodeProperty(DataFlow::Node node, string key) { +private string getNodeProperty(Node node, string key) { // List dataflow into and out of this node. Flow into this node is printed as `src->@`, and flow // out of this node is printed as `@->dest`. key = "flow" and result = strictconcat(string flow, boolean to, int order1, int order2 | - flow = getFromFlow(node, order1, order2) + "->@" and to = false + flow = getFromFlow(node, order1, order2) + "->" + starsForNode(node) + "@" and to = false or - flow = "@->" + getToFlow(node, order1, order2) and to = true + flow = starsForNode(node) + "@->" + getToFlow(node, order1, order2) and to = true | flow, ", " order by to, order1, order2, flow ) - or - // Is this node a dataflow sink? - key = "sink" and - any(DataFlow::Configuration cfg).isSink(node) and - result = "true" - or - // Is this node a dataflow source? - key = "source" and - any(DataFlow::Configuration cfg).isSource(node) and - result = "true" - or - // Is this node a dataflow barrier, and if so, what kind? - key = "barrier" and - result = - strictconcat(string kind | - any(DataFlow::Configuration cfg).isBarrier(node) and kind = "full" - or - any(DataFlow::Configuration cfg).isBarrierIn(node) and kind = "in" - or - any(DataFlow::Configuration cfg).isBarrierOut(node) and kind = "out" - | - kind, ", " - ) - // or - // // Is there partial flow from a source to this node? - // // This property will only be emitted if partial flow is enabled by overriding - // // `DataFlow::Configuration::explorationLimit()`. - // key = "pflow" and - // result = - // strictconcat(DataFlow::PartialPathNode sourceNode, DataFlow::PartialPathNode destNode, int dist, - // int order1, int order2 | - // any(DataFlow::Configuration cfg).hasPartialFlow(sourceNode, destNode, dist) and - // destNode.getNode() = node and - // // Only print flow from a source in the same function. - // sourceNode.getNode().getEnclosingCallable() = node.getEnclosingCallable() - // | - // nodeId(sourceNode.getNode(), order1, order2) + "+" + dist.toString(), ", " - // order by - // order1, order2, dist desc - // ) } /** @@ -121,16 +46,21 @@ private string getNodeProperty(DataFlow::Node node, string key) { */ class LocalFlowPropertyProvider extends IRPropertyProvider { override string getOperandProperty(Operand operand, string key) { - exists(DataFlow::Node node | - operand = node.asOperand() and + exists(Node node | + operand = [node.asOperand(), node.(RawIndirectOperand).getOperand()] and result = getNodeProperty(node, key) ) } override string getInstructionProperty(Instruction instruction, string key) { - exists(DataFlow::Node node | - instruction = node.asInstruction() and + exists(Node node | + instruction = [node.asInstruction(), node.(RawIndirectInstruction).getInstruction()] + | result = getNodeProperty(node, key) ) } + + override predicate shouldPrintOperand(Operand operand) { not Ssa::ignoreOperand(operand) } + + override predicate shouldPrintInstruction(Instruction instr) { not Ssa::ignoreInstruction(instr) } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRUtilities.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRUtilities.qll index 5fc15cf986c7..5c6cdebf800c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRUtilities.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRUtilities.qll @@ -3,37 +3,59 @@ */ private import cpp -// The `ValueNumbering` library has to be imported right after `cpp` to ensure -// that the cached IR gets the same checksum here as it does in queries that use -// `ValueNumbering` without `DataFlow`. -private import semmle.code.cpp.ir.ValueNumbering private import semmle.code.cpp.ir.IR -private import semmle.code.cpp.ir.dataflow.DataFlow +private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil +private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate + +private string stars(int k) { + k = + [0 .. max([ + any(RawIndirectInstruction n).getIndirectionIndex(), + any(RawIndirectOperand n).getIndirectionIndex() + ] + )] and + (if k = 0 then result = "" else result = "*" + stars(k - 1)) +} + +string starsForNode(Node node) { + result = stars(node.(IndirectInstruction).getIndirectionIndex()) + or + result = stars(node.(IndirectOperand).getIndirectionIndex()) + or + not node instanceof IndirectInstruction and + not node instanceof IndirectOperand and + result = "" +} + +private Instruction getInstruction(Node n, string stars) { + result = [n.asInstruction(), n.(RawIndirectInstruction).getInstruction()] and + stars = starsForNode(n) +} + +private Operand getOperand(Node n, string stars) { + result = [n.asOperand(), n.(RawIndirectOperand).getOperand()] and + stars = starsForNode(n) +} /** * Gets a short ID for an IR dataflow node. * - For `Instruction`s, this is just the result ID of the instruction (e.g. `m128`). * - For `Operand`s, this is the label of the operand, prefixed with the result ID of the * instruction and a dot (e.g. `m128.left`). - * - For `Variable`s, this is the qualified name of the variable. */ -string nodeId(DataFlow::Node node, int order1, int order2) { - exists(Instruction instruction | instruction = node.asInstruction() | - result = instruction.getResultId() and +string nodeId(Node node, int order1, int order2) { + exists(Instruction instruction, string stars | instruction = getInstruction(node, stars) | + result = stars + instruction.getResultId() and order1 = instruction.getBlock().getDisplayIndex() and order2 = instruction.getDisplayIndexInBlock() ) or - exists(Operand operand, Instruction instruction | - operand = node.asOperand() and + exists(Operand operand, Instruction instruction, string stars | + operand = getOperand(node, stars) and instruction = operand.getUse() | - result = instruction.getResultId() + "." + operand.getDumpId() and + result = stars + instruction.getResultId() + "." + operand.getDumpId() and order1 = instruction.getBlock().getDisplayIndex() and order2 = instruction.getDisplayIndexInBlock() ) - or - result = "var(" + node.asVariable().getQualifiedName() + ")" and - order1 = 1000000 and - order2 = 0 } From 43459c16fd8052124a34e6fa6f9a72b5f46473ce Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 23 May 2023 10:02:54 -0700 Subject: [PATCH 4/5] C++: Modernize the PrintIRStoreSteps (and rename it to PrintIRFieldFlowSteps) after the use-use flow changes. --- .../internal/PrintIRFieldFlowSteps.qll | 40 +++++++++++++++++++ .../dataflow/internal/PrintIRStoreSteps.qll | 33 --------------- 2 files changed, 40 insertions(+), 33 deletions(-) create mode 100644 cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll delete mode 100644 cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRStoreSteps.qll diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll new file mode 100644 index 000000000000..0c2be58a4b65 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll @@ -0,0 +1,40 @@ +/** + * Print the dataflow local store steps in IR dumps. + */ + +private import cpp +private import semmle.code.cpp.ir.IR +private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil +private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate +private import PrintIRUtilities + +/** + * Property provider for local IR dataflow store steps. + */ +class FieldFlowPropertyProvider extends IRPropertyProvider { + override string getOperandProperty(Operand operand, string key) { + exists(PostFieldUpdateNode pfun, Content content | + key = "store " + content.toString() and + operand = pfun.getPreUpdateNode().(IndirectOperand).getOperand() and + result = + strictconcat(string element, Node node | + storeStep(node, content, pfun) and + element = nodeId(node, _, _) + | + element, ", " + ) + ) + or + exists(Node node2, Content content | + key = "read " + content.toString() and + operand = node2.(IndirectOperand).getOperand() and + result = + strictconcat(string element, Node node1 | + readStep(node1, content, node2) and + element = nodeId(node1, _, _) + | + element, ", " + ) + ) + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRStoreSteps.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRStoreSteps.qll deleted file mode 100644 index 8c3182162170..000000000000 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRStoreSteps.qll +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Print the dataflow local store steps in IR dumps. - */ - -private import cpp -// The `ValueNumbering` library has to be imported right after `cpp` to ensure -// that the cached IR gets the same checksum here as it does in queries that use -// `ValueNumbering` without `DataFlow`. -private import semmle.code.cpp.ir.ValueNumbering -private import semmle.code.cpp.ir.IR -private import semmle.code.cpp.ir.dataflow.DataFlow -private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil -private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate -private import PrintIRUtilities - -/** - * Property provider for local IR dataflow store steps. - */ -class LocalFlowPropertyProvider extends IRPropertyProvider { - override string getInstructionProperty(Instruction instruction, string key) { - exists(DataFlow::Node objectNode, Content content | - key = "content[" + content.toString() + "]" and - instruction = objectNode.asInstruction() and - result = - strictconcat(string element, DataFlow::Node fieldNode | - storeStep(fieldNode, content, objectNode) and - element = nodeId(fieldNode, _, _) - | - element, ", " - ) - ) - } -} From 4b92a2a3d0f38f5ff606482d33456757399d580e Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 23 May 2023 10:13:19 -0700 Subject: [PATCH 5/5] C++: Fix Code Scanning error. --- .../code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll index 0c2be58a4b65..f0286c00cbca 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll @@ -8,9 +8,7 @@ private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate private import PrintIRUtilities -/** - * Property provider for local IR dataflow store steps. - */ +/** A property provider for local IR dataflow store steps. */ class FieldFlowPropertyProvider extends IRPropertyProvider { override string getOperandProperty(Operand operand, string key) { exists(PostFieldUpdateNode pfun, Content content |