Merge commit '52d8acc1a198c5ea29c1dddceda1d6c0fb75de14' into dataflow-defbyref-to-field

This is a partial merge from master. In particular, it takes in #3382
and #3385.
This commit is contained in:
Jonas Jensen
2020-05-07 16:46:11 +02:00
71 changed files with 1816 additions and 1119 deletions

View File

@@ -21,7 +21,7 @@ where
destBase = baseType(destType) and
destBase.getSize() != sourceBase.getSize() and
not dest.isInMacroExpansion() and
// If the source type is a char* or void* then don't
// If the source type is a `char*` or `void*` then don't
// produce a result, because it is likely to be a false
// positive.
not sourceBase instanceof CharType and

View File

@@ -21,7 +21,7 @@ where
destBase = baseType(destType) and
destBase.getSize() != sourceBase.getSize() and
not dest.isInMacroExpansion() and
// If the source type is a char* or void* then don't
// If the source type is a `char*` or `void*` then don't
// produce a result, because it is likely to be a false
// positive.
not sourceBase instanceof CharType and

View File

@@ -24,7 +24,7 @@ private predicate isCharSzPtrExpr(Expr e) {
from Expr sizeofExpr, Expr e
where
// If we see an addWithSizeof then we expect the type of
// the pointer expression to be char* or void*. Otherwise it
// the pointer expression to be `char*` or `void*`. Otherwise it
// is probably a mistake.
addWithSizeof(e, sizeofExpr, _) and not isCharSzPtrExpr(e)
select sizeofExpr,

View File

@@ -103,6 +103,9 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
/**
* Holds if this function is declared to be `constexpr`.
*
* Note that this does not hold if the function has been declared
* `consteval`.
*/
predicate isDeclaredConstexpr() { this.hasSpecifier("declared_constexpr") }
@@ -115,9 +118,16 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* template <typename T> constexpr int g(T x) { return f(x); }
* ```
* `g<int>` is declared constexpr, but is not constexpr.
*
* Will also hold if this function is `consteval`.
*/
predicate isConstexpr() { this.hasSpecifier("is_constexpr") }
/**
* Holds if this function is declared to be `consteval`.
*/
predicate isConsteval() { this.hasSpecifier("is_consteval") }
/**
* Holds if this function is declared with `__attribute__((naked))` or
* `__declspec(naked)`.

View File

@@ -92,13 +92,7 @@ int getBufferSize(Expr bufferExpr, Element why) {
// dataflow (all sources must be the same size)
bufferExprNode = DataFlow::exprNode(bufferExpr) and
result =
min(Expr def |
DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode)
|
getBufferSize(def, _)
) and
result =
max(Expr def |
unique(Expr def |
DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode)
|
getBufferSize(def, _)

View File

@@ -532,13 +532,7 @@ library class ExprEvaluator extends int {
interestingVariableAccess(e, va, v, true) and
// All assignments must have the same int value
result =
min(Expr value |
value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value)
|
getValueInternalNonSubExpr(value)
) and
result =
max(Expr value |
unique(Expr value |
value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value)
|
getValueInternalNonSubExpr(value)

View File

@@ -183,11 +183,14 @@ private predicate referenceFromVariableAccess(VariableAccess va, Expr reference)
)
}
private predicate valueMayEscapeAt(Expr e) {
private predicate addressMayEscapeAt(Expr e) {
exists(Call call |
e = call.getAnArgument().getFullyConverted() and
not stdIdentityFunction(call.getTarget()) and
not stdAddressOf(call.getTarget())
or
e = call.getQualifier().getFullyConverted() and
e.getUnderlyingType() instanceof PointerType
)
or
exists(AssignExpr assign | e = assign.getRValue().getFullyConverted())
@@ -205,8 +208,8 @@ private predicate valueMayEscapeAt(Expr e) {
exists(AsmStmt asm | e = asm.getAChild().(Expr).getFullyConverted())
}
private predicate valueMayEscapeMutablyAt(Expr e) {
valueMayEscapeAt(e) and
private predicate addressMayEscapeMutablyAt(Expr e) {
addressMayEscapeAt(e) and
exists(Type t | t = e.getType().getUnderlyingType() |
exists(PointerType pt |
pt = t
@@ -225,6 +228,22 @@ private predicate valueMayEscapeMutablyAt(Expr e) {
)
}
private predicate lvalueMayEscapeAt(Expr e) {
// A call qualifier, like `q` in `q.f()`, is special in that the address of
// `q` escapes even though `q` is not a pointer or a reference.
exists(Call call |
e = call.getQualifier().getFullyConverted() and
e.getType().getUnspecifiedType() instanceof Class
)
}
private predicate lvalueMayEscapeMutablyAt(Expr e) {
lvalueMayEscapeAt(e) and
// A qualifier of a call to a const member function is converted to a const
// class type.
not e.getType().isConst()
}
private predicate addressFromVariableAccess(VariableAccess va, Expr e) {
pointerFromVariableAccess(va, e)
or
@@ -271,8 +290,11 @@ private module EscapesTree_Cached {
*/
cached
predicate variableAddressEscapesTree(VariableAccess va, Expr e) {
valueMayEscapeAt(e) and
addressMayEscapeAt(e) and
addressFromVariableAccess(va, e)
or
lvalueMayEscapeAt(e) and
lvalueFromVariableAccess(va, e)
}
/**
@@ -301,8 +323,11 @@ private module EscapesTree_Cached {
*/
cached
predicate variableAddressEscapesTreeNonConst(VariableAccess va, Expr e) {
valueMayEscapeMutablyAt(e) and
addressMayEscapeMutablyAt(e) and
addressFromVariableAccess(va, e)
or
lvalueMayEscapeMutablyAt(e) and
lvalueFromVariableAccess(va, e)
}
/**

View File

@@ -505,8 +505,6 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
// Expr -> Expr
exprToExprStep_nocfg(nodeFrom.asExpr(), nodeTo.asExpr())
or
exprToExprStep_nocfg(nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr(), nodeTo.asExpr())
or
// Node -> FlowVar -> VariableAccess
exists(FlowVar var |
(
@@ -674,7 +672,7 @@ private module FieldFlow {
exists(FieldConfiguration cfg | cfg.hasFlow(node1, node2)) and
// This configuration should not be able to cross function boundaries, but
// we double-check here just to be sure.
node1.getFunction() = node2.getFunction()
node1.getEnclosingCallable() = node2.getEnclosingCallable()
}
}

View File

@@ -9,9 +9,8 @@ private import semmle.code.cpp.dataflow.EscapesTree
*/
abstract class Call extends Expr, NameQualifiableElement {
/**
* Gets the number of actual parameters in this call; use
* `getArgument(i)` with `i` between `0` and `result - 1` to
* retrieve actuals.
* Gets the number of arguments (actual parameters) of this call. The count
* does _not_ include the qualifier of the call, if any.
*/
int getNumberOfArguments() { result = count(this.getAnArgument()) }
@@ -32,21 +31,24 @@ abstract class Call extends Expr, NameQualifiableElement {
Expr getQualifier() { result = this.getChild(-1) }
/**
* Gets an argument for this call.
* Gets an argument for this call. To get the qualifier of this call, if
* any, use `getQualifier()`.
*/
Expr getAnArgument() { exists(int i | result = this.getChild(i) and i >= 0) }
/**
* Gets the nth argument for this call.
*
* The range of `n` is from `0` to `getNumberOfArguments() - 1`.
* The range of `n` is from `0` to `getNumberOfArguments() - 1`. To get the
* qualifier of this call, if any, use `getQualifier()`.
*/
Expr getArgument(int n) { result = this.getChild(n) and n >= 0 }
/**
* Gets a sub expression of the argument at position `index`. If the
* Gets a subexpression of the argument at position `index`. If the
* argument itself contains calls, such calls will be considered
* leafs in the expression tree.
* leaves in the expression tree. The qualifier of the call, if any, is not
* considered to be an argument.
*
* Example: the call `f(2, 3 + 4, g(4 + 5))` has sub expression(s)
* `2` at index 0; `3`, `4`, and `3 + 4` at index 1; and `g(4 + 5)`

View File

@@ -101,23 +101,24 @@ class IRBlock extends IRBlockBase {
private predicate startsBasicBlock(Instruction instr) {
not instr instanceof PhiInstruction and
(
count(Instruction predecessor | instr = predecessor.getASuccessor()) != 1 // Multiple predecessors or no predecessor
or
exists(Instruction predecessor |
instr = predecessor.getASuccessor() and
strictcount(Instruction other | other = predecessor.getASuccessor()) > 1
) // Predecessor has multiple successors
or
exists(Instruction predecessor, EdgeKind kind |
instr = predecessor.getSuccessor(kind) and
not kind instanceof GotoEdge
) // Incoming edge is not a GotoEdge
or
exists(Instruction predecessor |
instr = Construction::getInstructionBackEdgeSuccessor(predecessor, _)
) // A back edge enters this instruction
)
not adjacentInBlock(_, instr)
}
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
// - i2 must be the only successor of i1
i2 = unique(Instruction i | i = i1.getASuccessor()) and
// - i1 must be the only predecessor of i2
i1 = unique(Instruction i | i.getASuccessor() = i2) and
// - The edge between the two must be a GotoEdge. We just check that one
// exists since we've already checked that it's unique.
exists(GotoEdge edgeKind | exists(i1.getSuccessor(edgeKind))) and
// - The edge must not be a back edge. This means we get the same back edges
// in the basic-block graph as we do in the raw CFG.
not exists(Construction::getInstructionBackEdgeSuccessor(i1, _))
// This predicate could be simplified to remove one of the `unique`s if we
// were willing to rely on the CFG being well-formed and thus never having
// more than one successor to an instruction that has a `GotoEdge` out of it.
}
private predicate isEntryBlock(TIRBlock block) {
@@ -129,12 +130,6 @@ private module Cached {
cached
newtype TIRBlock = MkIRBlock(Instruction firstInstr) { startsBasicBlock(firstInstr) }
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
exists(GotoEdge edgeKind | i2 = i1.getSuccessor(edgeKind)) and
not startsBasicBlock(i2)
}
/** Holds if `i` is the `index`th instruction the block starting with `first`. */
private Instruction getInstructionFromFirst(Instruction first, int index) =
shortestDistances(startsBasicBlock/1, adjacentInBlock/2)(first, result, index)

View File

@@ -190,14 +190,15 @@ class Instruction extends Construction::TInstruction {
final Language::Location getLocation() { result = getAST().getLocation() }
/**
* Gets the `Expr` whose result is computed by this instruction, if any.
* Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a
* conversion.
*/
final Language::Expr getConvertedResultExpression() {
result = Construction::getInstructionConvertedResultExpression(this)
}
/**
* Gets the unconverted `Expr` whose result is computed by this instruction, if any.
* Gets the unconverted form of the `Expr` whose result is computed by this instruction, if any.
*/
final Language::Expr getUnconvertedResultExpression() {
result = Construction::getInstructionUnconvertedResultExpression(this)

View File

@@ -14,8 +14,7 @@ int getConstantValue(Instruction instr) {
or
exists(PhiInstruction phi |
phi = instr and
result = max(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef())) and
result = min(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
result = unique(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
)
}

View File

@@ -101,23 +101,24 @@ class IRBlock extends IRBlockBase {
private predicate startsBasicBlock(Instruction instr) {
not instr instanceof PhiInstruction and
(
count(Instruction predecessor | instr = predecessor.getASuccessor()) != 1 // Multiple predecessors or no predecessor
or
exists(Instruction predecessor |
instr = predecessor.getASuccessor() and
strictcount(Instruction other | other = predecessor.getASuccessor()) > 1
) // Predecessor has multiple successors
or
exists(Instruction predecessor, EdgeKind kind |
instr = predecessor.getSuccessor(kind) and
not kind instanceof GotoEdge
) // Incoming edge is not a GotoEdge
or
exists(Instruction predecessor |
instr = Construction::getInstructionBackEdgeSuccessor(predecessor, _)
) // A back edge enters this instruction
)
not adjacentInBlock(_, instr)
}
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
// - i2 must be the only successor of i1
i2 = unique(Instruction i | i = i1.getASuccessor()) and
// - i1 must be the only predecessor of i2
i1 = unique(Instruction i | i.getASuccessor() = i2) and
// - The edge between the two must be a GotoEdge. We just check that one
// exists since we've already checked that it's unique.
exists(GotoEdge edgeKind | exists(i1.getSuccessor(edgeKind))) and
// - The edge must not be a back edge. This means we get the same back edges
// in the basic-block graph as we do in the raw CFG.
not exists(Construction::getInstructionBackEdgeSuccessor(i1, _))
// This predicate could be simplified to remove one of the `unique`s if we
// were willing to rely on the CFG being well-formed and thus never having
// more than one successor to an instruction that has a `GotoEdge` out of it.
}
private predicate isEntryBlock(TIRBlock block) {
@@ -129,12 +130,6 @@ private module Cached {
cached
newtype TIRBlock = MkIRBlock(Instruction firstInstr) { startsBasicBlock(firstInstr) }
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
exists(GotoEdge edgeKind | i2 = i1.getSuccessor(edgeKind)) and
not startsBasicBlock(i2)
}
/** Holds if `i` is the `index`th instruction the block starting with `first`. */
private Instruction getInstructionFromFirst(Instruction first, int index) =
shortestDistances(startsBasicBlock/1, adjacentInBlock/2)(first, result, index)

View File

@@ -190,14 +190,15 @@ class Instruction extends Construction::TInstruction {
final Language::Location getLocation() { result = getAST().getLocation() }
/**
* Gets the `Expr` whose result is computed by this instruction, if any.
* Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a
* conversion.
*/
final Language::Expr getConvertedResultExpression() {
result = Construction::getInstructionConvertedResultExpression(this)
}
/**
* Gets the unconverted `Expr` whose result is computed by this instruction, if any.
* Gets the unconverted form of the `Expr` whose result is computed by this instruction, if any.
*/
final Language::Expr getUnconvertedResultExpression() {
result = Construction::getInstructionUnconvertedResultExpression(this)

View File

@@ -14,8 +14,7 @@ int getConstantValue(Instruction instr) {
or
exists(PhiInstruction phi |
phi = instr and
result = max(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef())) and
result = min(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
result = unique(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
)
}

View File

@@ -101,23 +101,24 @@ class IRBlock extends IRBlockBase {
private predicate startsBasicBlock(Instruction instr) {
not instr instanceof PhiInstruction and
(
count(Instruction predecessor | instr = predecessor.getASuccessor()) != 1 // Multiple predecessors or no predecessor
or
exists(Instruction predecessor |
instr = predecessor.getASuccessor() and
strictcount(Instruction other | other = predecessor.getASuccessor()) > 1
) // Predecessor has multiple successors
or
exists(Instruction predecessor, EdgeKind kind |
instr = predecessor.getSuccessor(kind) and
not kind instanceof GotoEdge
) // Incoming edge is not a GotoEdge
or
exists(Instruction predecessor |
instr = Construction::getInstructionBackEdgeSuccessor(predecessor, _)
) // A back edge enters this instruction
)
not adjacentInBlock(_, instr)
}
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
// - i2 must be the only successor of i1
i2 = unique(Instruction i | i = i1.getASuccessor()) and
// - i1 must be the only predecessor of i2
i1 = unique(Instruction i | i.getASuccessor() = i2) and
// - The edge between the two must be a GotoEdge. We just check that one
// exists since we've already checked that it's unique.
exists(GotoEdge edgeKind | exists(i1.getSuccessor(edgeKind))) and
// - The edge must not be a back edge. This means we get the same back edges
// in the basic-block graph as we do in the raw CFG.
not exists(Construction::getInstructionBackEdgeSuccessor(i1, _))
// This predicate could be simplified to remove one of the `unique`s if we
// were willing to rely on the CFG being well-formed and thus never having
// more than one successor to an instruction that has a `GotoEdge` out of it.
}
private predicate isEntryBlock(TIRBlock block) {
@@ -129,12 +130,6 @@ private module Cached {
cached
newtype TIRBlock = MkIRBlock(Instruction firstInstr) { startsBasicBlock(firstInstr) }
/** Holds if `i2` follows `i1` in a `IRBlock`. */
private predicate adjacentInBlock(Instruction i1, Instruction i2) {
exists(GotoEdge edgeKind | i2 = i1.getSuccessor(edgeKind)) and
not startsBasicBlock(i2)
}
/** Holds if `i` is the `index`th instruction the block starting with `first`. */
private Instruction getInstructionFromFirst(Instruction first, int index) =
shortestDistances(startsBasicBlock/1, adjacentInBlock/2)(first, result, index)

View File

@@ -190,14 +190,15 @@ class Instruction extends Construction::TInstruction {
final Language::Location getLocation() { result = getAST().getLocation() }
/**
* Gets the `Expr` whose result is computed by this instruction, if any.
* Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a
* conversion.
*/
final Language::Expr getConvertedResultExpression() {
result = Construction::getInstructionConvertedResultExpression(this)
}
/**
* Gets the unconverted `Expr` whose result is computed by this instruction, if any.
* Gets the unconverted form of the `Expr` whose result is computed by this instruction, if any.
*/
final Language::Expr getUnconvertedResultExpression() {
result = Construction::getInstructionUnconvertedResultExpression(this)

View File

@@ -14,8 +14,7 @@ int getConstantValue(Instruction instr) {
or
exists(PhiInstruction phi |
phi = instr and
result = max(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef())) and
result = min(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
result = unique(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
)
}

View File

@@ -271,33 +271,32 @@ class OperatorNewAllocationFunction extends AllocationFunction {
}
/**
* The predicate analyzes a `sizeExpr`, which is an argument to an allocation
* function like malloc, and tries to split it into an expression `lengthExpr`
* that describes the length of the allocated array, and the size of the allocated
* element type `sizeof`.
* If this is not possible, the allocation is considered to be of size 1 and of
* length `sizeExpr`.
* Holds if `sizeExpr` is an expression consisting of a subexpression
* `lengthExpr` multiplied by a constant `sizeof` that is the result of a
* `sizeof()` expression. Alternatively if there isn't a suitable `sizeof()`
* expression, `lengthExpr = sizeExpr` and `sizeof = 1`. For example:
* ```
* malloc(a * 2 * sizeof(char32_t));
* ```
* In this case if the `sizeExpr` is the argument to `malloc`, the `lengthExpr`
* is `a * 2` and `sizeof` is `4`.
*/
private predicate deconstructSizeExpr(Expr sizeExpr, Expr lengthExpr, int sizeof) {
if
sizeExpr instanceof MulExpr and
exists(SizeofOperator sizeofOp, Expr lengthOp |
sizeofOp = sizeExpr.(MulExpr).getAnOperand() and
lengthOp = sizeExpr.(MulExpr).getAnOperand() and
not lengthOp instanceof SizeofOperator and
exists(sizeofOp.getValue().toInt())
)
then
exists(SizeofOperator sizeofOp |
sizeofOp = sizeExpr.(MulExpr).getAnOperand() and
lengthExpr = sizeExpr.(MulExpr).getAnOperand() and
not lengthExpr instanceof SizeofOperator and
sizeof = sizeofOp.getValue().toInt()
)
else (
lengthExpr = sizeExpr and
sizeof = 1
exists(SizeofOperator sizeofOp |
sizeofOp = sizeExpr.(MulExpr).getAnOperand() and
lengthExpr = sizeExpr.(MulExpr).getAnOperand() and
not lengthExpr instanceof SizeofOperator and
sizeof = sizeofOp.getValue().toInt()
)
or
not exists(SizeofOperator sizeofOp, Expr lengthOp |
sizeofOp = sizeExpr.(MulExpr).getAnOperand() and
lengthOp = sizeExpr.(MulExpr).getAnOperand() and
not lengthOp instanceof SizeofOperator and
exists(sizeofOp.getValue().toInt())
) and
lengthExpr = sizeExpr and
sizeof = 1
}
/**

View File

@@ -0,0 +1,9 @@
struct S1 {
[[deprecated]] int a;
int b;
};
struct S2 {
int x;
[[deprecated, gnu::unused]] int b;
};

View File

@@ -0,0 +1,3 @@
| field_attributes.cpp:2:22:2:22 | a | field_attributes.cpp:2:5:2:14 | deprecated |
| field_attributes.cpp:8:35:8:35 | b | field_attributes.cpp:8:5:8:14 | deprecated |
| field_attributes.cpp:8:35:8:35 | b | field_attributes.cpp:8:17:8:27 | unused |

View File

@@ -0,0 +1,3 @@
import cpp
select any(Variable v) as v, v.getAnAttribute()

View File

@@ -3,6 +3,7 @@
| ms_var_attributes.cpp:7:5:7:10 | myInt2 | ms_var_attributes.h:4:1:4:9 | dllexport |
| ms_var_attributes.cpp:8:15:8:20 | myInt4 | ms_var_attributes.cpp:8:1:8:9 | dllexport |
| ms_var_attributes.cpp:9:5:9:10 | myInt5 | ms_var_attributes.h:7:1:7:9 | dllexport |
| ms_var_attributes.cpp:12:42:12:46 | field | ms_var_attributes.cpp:12:14:12:21 | property |
| ms_var_attributes.h:5:22:5:27 | myInt3 | ms_var_attributes.h:5:1:5:9 | dllexport |
| var_attributes.c:1:12:1:19 | weak_var | var_attributes.c:1:36:1:39 | weak |
| var_attributes.c:2:12:2:22 | weakref_var | var_attributes.c:2:39:2:45 | weakref |

View File

@@ -91,6 +91,7 @@
| file://:0:0:0:0 | implicit_int |
| file://:0:0:0:0 | inline |
| file://:0:0:0:0 | int |
| file://:0:0:0:0 | is_consteval |
| file://:0:0:0:0 | is_constexpr |
| file://:0:0:0:0 | is_thread_local |
| file://:0:0:0:0 | long |

View File

@@ -66,6 +66,7 @@
| file://:0:0:0:0 | initializer for <error> |
| file://:0:0:0:0 | inline |
| file://:0:0:0:0 | int |
| file://:0:0:0:0 | is_consteval |
| file://:0:0:0:0 | is_constexpr |
| file://:0:0:0:0 | is_thread_local |
| file://:0:0:0:0 | long |

View File

@@ -16,10 +16,8 @@
| example.c:26:18:26:24 | ref arg & ... | example.c:26:2:26:7 | coords |
| example.c:26:18:26:24 | ref arg & ... | example.c:26:19:26:24 | coords [inner post update] |
| example.c:26:19:26:24 | coords | example.c:26:18:26:24 | & ... |
| example.c:26:19:26:24 | coords [inner post update] | example.c:26:18:26:24 | & ... |
| example.c:28:22:28:25 | ref arg & ... | example.c:28:23:28:25 | pos [inner post update] |
| example.c:28:23:28:25 | pos | example.c:28:22:28:25 | & ... |
| example.c:28:23:28:25 | pos [inner post update] | example.c:28:22:28:25 | & ... |
| 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:8:8:8:9 | t1 |
| test.cpp:6:12:6:17 | call to source | test.cpp:9:8:9:9 | t1 |
@@ -48,11 +46,9 @@
| test.cpp:383:12:383:13 | 0 | test.cpp:384:33:384:35 | tmp |
| test.cpp:383:12:383:13 | 0 | test.cpp:385:8:385:10 | tmp |
| test.cpp:384:10:384:13 | & ... | test.cpp:384:3:384:8 | call to memcpy |
| test.cpp:384:10:384:13 | ref arg & ... | test.cpp:384:3:384:8 | call to memcpy |
| test.cpp:384:10:384:13 | ref arg & ... | test.cpp:384:11:384:13 | tmp [inner post update] |
| test.cpp:384:10:384:13 | ref arg & ... | test.cpp:385:8:385:10 | tmp |
| test.cpp:384:11:384:13 | tmp | test.cpp:384:10:384:13 | & ... |
| test.cpp:384:11:384:13 | tmp [inner post update] | test.cpp:384:10:384:13 | & ... |
| test.cpp:384:17:384:23 | source1 | test.cpp:384:10:384:13 | ref arg & ... |
| test.cpp:384:17:384:23 | source1 | test.cpp:384:16:384:23 | & ... |
| test.cpp:388:53:388:59 | source1 | test.cpp:391:17:391:23 | source1 |
@@ -64,11 +60,9 @@
| test.cpp:389:12:389:13 | 0 | test.cpp:394:10:394:12 | tmp |
| test.cpp:390:19:390:21 | tmp | test.cpp:390:18:390:21 | & ... |
| test.cpp:391:10:391:13 | & ... | test.cpp:391:3:391:8 | call to memcpy |
| test.cpp:391:10:391:13 | ref arg & ... | test.cpp:391:3:391:8 | call to memcpy |
| test.cpp:391:10:391:13 | ref arg & ... | test.cpp:391:11:391:13 | tmp [inner post update] |
| test.cpp:391:10:391:13 | ref arg & ... | test.cpp:392:8:392:10 | tmp |
| test.cpp:391:10:391:13 | ref arg & ... | test.cpp:394:10:394:12 | tmp |
| test.cpp:391:11:391:13 | tmp | test.cpp:391:10:391:13 | & ... |
| test.cpp:391:11:391:13 | tmp [inner post update] | test.cpp:391:10:391:13 | & ... |
| test.cpp:391:17:391:23 | source1 | test.cpp:391:10:391:13 | ref arg & ... |
| test.cpp:391:17:391:23 | source1 | test.cpp:391:16:391:23 | & ... |

View File

@@ -92,27 +92,23 @@
| format.cpp:116:28:116:29 | ref arg & ... | format.cpp:116:29:116:29 | i [inner post update] | |
| format.cpp:116:28:116:29 | ref arg & ... | format.cpp:117:8:117:8 | i | |
| format.cpp:116:29:116:29 | i | format.cpp:116:28:116:29 | & ... | |
| format.cpp:116:29:116:29 | i [inner post update] | format.cpp:116:28:116:29 | & ... | |
| format.cpp:120:10:120:11 | 0 | format.cpp:121:40:121:40 | i | |
| format.cpp:120:10:120:11 | 0 | format.cpp:122:8:122:8 | i | |
| format.cpp:121:39:121:40 | ref arg & ... | format.cpp:121:40:121:40 | i [inner post update] | |
| format.cpp:121:39:121:40 | ref arg & ... | format.cpp:122:8:122:8 | i | |
| format.cpp:121:40:121:40 | i | format.cpp:121:39:121:40 | & ... | |
| format.cpp:121:40:121:40 | i [inner post update] | format.cpp:121:39:121:40 | & ... | |
| format.cpp:125:21:125:24 | {...} | format.cpp:126:32:126:37 | buffer | |
| format.cpp:125:21:125:24 | {...} | format.cpp:127:8:127:13 | buffer | |
| format.cpp:125:23:125:23 | 0 | format.cpp:125:21:125:24 | {...} | TAINT |
| format.cpp:126:31:126:37 | ref arg & ... | format.cpp:126:32:126:37 | buffer [inner post update] | |
| format.cpp:126:31:126:37 | ref arg & ... | format.cpp:127:8:127:13 | buffer | |
| format.cpp:126:32:126:37 | buffer | format.cpp:126:31:126:37 | & ... | |
| format.cpp:126:32:126:37 | buffer [inner post update] | format.cpp:126:31:126:37 | & ... | |
| format.cpp:130:21:130:24 | {...} | format.cpp:131:40:131:45 | buffer | |
| format.cpp:130:21:130:24 | {...} | format.cpp:132:8:132:13 | buffer | |
| format.cpp:130:23:130:23 | 0 | format.cpp:130:21:130:24 | {...} | TAINT |
| format.cpp:131:39:131:45 | ref arg & ... | format.cpp:131:40:131:45 | buffer [inner post update] | |
| format.cpp:131:39:131:45 | ref arg & ... | format.cpp:132:8:132:13 | buffer | |
| format.cpp:131:40:131:45 | buffer | format.cpp:131:39:131:45 | & ... | |
| format.cpp:131:40:131:45 | buffer [inner post update] | format.cpp:131:39:131:45 | & ... | |
| stl.cpp:67:12:67:17 | call to source | stl.cpp:71:7:71:7 | a | |
| stl.cpp:68:16:68:20 | 123 | stl.cpp:68:16:68:21 | call to basic_string | TAINT |
| stl.cpp:68:16:68:21 | call to basic_string | stl.cpp:72:7:72:7 | b | |
@@ -307,7 +303,6 @@
| taint.cpp:165:24:165:24 | 0 | taint.cpp:165:22:165:25 | {...} | TAINT |
| taint.cpp:168:8:168:14 | ref arg tainted | taint.cpp:172:18:172:24 | tainted | |
| taint.cpp:170:10:170:15 | buffer | taint.cpp:170:3:170:8 | call to strcpy | |
| taint.cpp:170:10:170:15 | ref arg buffer | taint.cpp:170:3:170:8 | call to strcpy | |
| taint.cpp:170:10:170:15 | ref arg buffer | taint.cpp:171:8:171:13 | buffer | |
| taint.cpp:170:10:170:15 | ref arg buffer | taint.cpp:172:10:172:15 | buffer | |
| taint.cpp:170:10:170:15 | ref arg buffer | taint.cpp:173:8:173:13 | buffer | |
@@ -317,7 +312,6 @@
| taint.cpp:171:8:171:13 | ref arg buffer | taint.cpp:173:8:173:13 | buffer | |
| taint.cpp:172:10:172:15 | buffer | taint.cpp:172:3:172:8 | call to strcat | |
| taint.cpp:172:10:172:15 | buffer | taint.cpp:172:10:172:15 | ref arg buffer | TAINT |
| taint.cpp:172:10:172:15 | ref arg buffer | taint.cpp:172:3:172:8 | call to strcat | |
| taint.cpp:172:10:172:15 | ref arg buffer | taint.cpp:173:8:173:13 | buffer | |
| taint.cpp:172:18:172:24 | tainted | taint.cpp:172:10:172:15 | ref arg buffer | TAINT |
| taint.cpp:180:19:180:19 | p | taint.cpp:181:9:181:9 | p | |
@@ -325,16 +319,13 @@
| taint.cpp:185:11:185:16 | call to source | taint.cpp:186:11:186:11 | x | |
| taint.cpp:186:10:186:11 | ref arg & ... | taint.cpp:186:11:186:11 | x [inner post update] | |
| taint.cpp:186:11:186:11 | x | taint.cpp:186:10:186:11 | & ... | |
| taint.cpp:186:11:186:11 | x [inner post update] | taint.cpp:186:10:186:11 | & ... | |
| taint.cpp:192:23:192:28 | source | taint.cpp:194:13:194:18 | source | |
| taint.cpp:193:6:193:6 | x | taint.cpp:194:10:194:10 | x | |
| taint.cpp:193:6:193:6 | x | taint.cpp:195:7:195:7 | x | |
| taint.cpp:194:9:194:10 | & ... | taint.cpp:194:2:194:7 | call to memcpy | |
| taint.cpp:194:9:194:10 | ref arg & ... | taint.cpp:194:2:194:7 | call to memcpy | |
| taint.cpp:194:9:194:10 | ref arg & ... | taint.cpp:194:10:194:10 | x [inner post update] | |
| taint.cpp:194:9:194:10 | ref arg & ... | taint.cpp:195:7:195:7 | x | |
| taint.cpp:194:10:194:10 | x | taint.cpp:194:9:194:10 | & ... | |
| taint.cpp:194:10:194:10 | x [inner post update] | taint.cpp:194:9:194:10 | & ... | |
| taint.cpp:194:13:194:18 | source | taint.cpp:194:2:194:7 | call to memcpy | TAINT |
| taint.cpp:194:13:194:18 | source | taint.cpp:194:9:194:10 | ref arg & ... | TAINT |
| taint.cpp:194:21:194:31 | sizeof(int) | taint.cpp:194:2:194:7 | call to memcpy | TAINT |
@@ -495,11 +486,9 @@
| taint.cpp:346:12:346:13 | ref arg & ... | taint.cpp:346:13:346:13 | c [inner post update] | |
| taint.cpp:346:12:346:13 | ref arg & ... | taint.cpp:353:7:353:7 | c | |
| taint.cpp:346:13:346:13 | c | taint.cpp:346:12:346:13 | & ... | |
| taint.cpp:346:13:346:13 | c [inner post update] | taint.cpp:346:12:346:13 | & ... | |
| taint.cpp:347:12:347:13 | ref arg & ... | taint.cpp:347:13:347:13 | d [inner post update] | |
| taint.cpp:347:12:347:13 | ref arg & ... | taint.cpp:354:7:354:7 | d | |
| taint.cpp:347:13:347:13 | d | taint.cpp:347:12:347:13 | & ... | |
| taint.cpp:347:13:347:13 | d [inner post update] | taint.cpp:347:12:347:13 | & ... | |
| taint.cpp:348:14:348:14 | ref arg e | taint.cpp:355:7:355:7 | e | |
| taint.cpp:348:17:348:17 | ref arg t | taint.cpp:350:7:350:7 | t | |
| taint.cpp:365:24:365:29 | source | taint.cpp:369:13:369:18 | source | |

View File

@@ -11,9 +11,9 @@
| addressOf.cpp:38:20:38:20 | i | non-const address |
| addressOf.cpp:40:15:40:15 | i | non-const address |
| addressOf.cpp:42:19:42:22 | iref | non-const address |
| addressOf.cpp:48:3:48:4 | f1 | |
| addressOf.cpp:48:3:48:4 | f1 | const address |
| addressOf.cpp:49:15:49:22 | captured | non-const address |
| addressOf.cpp:50:3:50:4 | f2 | |
| addressOf.cpp:50:3:50:4 | f2 | const address |
| addressOf.cpp:51:10:51:17 | captured | |
| addressOf.cpp:56:16:56:16 | i | |
| addressOf.cpp:56:19:56:19 | i | |

View File

@@ -110,6 +110,7 @@
| file://:0:0:0:0 | int |
| file://:0:0:0:0 | int & |
| file://:0:0:0:0 | int * |
| file://:0:0:0:0 | is_consteval |
| file://:0:0:0:0 | is_constexpr |
| file://:0:0:0:0 | is_thread_local |
| file://:0:0:0:0 | long |

View File

@@ -59,6 +59,7 @@
| file://:0:0:0:0 | int | Other |
| file://:0:0:0:0 | int * | Other |
| file://:0:0:0:0 | int[0] | Other |
| file://:0:0:0:0 | is_consteval | Other |
| file://:0:0:0:0 | is_constexpr | Other |
| file://:0:0:0:0 | is_thread_local | Other |
| file://:0:0:0:0 | long | Other |