Merge pull request #14810 from MathiasVP/fix-ref-deref-duplication

C++: Fix dataflow duplication from `ReferenceDereference` expressions
This commit is contained in:
Mathias Vorreiter Pedersen
2023-11-16 16:10:07 +00:00
committed by GitHub
9 changed files with 494 additions and 132 deletions

View File

@@ -1273,31 +1273,90 @@ abstract private class IndirectExprNodeBase extends Node {
} }
} }
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand /** A signature for converting an indirect node to an expression. */
{ private signature module IndirectNodeToIndirectExprSig {
IndirectOperandIndirectExprNode() { /** The indirect node class to be converted to an expression */
exists(Expr e, int n, int indirectionIndex | class IndirectNode;
indirectExprNodeShouldBeIndirectOperand(this, e, n, indirectionIndex) and
not indirectExprNodeShouldBeIndirectOperand(_, e, n + 1, indirectionIndex) /**
) * Holds if the indirect expression at indirection index `indirectionIndex`
* of `node` is `e`. The integer `n` specifies how many conversions has been
* applied to `node`.
*/
predicate indirectNodeHasIndirectExpr(IndirectNode node, Expr e, int n, int indirectionIndex);
}
/**
* A module that implements the logic for deciding whether an indirect node
* should be an `IndirectExprNode`.
*/
private module IndirectNodeToIndirectExpr<IndirectNodeToIndirectExprSig Sig> {
import Sig
/**
* This predicate shifts the indirection index by one when `conv` is a
* `ReferenceDereferenceExpr`.
*
* This is necessary because `ReferenceDereferenceExpr` is a conversion
* in the AST, but appears as a `LoadInstruction` in the IR.
*/
bindingset[e, indirectionIndex]
private predicate adjustForReference(
Expr e, int indirectionIndex, Expr conv, int adjustedIndirectionIndex
) {
conv.(ReferenceDereferenceExpr).getExpr() = e and
adjustedIndirectionIndex = indirectionIndex - 1
or
not conv instanceof ReferenceDereferenceExpr and
conv = e and
adjustedIndirectionIndex = indirectionIndex
} }
final override Expr getConvertedExpr(int n, int index) { /** Holds if `node` should be an `IndirectExprNode`. */
indirectExprNodeShouldBeIndirectOperand(this, result, n, index) predicate charpred(IndirectNode node) {
exists(Expr e, int n, int indirectionIndex |
indirectNodeHasIndirectExpr(node, e, n, indirectionIndex) and
not exists(Expr conv, int adjustedIndirectionIndex |
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
indirectNodeHasIndirectExpr(_, conv, n + 1, adjustedIndirectionIndex)
)
)
} }
} }
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase instanceof IndirectInstruction private module IndirectOperandIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
class IndirectNode = IndirectOperand;
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectOperand/4;
}
module IndirectOperandToIndirectExpr =
IndirectNodeToIndirectExpr<IndirectOperandIndirectExprNodeImpl>;
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand
{ {
IndirectInstructionIndirectExprNode() { IndirectOperandIndirectExprNode() { IndirectOperandToIndirectExpr::charpred(this) }
exists(Expr e, int n, int indirectionIndex |
indirectExprNodeShouldBeIndirectInstruction(this, e, n, indirectionIndex) and
not indirectExprNodeShouldBeIndirectInstruction(_, e, n + 1, indirectionIndex)
)
}
final override Expr getConvertedExpr(int n, int index) { final override Expr getConvertedExpr(int n, int index) {
indirectExprNodeShouldBeIndirectInstruction(this, result, n, index) IndirectOperandToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
}
}
private module IndirectInstructionIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
class IndirectNode = IndirectInstruction;
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectInstruction/4;
}
module IndirectInstructionToIndirectExpr =
IndirectNodeToIndirectExpr<IndirectInstructionIndirectExprNodeImpl>;
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase instanceof IndirectInstruction
{
IndirectInstructionIndirectExprNode() { IndirectInstructionToIndirectExpr::charpred(this) }
final override Expr getConvertedExpr(int n, int index) {
IndirectInstructionToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
} }
} }

View File

@@ -0,0 +1,103 @@
module AstTest {
import semmle.code.cpp.dataflow.DataFlow
private import semmle.code.cpp.controlflow.Guards
/**
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
* S in `if (guarded(x)) S`.
*/
// This is tested in `BarrierGuard.cpp`.
predicate testBarrierGuard(GuardCondition g, Expr checked, boolean isTrue) {
g.(FunctionCall).getTarget().getName() = "guarded" and
checked = g.(FunctionCall).getArgument(0) and
isTrue = true
}
/** Common data flow configuration to be used by tests. */
module AstTestAllocationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asParameter().getName().matches("source%")
or
source.asExpr().(FunctionCall).getTarget().getName() = "indirect_source"
or
source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%")
or
// Track uninitialized variables
exists(source.asUninitialized())
}
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call |
call.getTarget().getName() = ["sink", "indirect_sink"] and
sink.asExpr() = call.getAnArgument()
)
}
predicate isBarrier(DataFlow::Node barrier) {
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
}
}
module AstFlow = DataFlow::Global<AstTestAllocationConfig>;
}
module IRTest {
private import cpp
import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.controlflow.IRGuards
/**
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
* S in `if (guarded(x)) S`.
*/
// This is tested in `BarrierGuard.cpp`.
predicate testBarrierGuard(IRGuardCondition g, Expr checked, boolean isTrue) {
exists(Call call |
call = g.getUnconvertedResultExpression() and
call.getTarget().hasName("guarded") and
checked = call.getArgument(0) and
isTrue = true
)
}
/** Common data flow configuration to be used by tests. */
module IRTestAllocationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asIndirectExpr(1).(FunctionCall).getTarget().getName() = "indirect_source"
or
source.asParameter().getName().matches("source%")
or
source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%")
or
exists(source.asUninitialized())
}
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call, Expr e | e = call.getAnArgument() |
call.getTarget().getName() = "sink" and
sink.asExpr() = e
or
call.getTarget().getName() = "indirect_sink" and
sink.asIndirectExpr() = e
)
}
predicate isBarrier(DataFlow::Node barrier) {
exists(Expr barrierExpr | barrierExpr in [barrier.asExpr(), barrier.asIndirectExpr()] |
barrierExpr.(VariableAccess).getTarget().hasName("barrier")
)
or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getAnIndirectBarrierNode()
}
}
module IRFlow = DataFlow::Global<IRTestAllocationConfig>;
}

View File

@@ -24,6 +24,7 @@ argHasPostUpdate
| lambdas.cpp:45:2:45:2 | e | ArgumentNode is missing PostUpdateNode. | | lambdas.cpp:45:2:45:2 | e | ArgumentNode is missing PostUpdateNode. |
| test.cpp:67:29:67:35 | source1 | ArgumentNode is missing PostUpdateNode. | | test.cpp:67:29:67:35 | source1 | ArgumentNode is missing PostUpdateNode. |
| test.cpp:813:19:813:35 | * ... | ArgumentNode is missing PostUpdateNode. | | test.cpp:813:19:813:35 | * ... | ArgumentNode is missing PostUpdateNode. |
| test.cpp:848:23:848:25 | rpx | ArgumentNode is missing PostUpdateNode. |
postWithInFlow postWithInFlow
| BarrierGuard.cpp:49:6:49:6 | x [post update] | PostUpdateNode should not be the target of local flow. | | BarrierGuard.cpp:49:6:49:6 | x [post update] | PostUpdateNode should not be the target of local flow. |
| BarrierGuard.cpp:60:7:60:7 | x [post update] | PostUpdateNode should not be the target of local flow. | | BarrierGuard.cpp:60:7:60:7 | x [post update] | PostUpdateNode should not be the target of local flow. |

View File

@@ -0,0 +1,294 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (test-source-sink.ql:3,25-42)
WARNING: Module DataFlow has been deprecated and may be removed in future (test-source-sink.ql:3,57-74)
astFlow
| BarrierGuard.cpp:5:19:5:24 | source | BarrierGuard.cpp:9:10:9:15 | source |
| BarrierGuard.cpp:13:17:13:22 | source | BarrierGuard.cpp:15:10:15:15 | source |
| BarrierGuard.cpp:21:17:21:22 | source | BarrierGuard.cpp:25:10:25:15 | source |
| BarrierGuard.cpp:29:16:29:21 | source | BarrierGuard.cpp:31:10:31:15 | source |
| BarrierGuard.cpp:29:16:29:21 | source | BarrierGuard.cpp:33:10:33:15 | source |
| BarrierGuard.cpp:49:10:49:15 | call to source | BarrierGuard.cpp:51:13:51:13 | x |
| BarrierGuard.cpp:49:10:49:15 | call to source | BarrierGuard.cpp:53:13:53:13 | x |
| BarrierGuard.cpp:49:10:49:15 | call to source | BarrierGuard.cpp:55:13:55:13 | x |
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:62:14:62:14 | x |
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:64:14:64:14 | x |
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:66:14:66:14 | x |
| acrossLinkTargets.cpp:19:27:19:32 | call to source | acrossLinkTargets.cpp:12:8:12:8 | x |
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:18:8:18:19 | sourceArray1 |
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:22:8:22:20 | & ... |
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:23:17:23:29 | & ... |
| clang.cpp:29:27:29:32 | call to source | clang.cpp:30:27:30:28 | m1 |
| clang.cpp:29:27:29:32 | call to source | clang.cpp:31:27:31:34 | call to getFirst |
| clang.cpp:35:32:35:37 | call to source | clang.cpp:38:10:38:11 | m2 |
| clang.cpp:44:35:44:40 | call to source | clang.cpp:46:17:46:18 | m2 |
| clang.cpp:51:19:51:24 | call to source | clang.cpp:52:8:52:17 | stackArray |
| clang.cpp:51:19:51:24 | call to source | clang.cpp:53:17:53:26 | stackArray |
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:35:16:35:25 | call to notSource1 |
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:43:15:43:24 | call to notSource1 |
| dispatch.cpp:10:37:10:42 | call to source | dispatch.cpp:36:16:36:25 | call to notSource2 |
| dispatch.cpp:10:37:10:42 | call to source | dispatch.cpp:44:15:44:24 | call to notSource2 |
| dispatch.cpp:37:19:37:24 | call to source | dispatch.cpp:11:38:11:38 | x |
| dispatch.cpp:45:18:45:23 | call to source | dispatch.cpp:11:38:11:38 | x |
| globals.cpp:5:17:5:22 | call to source | globals.cpp:6:10:6:14 | local |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:14:3:14:6 | t |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:18:8:18:8 | call to operator() |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:21:3:21:6 | t |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:29:3:29:6 | t |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:35:8:35:8 | a |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:41:8:41:8 | a |
| lambdas.cpp:43:7:43:12 | call to source | lambdas.cpp:46:7:46:7 | w |
| ref.cpp:29:11:29:16 | call to source | ref.cpp:62:10:62:11 | x3 |
| ref.cpp:53:9:53:10 | x1 | ref.cpp:56:10:56:11 | x1 |
| ref.cpp:53:13:53:14 | x2 | ref.cpp:59:10:59:11 | x2 |
| ref.cpp:53:17:53:18 | x3 | ref.cpp:62:10:62:11 | x3 |
| ref.cpp:53:21:53:22 | x4 | ref.cpp:65:10:65:11 | x4 |
| ref.cpp:55:23:55:28 | call to source | ref.cpp:56:10:56:11 | x1 |
| ref.cpp:94:15:94:20 | call to source | ref.cpp:129:13:129:15 | val |
| ref.cpp:109:15:109:20 | call to source | ref.cpp:132:13:132:15 | val |
| ref.cpp:122:23:122:28 | call to source | ref.cpp:123:13:123:15 | val |
| ref.cpp:125:19:125:24 | call to source | ref.cpp:126:13:126:15 | val |
| self-Iterator.cpp:19:23:19:28 | call to source | self-Iterator.cpp:20:10:20:10 | x |
| test.cpp:6:12:6:17 | call to source | test.cpp:7:8:7:9 | t1 |
| test.cpp:6:12:6:17 | call to source | test.cpp:9:8:9:9 | t1 |
| test.cpp:6:12:6:17 | call to source | test.cpp:10:8:10:9 | t2 |
| test.cpp:6:12:6:17 | call to source | test.cpp:15:8:15:9 | t2 |
| test.cpp:6:12:6:17 | call to source | test.cpp:26:8:26:9 | t1 |
| test.cpp:35:10:35:15 | call to source | test.cpp:30:8:30:8 | t |
| test.cpp:36:13:36:18 | call to source | test.cpp:31:8:31:8 | c |
| test.cpp:50:14:50:19 | call to source | test.cpp:58:10:58:10 | t |
| test.cpp:66:30:66:36 | source1 | test.cpp:71:8:71:9 | x4 |
| test.cpp:75:7:75:8 | u1 | test.cpp:76:8:76:9 | u1 |
| test.cpp:83:7:83:8 | u2 | test.cpp:84:8:84:18 | ... ? ... : ... |
| test.cpp:83:7:83:8 | u2 | test.cpp:86:8:86:9 | i1 |
| test.cpp:89:28:89:34 | source1 | test.cpp:90:8:90:14 | source1 |
| test.cpp:100:13:100:18 | call to source | test.cpp:103:10:103:12 | ref |
| test.cpp:138:27:138:32 | call to source | test.cpp:140:8:140:8 | y |
| test.cpp:151:33:151:38 | call to source | test.cpp:144:8:144:8 | s |
| test.cpp:151:33:151:38 | call to source | test.cpp:152:8:152:8 | y |
| test.cpp:164:34:164:39 | call to source | test.cpp:157:8:157:8 | x |
| test.cpp:164:34:164:39 | call to source | test.cpp:165:8:165:8 | y |
| test.cpp:171:11:171:16 | call to source | test.cpp:178:8:178:8 | y |
| test.cpp:245:14:245:19 | call to source | test.cpp:260:12:260:12 | x |
| test.cpp:265:22:265:27 | call to source | test.cpp:266:12:266:12 | x |
| test.cpp:305:17:305:22 | call to source | test.cpp:289:14:289:14 | x |
| test.cpp:314:4:314:9 | call to source | test.cpp:318:7:318:7 | x |
| test.cpp:347:17:347:22 | call to source | test.cpp:349:10:349:18 | globalVar |
| test.cpp:359:13:359:18 | call to source | test.cpp:365:10:365:14 | field |
| test.cpp:373:13:373:18 | call to source | test.cpp:369:10:369:14 | field |
| test.cpp:373:13:373:18 | call to source | test.cpp:375:10:375:14 | field |
| test.cpp:382:48:382:54 | source1 | test.cpp:385:8:385:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:392:8:392:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:394:10:394:12 | tmp |
| test.cpp:399:7:399:9 | tmp | test.cpp:401:8:401:10 | tmp |
| test.cpp:405:7:405:9 | tmp | test.cpp:408:8:408:10 | tmp |
| test.cpp:416:7:416:11 | local | test.cpp:418:8:418:12 | local |
| test.cpp:417:16:417:20 | ref arg local | test.cpp:418:8:418:12 | local |
| test.cpp:422:7:422:11 | local | test.cpp:424:8:424:12 | local |
| test.cpp:423:20:423:25 | ref arg & ... | test.cpp:424:8:424:12 | local |
| test.cpp:433:7:433:11 | local | test.cpp:435:8:435:12 | local |
| test.cpp:433:7:433:11 | local | test.cpp:436:8:436:13 | * ... |
| test.cpp:434:20:434:24 | ref arg local | test.cpp:435:8:435:12 | local |
| test.cpp:434:20:434:24 | ref arg local | test.cpp:436:8:436:13 | * ... |
| test.cpp:440:7:440:11 | local | test.cpp:442:8:442:12 | local |
| test.cpp:441:18:441:23 | ref arg & ... | test.cpp:442:8:442:12 | local |
| test.cpp:448:7:448:11 | local | test.cpp:450:8:450:12 | local |
| test.cpp:448:7:448:11 | local | test.cpp:451:8:451:13 | * ... |
| test.cpp:449:18:449:22 | ref arg local | test.cpp:450:8:450:12 | local |
| test.cpp:449:18:449:22 | ref arg local | test.cpp:451:8:451:13 | * ... |
| test.cpp:456:26:456:32 | source1 | test.cpp:457:9:457:22 | (statement expression) |
| test.cpp:456:26:456:32 | source1 | test.cpp:468:8:468:12 | local |
| test.cpp:472:8:472:13 | call to source | test.cpp:478:8:478:8 | x |
| test.cpp:506:8:506:13 | call to source | test.cpp:513:8:513:8 | x |
| test.cpp:517:7:517:16 | stackArray | test.cpp:521:8:521:20 | access to array |
| test.cpp:519:19:519:24 | call to source | test.cpp:521:8:521:20 | access to array |
| test.cpp:551:9:551:9 | y | test.cpp:541:10:541:10 | y |
| test.cpp:583:11:583:16 | call to source | test.cpp:590:8:590:8 | x |
| test.cpp:628:20:628:25 | ref arg buffer | test.cpp:629:17:629:22 | buffer |
| test.cpp:633:18:633:23 | call to source | test.cpp:634:8:634:8 | x |
| test.cpp:702:38:702:43 | source | test.cpp:695:8:695:10 | buf |
| test.cpp:726:11:726:16 | call to source | test.cpp:735:8:735:8 | x |
| test.cpp:733:7:733:7 | x | test.cpp:735:8:735:8 | x |
| test.cpp:749:27:749:32 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:751:27:751:32 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:753:32:753:37 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:755:32:755:37 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:769:27:769:32 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:771:27:771:32 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:773:32:773:37 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:775:32:775:37 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:788:31:788:36 | call to source | test.cpp:782:12:782:12 | x |
| test.cpp:790:31:790:36 | call to source | test.cpp:782:12:782:12 | x |
| test.cpp:797:22:797:28 | ref arg content | test.cpp:798:19:798:25 | content |
| test.cpp:842:11:842:16 | call to source | test.cpp:844:8:844:8 | y |
| test.cpp:846:13:846:27 | call to indirect_source | test.cpp:848:23:848:25 | rpx |
| true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x |
| true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x |
| true_upon_entry.cpp:33:11:33:16 | call to source | true_upon_entry.cpp:39:8:39:8 | x |
| true_upon_entry.cpp:43:11:43:16 | call to source | true_upon_entry.cpp:49:8:49:8 | x |
| true_upon_entry.cpp:54:11:54:16 | call to source | true_upon_entry.cpp:57:8:57:8 | x |
| true_upon_entry.cpp:70:11:70:16 | call to source | true_upon_entry.cpp:78:8:78:8 | x |
| true_upon_entry.cpp:83:11:83:16 | call to source | true_upon_entry.cpp:86:8:86:8 | x |
irFlow
| BarrierGuard.cpp:5:19:5:24 | source | BarrierGuard.cpp:9:10:9:15 | source |
| BarrierGuard.cpp:13:17:13:22 | source | BarrierGuard.cpp:15:10:15:15 | source |
| BarrierGuard.cpp:21:17:21:22 | source | BarrierGuard.cpp:25:10:25:15 | source |
| BarrierGuard.cpp:29:16:29:21 | source | BarrierGuard.cpp:31:10:31:15 | source |
| BarrierGuard.cpp:29:16:29:21 | source | BarrierGuard.cpp:33:10:33:15 | source |
| BarrierGuard.cpp:49:10:49:15 | call to source | BarrierGuard.cpp:53:13:53:13 | x |
| BarrierGuard.cpp:49:10:49:15 | call to source | BarrierGuard.cpp:55:13:55:13 | x |
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:64:14:64:14 | x |
| BarrierGuard.cpp:60:11:60:16 | call to source | BarrierGuard.cpp:66:14:66:14 | x |
| acrossLinkTargets.cpp:19:27:19:32 | call to source | acrossLinkTargets.cpp:12:8:12:8 | x |
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:18:8:18:19 | sourceArray1 |
| clang.cpp:12:9:12:20 | sourceArray1 | clang.cpp:23:17:23:29 | & ... indirection |
| clang.cpp:29:27:29:32 | call to source | clang.cpp:30:27:30:28 | m1 |
| clang.cpp:29:27:29:32 | call to source | clang.cpp:31:27:31:34 | call to getFirst |
| clang.cpp:35:32:35:37 | call to source | clang.cpp:38:10:38:11 | m2 |
| clang.cpp:40:42:40:47 | call to source | clang.cpp:42:18:42:19 | m2 |
| clang.cpp:44:35:44:40 | call to source | clang.cpp:46:17:46:18 | m2 |
| clang.cpp:50:7:50:16 | definition of stackArray | clang.cpp:52:8:52:17 | stackArray |
| clang.cpp:50:25:50:30 | call to source | clang.cpp:53:17:53:26 | stackArray indirection |
| clang.cpp:50:35:50:40 | call to source | clang.cpp:53:17:53:26 | stackArray indirection |
| clang.cpp:51:19:51:24 | call to source | clang.cpp:53:17:53:26 | stackArray indirection |
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:35:16:35:25 | call to notSource1 |
| dispatch.cpp:9:37:9:42 | call to source | dispatch.cpp:43:15:43:24 | call to notSource1 |
| dispatch.cpp:10:37:10:42 | call to source | dispatch.cpp:36:16:36:25 | call to notSource2 |
| dispatch.cpp:10:37:10:42 | call to source | dispatch.cpp:44:15:44:24 | call to notSource2 |
| dispatch.cpp:16:37:16:42 | call to source | dispatch.cpp:32:16:32:24 | call to isSource2 |
| dispatch.cpp:16:37:16:42 | call to source | dispatch.cpp:40:15:40:23 | call to isSource2 |
| dispatch.cpp:22:37:22:42 | call to source | dispatch.cpp:31:16:31:24 | call to isSource1 |
| dispatch.cpp:22:37:22:42 | call to source | dispatch.cpp:39:15:39:23 | call to isSource1 |
| dispatch.cpp:22:37:22:42 | call to source | dispatch.cpp:55:22:55:30 | call to isSource1 |
| dispatch.cpp:22:37:22:42 | call to source | dispatch.cpp:58:28:58:36 | call to isSource1 |
| dispatch.cpp:33:18:33:23 | call to source | dispatch.cpp:23:38:23:38 | x |
| dispatch.cpp:37:19:37:24 | call to source | dispatch.cpp:11:38:11:38 | x |
| dispatch.cpp:41:17:41:22 | call to source | dispatch.cpp:23:38:23:38 | x |
| dispatch.cpp:45:18:45:23 | call to source | dispatch.cpp:11:38:11:38 | x |
| dispatch.cpp:69:15:69:20 | call to source | dispatch.cpp:23:38:23:38 | x |
| dispatch.cpp:73:14:73:19 | call to source | dispatch.cpp:23:38:23:38 | x |
| dispatch.cpp:81:13:81:18 | call to source | dispatch.cpp:23:38:23:38 | x |
| dispatch.cpp:107:17:107:22 | call to source | dispatch.cpp:96:8:96:8 | x |
| dispatch.cpp:140:8:140:13 | call to source | dispatch.cpp:96:8:96:8 | x |
| dispatch.cpp:144:8:144:13 | call to source | dispatch.cpp:96:8:96:8 | x |
| flowOut.cpp:5:16:5:21 | call to source | flowOut.cpp:19:9:19:9 | x |
| globals.cpp:5:17:5:22 | call to source | globals.cpp:6:10:6:14 | local |
| globals.cpp:13:23:13:28 | call to source | globals.cpp:12:10:12:24 | flowTestGlobal1 |
| globals.cpp:23:23:23:28 | call to source | globals.cpp:19:10:19:24 | flowTestGlobal2 |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:14:8:14:8 | t |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:18:8:18:8 | call to operator() |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:21:8:21:8 | t |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:29:8:29:8 | t |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:35:8:35:8 | a |
| lambdas.cpp:8:10:8:15 | call to source | lambdas.cpp:41:8:41:8 | a |
| lambdas.cpp:43:7:43:12 | call to source | lambdas.cpp:46:7:46:7 | w |
| ref.cpp:29:11:29:16 | call to source | ref.cpp:62:10:62:11 | x3 |
| ref.cpp:53:9:53:10 | definition of x1 | ref.cpp:56:10:56:11 | x1 |
| ref.cpp:53:13:53:14 | definition of x2 | ref.cpp:59:10:59:11 | x2 |
| ref.cpp:53:17:53:18 | definition of x3 | ref.cpp:62:10:62:11 | x3 |
| ref.cpp:53:21:53:22 | definition of x4 | ref.cpp:65:10:65:11 | x4 |
| ref.cpp:55:23:55:28 | call to source | ref.cpp:56:10:56:11 | x1 |
| ref.cpp:94:15:94:20 | call to source | ref.cpp:129:13:129:15 | val |
| ref.cpp:109:15:109:20 | call to source | ref.cpp:132:13:132:15 | val |
| ref.cpp:122:23:122:28 | call to source | ref.cpp:123:13:123:15 | val |
| ref.cpp:125:19:125:24 | call to source | ref.cpp:126:13:126:15 | val |
| self-Iterator.cpp:19:23:19:30 | call to source | self-Iterator.cpp:20:10:20:10 | x |
| test.cpp:6:12:6:17 | call to source | test.cpp:7:8:7:9 | t1 |
| test.cpp:6:12:6:17 | call to source | test.cpp:9:8:9:9 | t1 |
| test.cpp:6:12:6:17 | call to source | test.cpp:10:8:10:9 | t2 |
| test.cpp:6:12:6:17 | call to source | test.cpp:15:8:15:9 | t2 |
| test.cpp:6:12:6:17 | call to source | test.cpp:26:8:26:9 | t1 |
| test.cpp:35:10:35:15 | call to source | test.cpp:30:8:30:8 | t |
| test.cpp:36:13:36:18 | call to source | test.cpp:31:8:31:8 | c |
| test.cpp:50:14:50:19 | call to source | test.cpp:58:10:58:10 | t |
| test.cpp:66:30:66:36 | source1 | test.cpp:71:8:71:9 | x4 |
| test.cpp:75:7:75:8 | definition of u1 | test.cpp:76:8:76:9 | u1 |
| test.cpp:83:7:83:8 | definition of u2 | test.cpp:84:8:84:18 | ... ? ... : ... |
| test.cpp:83:7:83:8 | definition of u2 | test.cpp:86:8:86:9 | i1 |
| test.cpp:89:28:89:34 | source1 indirection | test.cpp:90:8:90:14 | source1 |
| test.cpp:100:13:100:18 | call to source | test.cpp:103:10:103:12 | ref |
| test.cpp:138:27:138:32 | call to source | test.cpp:140:8:140:8 | y |
| test.cpp:151:33:151:38 | call to source | test.cpp:144:8:144:8 | s |
| test.cpp:151:33:151:38 | call to source | test.cpp:152:8:152:8 | y |
| test.cpp:164:34:164:39 | call to source | test.cpp:157:8:157:8 | x |
| test.cpp:164:34:164:39 | call to source | test.cpp:165:8:165:8 | y |
| test.cpp:171:11:171:16 | call to source | test.cpp:178:8:178:8 | y |
| test.cpp:245:14:245:19 | call to source | test.cpp:260:12:260:12 | x |
| test.cpp:265:22:265:27 | call to source | test.cpp:266:12:266:12 | x |
| test.cpp:305:17:305:22 | call to source | test.cpp:289:14:289:14 | x |
| test.cpp:314:4:314:9 | call to source | test.cpp:318:7:318:7 | x |
| test.cpp:333:17:333:22 | call to source | test.cpp:337:10:337:18 | globalVar |
| test.cpp:333:17:333:22 | call to source | test.cpp:339:10:339:18 | globalVar |
| test.cpp:333:17:333:22 | call to source | test.cpp:343:10:343:18 | globalVar |
| test.cpp:333:17:333:22 | call to source | test.cpp:349:10:349:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:337:10:337:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:339:10:339:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:343:10:343:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:349:10:349:18 | globalVar |
| test.cpp:359:13:359:18 | call to source | test.cpp:365:10:365:14 | field |
| test.cpp:373:13:373:18 | call to source | test.cpp:369:10:369:14 | field |
| test.cpp:373:13:373:18 | call to source | test.cpp:375:10:375:14 | field |
| test.cpp:382:48:382:54 | source1 | test.cpp:385:8:385:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:392:8:392:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:394:10:394:12 | tmp |
| test.cpp:399:7:399:9 | definition of tmp | test.cpp:401:8:401:10 | tmp |
| test.cpp:405:7:405:9 | definition of tmp | test.cpp:408:8:408:10 | tmp |
| test.cpp:416:7:416:11 | definition of local | test.cpp:418:8:418:12 | local |
| test.cpp:417:16:417:20 | intRefSource output argument | test.cpp:418:8:418:12 | local |
| test.cpp:422:7:422:11 | definition of local | test.cpp:424:8:424:12 | local |
| test.cpp:423:20:423:25 | intPointerSource output argument | test.cpp:424:8:424:12 | local |
| test.cpp:433:7:433:11 | definition of local | test.cpp:435:8:435:12 | local |
| test.cpp:434:20:434:24 | intPointerSource output argument | test.cpp:436:8:436:13 | * ... |
| test.cpp:440:7:440:11 | definition of local | test.cpp:442:8:442:12 | local |
| test.cpp:441:18:441:23 | intArraySource output argument | test.cpp:442:8:442:12 | local |
| test.cpp:448:7:448:11 | definition of local | test.cpp:450:8:450:12 | local |
| test.cpp:449:18:449:22 | intArraySource output argument | test.cpp:451:8:451:13 | * ... |
| test.cpp:456:26:456:32 | source1 | test.cpp:457:9:457:22 | (statement expression) |
| test.cpp:456:26:456:32 | source1 | test.cpp:468:8:468:12 | local |
| test.cpp:472:8:472:13 | call to source | test.cpp:478:8:478:8 | x |
| test.cpp:506:8:506:13 | call to source | test.cpp:513:8:513:8 | x |
| test.cpp:519:19:519:24 | call to source | test.cpp:521:8:521:20 | access to array |
| test.cpp:531:29:531:34 | call to source | test.cpp:532:8:532:9 | * ... |
| test.cpp:547:9:547:9 | definition of x | test.cpp:536:10:536:11 | * ... |
| test.cpp:551:9:551:9 | definition of y | test.cpp:541:10:541:10 | y |
| test.cpp:562:17:562:31 | call to indirect_source indirection | test.cpp:566:10:566:19 | * ... |
| test.cpp:562:17:562:31 | call to indirect_source indirection | test.cpp:568:10:568:19 | * ... |
| test.cpp:562:17:562:31 | call to indirect_source indirection | test.cpp:572:10:572:19 | * ... |
| test.cpp:562:17:562:31 | call to indirect_source indirection | test.cpp:578:10:578:19 | * ... |
| test.cpp:576:17:576:31 | call to indirect_source indirection | test.cpp:566:10:566:19 | * ... |
| test.cpp:576:17:576:31 | call to indirect_source indirection | test.cpp:568:10:568:19 | * ... |
| test.cpp:576:17:576:31 | call to indirect_source indirection | test.cpp:572:10:572:19 | * ... |
| test.cpp:576:17:576:31 | call to indirect_source indirection | test.cpp:578:10:578:19 | * ... |
| test.cpp:594:12:594:26 | call to indirect_source indirection | test.cpp:597:8:597:13 | * ... |
| test.cpp:601:20:601:20 | intPointerSource output argument | test.cpp:603:8:603:9 | * ... |
| test.cpp:607:20:607:20 | intPointerSource output argument | test.cpp:609:8:609:9 | * ... |
| test.cpp:614:20:614:20 | intPointerSource output argument | test.cpp:616:8:616:17 | * ... |
| test.cpp:628:20:628:25 | intPointerSource output argument | test.cpp:629:17:629:22 | buffer indirection |
| test.cpp:633:18:633:23 | call to source | test.cpp:634:8:634:8 | x |
| test.cpp:646:7:646:12 | call to source | test.cpp:645:8:645:8 | x |
| test.cpp:660:7:660:12 | call to source | test.cpp:658:8:658:8 | x |
| test.cpp:664:18:664:23 | call to source | test.cpp:666:8:666:16 | * ... |
| test.cpp:681:7:681:12 | call to source | test.cpp:679:8:679:16 | * ... |
| test.cpp:733:7:733:7 | definition of x | test.cpp:735:8:735:8 | x |
| test.cpp:751:27:751:32 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:753:32:753:37 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:755:32:755:37 | call to source | test.cpp:740:10:740:10 | x |
| test.cpp:771:27:771:32 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:773:32:773:37 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:775:32:775:37 | call to source | test.cpp:760:10:760:10 | x |
| test.cpp:788:31:788:36 | call to source | test.cpp:782:12:782:12 | x |
| test.cpp:790:31:790:36 | call to source | test.cpp:782:12:782:12 | x |
| test.cpp:797:22:797:28 | intPointerSource output argument | test.cpp:798:19:798:25 | content indirection |
| test.cpp:808:25:808:39 | call to indirect_source indirection | test.cpp:813:19:813:35 | * ... indirection |
| test.cpp:818:26:818:31 | call to source | test.cpp:823:10:823:27 | * ... |
| test.cpp:832:21:832:26 | call to source | test.cpp:836:10:836:22 | global_direct |
| test.cpp:842:11:842:16 | call to source | test.cpp:844:8:844:8 | y |
| test.cpp:846:13:846:27 | call to indirect_source indirection | test.cpp:848:17:848:25 | rpx indirection |
| true_upon_entry.cpp:9:11:9:16 | call to source | true_upon_entry.cpp:13:8:13:8 | x |
| true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x |
| true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x |
| true_upon_entry.cpp:33:11:33:16 | call to source | true_upon_entry.cpp:39:8:39:8 | x |
| true_upon_entry.cpp:43:11:43:16 | call to source | true_upon_entry.cpp:49:8:49:8 | x |
| true_upon_entry.cpp:54:11:54:16 | call to source | true_upon_entry.cpp:57:8:57:8 | x |
| true_upon_entry.cpp:62:11:62:16 | call to source | true_upon_entry.cpp:66:8:66:8 | x |
| true_upon_entry.cpp:70:11:70:16 | call to source | true_upon_entry.cpp:78:8:78:8 | x |
| true_upon_entry.cpp:83:11:83:16 | call to source | true_upon_entry.cpp:86:8:86:8 | x |
| true_upon_entry.cpp:98:11:98:16 | call to source | true_upon_entry.cpp:105:8:105:8 | x |

View File

@@ -0,0 +1,9 @@
import TestBase
query predicate astFlow(AstTest::DataFlow::Node source, AstTest::DataFlow::Node sink) {
AstTest::AstFlow::flow(source, sink)
}
query predicate irFlow(IRTest::DataFlow::Node source, IRTest::DataFlow::Node sink) {
IRTest::IRFlow::flow(source, sink)
}

View File

@@ -836,4 +836,14 @@ namespace MoreGlobalTests {
sink(global_direct); // $ ir MISSING: ast sink(global_direct); // $ ir MISSING: ast
indirect_sink(global_direct); // clean indirect_sink(global_direct); // clean
} }
}
void test_references() {
int x = source();
int &y = x;
sink(y); // $ ast,ir
int* px = indirect_source();
int*& rpx = px;
indirect_sink((int*)rpx); // $ ast,ir
} }

View File

@@ -1,9 +1,2 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:19,45-53)
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:20,24-32)
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:27,15-23)
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:33,22-30)
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:40,25-33)
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:42,17-25)
WARNING: Module DataFlow has been deprecated and may be removed in future (test.ql:46,20-28)
testFailures testFailures
failures failures

View File

@@ -1,107 +1,3 @@
import TestBase
import TestUtilities.dataflow.FlowTestCommon import TestUtilities.dataflow.FlowTestCommon
module AstTest {
private import semmle.code.cpp.dataflow.DataFlow
private import semmle.code.cpp.controlflow.Guards
/**
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
* S in `if (guarded(x)) S`.
*/
// This is tested in `BarrierGuard.cpp`.
predicate testBarrierGuard(GuardCondition g, Expr checked, boolean isTrue) {
g.(FunctionCall).getTarget().getName() = "guarded" and
checked = g.(FunctionCall).getArgument(0) and
isTrue = true
}
/** Common data flow configuration to be used by tests. */
module AstTestAllocationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asParameter().getName().matches("source%")
or
source.asExpr().(FunctionCall).getTarget().getName() = "indirect_source"
or
source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%")
or
// Track uninitialized variables
exists(source.asUninitialized())
}
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call |
call.getTarget().getName() = ["sink", "indirect_sink"] and
sink.asExpr() = call.getAnArgument()
)
}
predicate isBarrier(DataFlow::Node barrier) {
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
}
}
module AstFlow = DataFlow::Global<AstTestAllocationConfig>;
}
module IRTest {
private import cpp
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.controlflow.IRGuards
/**
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
* S in `if (guarded(x)) S`.
*/
// This is tested in `BarrierGuard.cpp`.
predicate testBarrierGuard(IRGuardCondition g, Expr checked, boolean isTrue) {
exists(Call call |
call = g.getUnconvertedResultExpression() and
call.getTarget().hasName("guarded") and
checked = call.getArgument(0) and
isTrue = true
)
}
/** Common data flow configuration to be used by tests. */
module IRTestAllocationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asIndirectExpr(1).(FunctionCall).getTarget().getName() = "indirect_source"
or
source.asParameter().getName().matches("source%")
or
source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%")
or
exists(source.asUninitialized())
}
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call, Expr e | e = call.getAnArgument() |
call.getTarget().getName() = "sink" and
sink.asExpr() = e
or
call.getTarget().getName() = "indirect_sink" and
sink.asIndirectExpr() = e
)
}
predicate isBarrier(DataFlow::Node barrier) {
exists(Expr barrierExpr | barrierExpr in [barrier.asExpr(), barrier.asIndirectExpr()] |
barrierExpr.(VariableAccess).getTarget().hasName("barrier")
)
or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
or
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getAnIndirectBarrierNode()
}
}
module IRFlow = DataFlow::Global<IRTestAllocationConfig>;
}
import MakeTest<MergeTests<AstFlowTest<AstTest::AstFlow>, IRFlowTest<IRTest::IRFlow>>> import MakeTest<MergeTests<AstFlowTest<AstTest::AstFlow>, IRFlowTest<IRTest::IRFlow>>>

View File

@@ -5,7 +5,6 @@ edges
| test.cpp:43:18:43:34 | call to getenv indirection | test.cpp:29:30:29:36 | command indirection | | test.cpp:43:18:43:34 | call to getenv indirection | test.cpp:29:30:29:36 | command indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | (reference dereference) indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection |
| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection |
| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer indirection | | test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer indirection |
@@ -22,7 +21,6 @@ nodes
| test.cpp:56:12:56:17 | fgets output argument | semmle.label | fgets output argument | | test.cpp:56:12:56:17 | fgets output argument | semmle.label | fgets output argument |
| test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection | | test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection |
| test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection | | test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection |
| test.cpp:64:10:64:16 | (reference dereference) indirection | semmle.label | (reference dereference) indirection |
| test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection | | test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection |
| test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection | | test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection |
| test.cpp:76:12:76:17 | fgets output argument | semmle.label | fgets output argument | | test.cpp:76:12:76:17 | fgets output argument | semmle.label | fgets output argument |
@@ -39,7 +37,6 @@ subpaths
| test.cpp:31:10:31:16 | command indirection | test.cpp:43:18:43:34 | call to getenv indirection | test.cpp:31:10:31:16 | command indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:43:18:43:34 | call to getenv indirection | an environment variable | | test.cpp:31:10:31:16 | command indirection | test.cpp:43:18:43:34 | call to getenv indirection | test.cpp:31:10:31:16 | command indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:43:18:43:34 | call to getenv indirection | an environment variable |
| test.cpp:62:10:62:15 | buffer indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets | | test.cpp:62:10:62:15 | buffer indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:63:10:63:13 | data indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets | | test.cpp:63:10:63:13 | data indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:64:10:64:16 | (reference dereference) indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | (reference dereference) indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:64:10:64:16 | dataref indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets | | test.cpp:64:10:64:16 | dataref indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:65:10:65:14 | data2 indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets | | test.cpp:65:10:65:14 | data2 indirection | test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:56:12:56:17 | fgets output argument | string read by fgets |
| test.cpp:78:10:78:15 | buffer indirection | test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:76:12:76:17 | fgets output argument | string read by fgets | | test.cpp:78:10:78:15 | buffer indirection | test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer indirection | The value of this argument may come from $@ and is being passed to system. | test.cpp:76:12:76:17 | fgets output argument | string read by fgets |