mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)`.
|
||||
|
||||
@@ -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, _)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)`
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
struct S1 {
|
||||
[[deprecated]] int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
struct S2 {
|
||||
int x;
|
||||
[[deprecated, gnu::unused]] int b;
|
||||
};
|
||||
@@ -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 |
|
||||
@@ -0,0 +1,3 @@
|
||||
import cpp
|
||||
|
||||
select any(Variable v) as v, v.getAnAttribute()
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 | & ... |
|
||||
|
||||
@@ -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 | |
|
||||
|
||||
@@ -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 | |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
Reference in New Issue
Block a user