mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
C++: Add an 'asDefinition' overload to check if a definition is certain or not.
This commit is contained in:
@@ -313,13 +313,79 @@ class Node extends TIRDataFlowNode {
|
||||
* `n.asExpr() instanceof IncrementOperation` since the result of evaluating
|
||||
* the expression `x++` is passed to `sink`.
|
||||
*/
|
||||
Expr asDefinition() {
|
||||
exists(StoreInstruction store |
|
||||
Expr asDefinition() { result = this.asDefinition(_) }
|
||||
|
||||
/**
|
||||
* Gets the definition associated with this node, if any.
|
||||
*
|
||||
* For example, consider the following example
|
||||
* ```cpp
|
||||
* int x = 42; // 1
|
||||
* x = 34; // 2
|
||||
* ++x; // 3
|
||||
* x++; // 4
|
||||
* x += 1; // 5
|
||||
* int y = x += 2; // 6
|
||||
* ```
|
||||
* - For (1) the result is `42`.
|
||||
* - For (2) the result is `x = 34`.
|
||||
* - For (3) the result is `++x`.
|
||||
* - For (4) the result is `x++`.
|
||||
* - For (5) the result is `x += 1`.
|
||||
* - For (6) there are two results:
|
||||
* - For the definition generated by `x += 2` the result is `x += 2`
|
||||
* - For the definition generated by `int y = ...` the result is
|
||||
* also `x += 2`.
|
||||
*
|
||||
* For assignments, `node.asDefinition()` and `node.asExpr()` will both exist
|
||||
* for the same dataflow node. However, for expression such as `x++` that
|
||||
* both write to `x` and read the current value of `x`, `node.asDefinition()`
|
||||
* will give the node corresponding to the value after the increment, and
|
||||
* `node.asExpr()` will give the node corresponding to the value before the
|
||||
* increment. For an example of this, consider the following:
|
||||
*
|
||||
* ```cpp
|
||||
* sink(x++);
|
||||
* ```
|
||||
* in the above program, there will not be flow from a node `n` such that
|
||||
* `n.asDefinition() instanceof IncrementOperation` to the argument of `sink`
|
||||
* since the value passed to `sink` is the value before to the increment.
|
||||
* However, there will be dataflow from a node `n` such that
|
||||
* `n.asExpr() instanceof IncrementOperation` since the result of evaluating
|
||||
* the expression `x++` is passed to `sink`.
|
||||
*
|
||||
* If `uncertain = false` then the definition is guaranteed to overwrite
|
||||
* the entire buffer pointed to by the destination address of the definition.
|
||||
* Otherwise, `uncertain = true`.
|
||||
*
|
||||
* For example, the write `int x; x = 42;` is guaranteed to overwrite all the
|
||||
* bytes allocated to `x`, while the assignment `int p[10]; p[3] = 42;` has
|
||||
* `uncertain = true` since the write will not overwrite the entire buffer
|
||||
* pointed to by `p`.
|
||||
*/
|
||||
Expr asDefinition(boolean uncertain) {
|
||||
exists(StoreInstruction store, Ssa::DefinitionExt def |
|
||||
store = this.asInstruction() and
|
||||
result = asDefinitionImpl(store)
|
||||
result = asDefinitionImpl(store) and
|
||||
Ssa::defToNode(this, def, _, _, _, _) and
|
||||
if def.isCertain() then uncertain = false else uncertain = true
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the definition associated with this node, if this node is a certain definition.
|
||||
*
|
||||
* See `Node.asDefinition` for a description of certain and uncertain definitions.
|
||||
*/
|
||||
Expr asCertainDefinition() { result = this.asDefinition(false) }
|
||||
|
||||
/**
|
||||
* Gets the definition associated with this node, if this node is an uncertain definition.
|
||||
*
|
||||
* See `Node.asDefinition` for a description of certain and uncertain definitions.
|
||||
*/
|
||||
Expr asUncertainDefinition() { result = this.asDefinition(true) }
|
||||
|
||||
/**
|
||||
* Gets the indirect definition at a given indirection corresponding to this
|
||||
* node, if any.
|
||||
|
||||
Reference in New Issue
Block a user