Merge remote-tracking branch 'upstream/main' into 'rc/3.14'

This commit is contained in:
Arthur Baars
2024-06-28 19:50:35 +02:00
772 changed files with 16846 additions and 17035 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The "Guards" library (`semmle.code.cpp.controlflow.Guards`) now also infers guards from calls to the builtin operation `__builtin_expect`. As a result, some queries may produce fewer false positives.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The queries "Potential double free" (`cpp/double-free`) and "Potential use after free" (`cpp/use-after-free`) now produce fewer false positives.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* It is now possible to extend the classes `AllocationFunction` and `DeallocationFunction` via data extensions. Extensions of these classes should be added to the `lib/ext/allocation` and `lib/ext/deallocation` directories respectively.

View File

@@ -0,0 +1,7 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: allocationFunctionModel
data:
- ["", "", False, "kmem_alloc", "0", "", "", True]
- ["", "", False, "kmem_zalloc", "0", "", "", True]

View File

@@ -0,0 +1,7 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: allocationFunctionModel
data:
- ["", "", False, "g_malloc", "0", "", "", True]
- ["", "", False, "g_try_malloc", "0", "", "", True]

View File

@@ -0,0 +1,10 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: allocationFunctionModel
data:
- ["", "", False, "CRYPTO_malloc", "0", "", "", True]
- ["", "", False, "CRYPTO_zalloc", "0", "", "", True]
- ["", "", False, "CRYPTO_secure_malloc", "0", "", "", True]
- ["", "", False, "CRYPTO_secure_zalloc", "0", "", "", True]

View File

@@ -0,0 +1,15 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: allocationFunctionModel
data:
- ["", "", False, "malloc", "0", "", "", True]
- ["std", "", False, "malloc", "0", "", "", True]
- ["bsl", "", False, "malloc", "0", "", "", True]
- ["", "", False, "alloca", "0", "", "", False]
- ["", "", False, "__builtin_alloca", "0", "", "", False]
- ["", "", False, "_alloca", "0", "", "", False]
- ["", "", False, "_malloca", "0", "", "", False]
- ["", "", False, "calloc", "1", "0", "", True]
- ["std", "", False, "calloc", "1", "0", "", True]
- ["bsl", "", False, "calloc", "1", "0", "", True]

View File

@@ -0,0 +1,29 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: allocationFunctionModel
data:
- ["", "", False, "MmAllocateContiguousMemory", "0", "", "", True]
- ["", "", False, "MmAllocateContiguousNodeMemory", "0", "", "", True]
- ["", "", False, "MmAllocateContiguousMemorySpecifyCache", "0", "", "", True]
- ["", "", False, "MmAllocateContiguousMemorySpecifyCacheNode", "0", "", "", True]
- ["", "", False, "MmAllocateNonCachedMemory", "0", "", "", True]
- ["", "", False, "MmAllocateMappingAddress", "0", "", "", True]
- ["", "", False, "CoTaskMemAlloc", "0", "", "", True]
- ["", "", False, "ExAllocatePool", "1", "", "", True]
- ["", "", False, "ExAllocatePool2", "1", "", "", True]
- ["", "", False, "ExAllocatePool3", "1", "", "", True]
- ["", "", False, "ExAllocatePoolWithTag", "1", "", "", True]
- ["", "", False, "ExAllocatePoolWithTagPriority", "1", "", "", True]
- ["", "", False, "ExAllocatePoolWithQuota", "1", "", "", True]
- ["", "", False, "ExAllocatePoolWithQuotaTag", "1", "", "", True]
- ["", "", False, "ExAllocatePoolZero", "1", "", "", True]
- ["", "", False, "IoAllocateMdl", "1", "", "", True]
- ["", "", False, "IoAllocateErrorLogEntry", "1", "", "", True]
- ["", "", False, "LocalAlloc", "1", "", "", True]
- ["", "", False, "GlobalAlloc", "1", "", "", True]
- ["", "", False, "VirtualAlloc", "1", "", "", True]
- ["", "", False, "HeapAlloc", "2", "", "", True]
- ["", "", False, "MmAllocatePagesForMdl", "3", "", "", True]
- ["", "", False, "MmAllocatePagesForMdlEx", "3", "", "", True]
- ["", "", False, "MmAllocateNodePagesForMdlEx", "3", "", "", True]

View File

@@ -0,0 +1,5 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: allocationFunctionModel
data: []

View File

@@ -0,0 +1,8 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: deallocationFunctionModel
data:
- ["", "", False, "pool_put", "1"]
- ["", "", False, "pool_cache_put", "1"]
- ["", "", False, "kmem_free", "0"]

View File

@@ -0,0 +1,42 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: deallocationFunctionModel
data:
- ["", "", False, "free", "0"]
- ["std", "", False, "free", "0"]
- ["bsl", "", False, "free", "0"]
- ["", "", False, "realloc", "0"]
- ["std", "", False, "realloc", "0"]
- ["bsl", "", False, "realloc", "0"]
- ["", "", False, "CRYPTO_free", "0"]
- ["", "", False, "CRYPTO_secure_free", "0"]
- ["", "", False, "g_free", "0"]
- ["", "", False, "ExFreePool", "0"]
- ["", "", False, "ExFreePoolWithTag", "0"]
- ["", "", False, "ExDeleteTimer", "0"]
- ["", "", False, "IoFreeIrp", "0"]
- ["", "", False, "IoFreeMdl", "0"]
- ["", "", False, "IoFreeErrorLogEntry", "0"]
- ["", "", False, "IoFreeWorkItem", "0"]
- ["", "", False, "MmFreeContiguousMemory", "0"]
- ["", "", False, "MmFreeContiguousMemorySpecifyCache", "0"]
- ["", "", False, "MmFreeNonCachedMemory", "0"]
- ["", "", False, "MmFreeMappingAddress", "0"]
- ["", "", False, "MmFreePagesFromMdl", "0"]
- ["", "", False, "MmUnmapReservedMapping", "0"]
- ["", "", False, "MmUnmapLockedPages", "0"]
- ["", "", False, "NdisFreeGenericObject", "0"]
- ["", "", False, "NdisFreeMemory", "0"]
- ["", "", False, "NdisFreeMemoryWithTag", "0"]
- ["", "", False, "NdisFreeMdl", "0"]
- ["", "", False, "NdisFreeNetBufferListPool", "0"]
- ["", "", False, "NdisFreeNetBufferPool", "0"]
- ["", "", False, "LocalFree", "0"]
- ["", "", False, "GlobalFree", "0"]
- ["", "", False, "LocalReAlloc", "0"]
- ["", "", False, "GlobalReAlloc", "0"]
- ["", "", False, "VirtualFree", "0"]
- ["", "", False, "CoTaskMemFree", "0"]
- ["", "", False, "CoTaskMemRealloc", "0"]
- ["", "", False, "SysFreeString", "0"]

View File

@@ -0,0 +1,41 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: deallocationFunctionModel
data:
- ["", "", False, "ExFreePool", "0"]
- ["", "", False, "ExFreePoolWithTag", "0"]
- ["", "", False, "ExDeleteTimer", "0"]
- ["", "", False, "IoFreeIrp", "0"]
- ["", "", False, "IoFreeMdl", "0"]
- ["", "", False, "IoFreeErrorLogEntry", "0"]
- ["", "", False, "IoFreeWorkItem", "0"]
- ["", "", False, "MmFreeContiguousMemory", "0"]
- ["", "", False, "MmFreeContiguousMemorySpecifyCache", "0"]
- ["", "", False, "MmFreeNonCachedMemory", "0"]
- ["", "", False, "MmFreeMappingAddress", "0"]
- ["", "", False, "MmFreePagesFromMdl", "0"]
- ["", "", False, "MmUnmapReservedMapping", "0"]
- ["", "", False, "MmUnmapLockedPages", "0"]
- ["", "", False, "NdisFreeGenericObject", "0"]
- ["", "", False, "NdisFreeMemory", "0"]
- ["", "", False, "NdisFreeMemoryWithTag", "0"]
- ["", "", False, "NdisFreeMdl", "0"]
- ["", "", False, "NdisFreeNetBufferListPool", "0"]
- ["", "", False, "NdisFreeNetBufferPool", "0"]
- ["", "", False, "LocalFree", "0"]
- ["", "", False, "GlobalFree", "0"]
- ["", "", False, "LocalReAlloc", "0"]
- ["", "", False, "GlobalReAlloc", "0"]
- ["", "", False, "VirtualFree", "0"]
- ["", "", False, "CoTaskMemFree", "0"]
- ["", "", False, "CoTaskMemRealloc", "0"]
- ["", "", False, "SysFreeString", "0"]
- ["", "", False, "ExFreeToLookasideListEx", "1"]
- ["", "", False, "ExFreeToPagedLookasideList", "1"]
- ["", "", False, "ExFreeToNPagedLookasideList", "1"]
- ["", "", False, "NdisFreeMemoryWithTagPriority", "1"]
- ["", "", False, "StorPortFreeMdl", "1"]
- ["", "", False, "StorPortFreePool", "1"]
- ["", "", False, "HeapFree", "2"]
- ["", "", False, "HeapReAlloc", "2"]

View File

@@ -0,0 +1,5 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: deallocationFunctionModel
data: []

View File

@@ -16,4 +16,6 @@ dependencies:
codeql/xml: ${workspace}
dataExtensions:
- ext/*.model.yml
- ext/deallocation/*.model.yml
- ext/allocation/*.model.yml
warnOnImplicitThis: true

View File

@@ -762,6 +762,8 @@ private predicate compares_eq(
exists(AbstractValue dual | value = dual.getDualValue() |
compares_eq(test.(LogicalNotInstruction).getUnary(), left, right, k, areEqual, dual)
)
or
compares_eq(test.(BuiltinExpectCallInstruction).getCondition(), left, right, k, areEqual, value)
}
/**
@@ -831,6 +833,9 @@ private predicate unary_compares_eq(
int_value(const) = k1 and
k = k1 + k2
)
or
unary_compares_eq(test.(BuiltinExpectCallInstruction).getCondition(), op, k, areEqual,
inNonZeroCase, value)
}
/** Rearrange various simple comparisons into `left == right + k` form. */
@@ -910,12 +915,68 @@ private predicate unary_simple_comparison_eq(
)
}
/** A call to the builtin operation `__builtin_expect`. */
private class BuiltinExpectCallInstruction extends CallInstruction {
BuiltinExpectCallInstruction() { this.getStaticCallTarget().hasName("__builtin_expect") }
/** Gets the condition of this call. */
Instruction getCondition() {
// The first parameter of `__builtin_expect` has type `long`. So we skip
// the conversion when inferring guards.
result = this.getArgument(0).(ConvertInstruction).getUnary()
}
}
/**
* Holds if `left == right + k` is `areEqual` if `cmp` evaluates to `value`,
* and `cmp` is an instruction that compares the value of
* `__builtin_expect(left == right + k, _)` to `0`.
*/
private predicate builtin_expect_eq(
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
) {
exists(BuiltinExpectCallInstruction call, Instruction const, AbstractValue innerValue |
int_value(const) = 0 and
cmp.hasOperands(call.getAUse(), const.getAUse()) and
compares_eq(call.getCondition(), left, right, k, areEqual, innerValue)
|
cmp instanceof CompareNEInstruction and
value = innerValue
or
cmp instanceof CompareEQInstruction and
value.getDualValue() = innerValue
)
}
private predicate complex_eq(
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
) {
sub_eq(cmp, left, right, k, areEqual, value)
or
add_eq(cmp, left, right, k, areEqual, value)
or
builtin_expect_eq(cmp, left, right, k, areEqual, value)
}
/**
* Holds if `op == k` is `areEqual` if `cmp` evaluates to `value`, and `cmp` is
* an instruction that compares the value of `__builtin_expect(op == k, _)` to `0`.
*/
private predicate unary_builtin_expect_eq(
CompareInstruction cmp, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
AbstractValue value
) {
exists(BuiltinExpectCallInstruction call, Instruction const, AbstractValue innerValue |
int_value(const) = 0 and
cmp.hasOperands(call.getAUse(), const.getAUse()) and
unary_compares_eq(call.getCondition(), op, k, areEqual, inNonZeroCase, innerValue)
|
cmp instanceof CompareNEInstruction and
value = innerValue
or
cmp instanceof CompareEQInstruction and
value.getDualValue() = innerValue
)
}
private predicate unary_complex_eq(
@@ -924,6 +985,8 @@ private predicate unary_complex_eq(
unary_sub_eq(test, op, k, areEqual, inNonZeroCase, value)
or
unary_add_eq(test, op, k, areEqual, inNonZeroCase, value)
or
unary_builtin_expect_eq(test, op, k, areEqual, inNonZeroCase, value)
}
/*

View File

@@ -216,7 +216,7 @@ predicate localMustFlowStep(Node node1, Node node2) { none() }
/** Gets the type of `n` used for type pruning. */
Type getNodeType(Node n) {
suppressUnusedNode(n) and
exists(n) and
result instanceof VoidType // stub implementation
}
@@ -227,13 +227,10 @@ string ppReprType(Type t) { none() } // stub implementation
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
* a node of type `t1` to a node of type `t2`.
*/
pragma[inline]
predicate compatibleTypes(Type t1, Type t2) {
any() // stub implementation
t1 instanceof VoidType and t2 instanceof VoidType // stub implementation
}
private predicate suppressUnusedNode(Node n) { any() }
//////////////////////////////////////////////////////////////////////////////
// Java QL library compatibility wrappers
//////////////////////////////////////////////////////////////////////////////

View File

@@ -988,7 +988,7 @@ predicate localMustFlowStep(Node node1, Node node2) { none() }
/** Gets the type of `n` used for type pruning. */
DataFlowType getNodeType(Node n) {
suppressUnusedNode(n) and
exists(n) and
result instanceof VoidType // stub implementation
}
@@ -999,13 +999,10 @@ string ppReprType(DataFlowType t) { none() } // stub implementation
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
* a node of type `t1` to a node of type `t2`.
*/
pragma[inline]
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) {
any() // stub implementation
t1 instanceof VoidType and t2 instanceof VoidType // stub implementation
}
private predicate suppressUnusedNode(Node n) { any() }
//////////////////////////////////////////////////////////////////////////////
// Java QL library compatibility wrappers
//////////////////////////////////////////////////////////////////////////////

View File

@@ -193,6 +193,46 @@ private module Cached {
)
}
/** Holds if `operand`'s definition is a `VariableAddressInstruction` whose variable is a temporary */
private predicate isIRTempVariable(Operand operand) {
operand.getDef().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable
}
/**
* Holds if `node` is an indirect operand whose operand is an argument, and
* the `n`'th expression associated with the operand is `e`.
*/
private predicate isIndirectOperandOfArgument(
IndirectOperand node, ArgumentOperand operand, Expr e, int n
) {
node.hasOperandAndIndirectionIndex(operand, 1) and
e = getConvertedResultExpression(operand.getDef(), n)
}
/**
* Holds if `opFrom` is an operand to a conversion, and `opTo` is the unique
* use of the conversion.
*/
private predicate isConversionStep(Operand opFrom, Operand opTo) {
exists(Instruction mid |
conversionFlow(opFrom, mid, false, false) and
opTo = unique( | | getAUse(mid))
)
}
/**
* Holds if an operand that satisfies `isIRTempVariable` flows to `op`
* through a (possibly empty) sequence of conversions.
*/
private predicate irTempOperandConversionFlows(Operand op) {
isIRTempVariable(op)
or
exists(Operand mid |
irTempOperandConversionFlows(mid) and
isConversionStep(mid, op)
)
}
/** Holds if `node` should be an `IndirectOperand` that maps `node.asExpr()` to `e`. */
private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e, int n) {
exists(ArgumentOperand operand |
@@ -203,9 +243,8 @@ private module Cached {
// result. However, the instruction actually represents the _address_ of
// the argument. So to fix this mismatch, we have the indirection of the
// `VariableAddressInstruction` map to the expression.
node.hasOperandAndIndirectionIndex(operand, 1) and
e = getConvertedResultExpression(operand.getDef(), n) and
operand.getDef().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable
isIndirectOperandOfArgument(node, operand, e, n) and
irTempOperandConversionFlows(operand)
)
}

View File

@@ -1,3 +1,3 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IR
import semmle.code.cpp.ir.implementation.raw.IR
import semmle.code.cpp.ir.internal.Overlap
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

@@ -1,3 +1,3 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IR
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
import semmle.code.cpp.ir.internal.Overlap
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

@@ -7,119 +7,6 @@
import semmle.code.cpp.models.interfaces.Allocation
import semmle.code.cpp.models.interfaces.Taint
/**
* An allocation function (such as `malloc`) that has an argument for the size
* in bytes.
*/
private class MallocAllocationFunction extends AllocationFunction {
int sizeArg;
MallocAllocationFunction() {
// --- C library allocation
this.hasGlobalOrStdOrBslName("malloc") and // malloc(size)
sizeArg = 0
or
this.hasGlobalName([
// --- Windows Memory Management for Windows Drivers
"MmAllocateContiguousMemory", // MmAllocateContiguousMemory(size, maxaddress)
"MmAllocateContiguousNodeMemory", // MmAllocateContiguousNodeMemory(size, minaddress, maxaddress, bound, flag, prefer)
"MmAllocateContiguousMemorySpecifyCache", // MmAllocateContiguousMemorySpecifyCache(size, minaddress, maxaddress, bound, type)
"MmAllocateContiguousMemorySpecifyCacheNode", // MmAllocateContiguousMemorySpecifyCacheNode(size, minaddress, maxaddress, bound, type, prefer)
"MmAllocateNonCachedMemory", // MmAllocateNonCachedMemory(size)
"MmAllocateMappingAddress", // MmAllocateMappingAddress(size, tag)
// --- Windows COM allocation
"CoTaskMemAlloc", // CoTaskMemAlloc(size)
// --- Solaris/BSD kernel memory allocator
"kmem_alloc", // kmem_alloc(size, flags)
"kmem_zalloc", // kmem_zalloc(size, flags)
// --- OpenSSL memory allocation
"CRYPTO_malloc", // CRYPTO_malloc(size_t num, const char *file, int line)
"CRYPTO_zalloc", // CRYPTO_zalloc(size_t num, const char *file, int line)
"CRYPTO_secure_malloc", // CRYPTO_secure_malloc(size_t num, const char *file, int line)
"CRYPTO_secure_zalloc", // CRYPTO_secure_zalloc(size_t num, const char *file, int line)
"g_malloc", // g_malloc (n_bytes);
"g_try_malloc" // g_try_malloc(n_bytes);
]) and
sizeArg = 0
or
this.hasGlobalName([
// --- Windows Memory Management for Windows Drivers
"ExAllocatePool", // ExAllocatePool(type, size)
"ExAllocatePool2", // ExAllocatePool2(flags, size, tag)
"ExAllocatePool3", // ExAllocatePool3(flags, size, tag, extparams, extparamscount)
"ExAllocatePoolWithTag", // ExAllocatePool(type, size, tag)
"ExAllocatePoolWithTagPriority", // ExAllocatePoolWithTagPriority(type, size, tag, priority)
"ExAllocatePoolWithQuota", // ExAllocatePoolWithQuota(type, size)
"ExAllocatePoolWithQuotaTag", // ExAllocatePoolWithQuotaTag(type, size, tag)
"ExAllocatePoolZero", // ExAllocatePoolZero(type, size, tag)
"IoAllocateMdl", // IoAllocateMdl(address, size, flag, flag, irp)
"IoAllocateErrorLogEntry", // IoAllocateErrorLogEntry(object, size)
// --- Windows Global / Local legacy allocation
"LocalAlloc", // LocalAlloc(flags, size)
"GlobalAlloc", // GlobalAlloc(flags, size)
// --- Windows System Services allocation
"VirtualAlloc" // VirtualAlloc(address, size, type, flag)
]) and
sizeArg = 1
or
this.hasGlobalName("HeapAlloc") and // HeapAlloc(heap, flags, size)
sizeArg = 2
or
this.hasGlobalName([
// --- Windows Memory Management for Windows Drivers
"MmAllocatePagesForMdl", // MmAllocatePagesForMdl(minaddress, maxaddress, skip, size)
"MmAllocatePagesForMdlEx", // MmAllocatePagesForMdlEx(minaddress, maxaddress, skip, size, type, flags)
"MmAllocateNodePagesForMdlEx" // MmAllocateNodePagesForMdlEx(minaddress, maxaddress, skip, size, type, prefer, flags)
]) and
sizeArg = 3
}
override int getSizeArg() { result = sizeArg }
}
/**
* An allocation function (such as `alloca`) that does not require a
* corresponding free (and has an argument for the size in bytes).
*/
private class AllocaAllocationFunction extends AllocationFunction {
int sizeArg;
AllocaAllocationFunction() {
this.hasGlobalName([
// --- stack allocation
"alloca", // // alloca(size)
"__builtin_alloca", // __builtin_alloca(size)
"_alloca", // _alloca(size)
"_malloca" // _malloca(size)
]) and
sizeArg = 0
}
override int getSizeArg() { result = sizeArg }
override predicate requiresDealloc() { none() }
}
/**
* An allocation function (such as `calloc`) that has an argument for the size
* and another argument for the size of those units (in bytes).
*/
private class CallocAllocationFunction extends AllocationFunction {
int sizeArg;
int multArg;
CallocAllocationFunction() {
// --- C library allocation
this.hasGlobalOrStdOrBslName("calloc") and // calloc(num, size)
sizeArg = 1 and
multArg = 0
}
override int getSizeArg() { result = sizeArg }
override int getSizeMult() { result = multArg }
}
/**
* An allocation function (such as `realloc`) that has an argument for the size
* in bytes, and an argument for an existing pointer that is to be reallocated.
@@ -373,6 +260,63 @@ private class NewArrayAllocationExpr extends AllocationExpr, NewArrayExpr {
override predicate requiresDealloc() { not exists(this.getPlacementPointer()) }
}
/**
* Holds if `f` is an allocation function according to the
* extensible `allocationFunctionModel` predicate.
*/
private predicate isAllocationFunctionFromModel(
Function f, string namespace, string type, string name
) {
exists(boolean subtypes | allocationFunctionModel(namespace, type, subtypes, name, _, _, _, _) |
if type = ""
then f.hasQualifiedName(namespace, "", name)
else
exists(Class c |
c.hasQualifiedName(namespace, type) and f.hasQualifiedName(namespace, _, name)
|
if subtypes = true
then f = c.getADerivedClass*().getAMemberFunction()
else f = c.getAMemberFunction()
)
)
}
/**
* An allocation function modeled via the extensible `allocationFunctionModel` predicate.
*/
private class AllocationFunctionFromModel extends AllocationFunction {
string namespace;
string type;
string name;
AllocationFunctionFromModel() { isAllocationFunctionFromModel(this, namespace, type, name) }
final override int getSizeArg() {
exists(string sizeArg |
allocationFunctionModel(namespace, type, _, name, sizeArg, _, _, _) and
result = sizeArg.toInt()
)
}
final override int getSizeMult() {
exists(string sizeMult |
allocationFunctionModel(namespace, type, _, name, _, sizeMult, _, _) and
result = sizeMult.toInt()
)
}
final override int getReallocPtrArg() {
exists(string reallocPtrArg |
allocationFunctionModel(namespace, type, _, name, _, _, reallocPtrArg, _) and
result = reallocPtrArg.toInt()
)
}
final override predicate requiresDealloc() {
allocationFunctionModel(namespace, type, _, name, _, _, _, true)
}
}
private module HeuristicAllocation {
/** A class that maps an `AllocationExpr` to an `HeuristicAllocationExpr`. */
private class HeuristicAllocationModeled extends HeuristicAllocationExpr instanceof AllocationExpr

View File

@@ -7,61 +7,42 @@
import semmle.code.cpp.models.interfaces.Deallocation
/**
* A deallocation function such as `free`.
* Holds if `f` is an deallocation function according to the
* extensible `deallocationFunctionModel` predicate.
*/
private class StandardDeallocationFunction extends DeallocationFunction {
int freedArg;
private predicate isDeallocationFunctionFromModel(
Function f, string namespace, string type, string name
) {
exists(boolean subtypes | deallocationFunctionModel(namespace, type, subtypes, name, _) |
if type = ""
then f.hasQualifiedName(namespace, "", name)
else
exists(Class c |
c.hasQualifiedName(namespace, type) and f.hasQualifiedName(namespace, _, name)
|
if subtypes = true
then f = c.getADerivedClass*().getAMemberFunction()
else f = c.getAMemberFunction()
)
)
}
StandardDeallocationFunction() {
this.hasGlobalOrStdOrBslName([
// --- C library allocation
"free", "realloc"
]) and
freedArg = 0
or
this.hasGlobalName([
// --- OpenSSL memory deallocation
"CRYPTO_free", "CRYPTO_secure_free",
// --- glib memory deallocation
"g_free"
]) and
freedArg = 0
or
this.hasGlobalOrStdName([
// --- Windows Memory Management for Windows Drivers
"ExFreePool", "ExFreePoolWithTag", "ExDeleteTimer", "IoFreeIrp", "IoFreeMdl",
"IoFreeErrorLogEntry", "IoFreeWorkItem", "MmFreeContiguousMemory",
"MmFreeContiguousMemorySpecifyCache", "MmFreeNonCachedMemory", "MmFreeMappingAddress",
"MmFreePagesFromMdl", "MmUnmapReservedMapping", "MmUnmapLockedPages",
"NdisFreeGenericObject", "NdisFreeMemory", "NdisFreeMemoryWithTag", "NdisFreeMdl",
"NdisFreeNetBufferListPool", "NdisFreeNetBufferPool",
// --- Windows Global / Local legacy allocation
"LocalFree", "GlobalFree", "LocalReAlloc", "GlobalReAlloc",
// --- Windows System Services allocation
"VirtualFree",
// --- Windows COM allocation
"CoTaskMemFree", "CoTaskMemRealloc",
// --- Windows Automation
"SysFreeString",
// --- Solaris/BSD kernel memory allocator
"kmem_free"
]) and
freedArg = 0
or
this.hasGlobalOrStdName([
// --- Windows Memory Management for Windows Drivers
"ExFreeToLookasideListEx", "ExFreeToPagedLookasideList", "ExFreeToNPagedLookasideList",
"NdisFreeMemoryWithTagPriority", "StorPortFreeMdl", "StorPortFreePool",
// --- NetBSD pool manager
"pool_put", "pool_cache_put"
]) and
freedArg = 1
or
this.hasGlobalOrStdName(["HeapFree", "HeapReAlloc"]) and
freedArg = 2
/**
* A deallocation function modeled via the extensible `deallocationFunctionModel` predicate.
*/
private class DeallocationFunctionFromModel extends DeallocationFunction {
string namespace;
string type;
string name;
DeallocationFunctionFromModel() { isDeallocationFunctionFromModel(this, namespace, type, name) }
final override int getFreedArg() {
exists(string freedArg |
deallocationFunctionModel(namespace, type, _, name, freedArg) and
result = freedArg.toInt()
)
}
override int getFreedArg() { result = freedArg }
}
/**

View File

@@ -89,6 +89,14 @@ abstract class AllocationFunction extends Function {
predicate requiresDealloc() { any() }
}
/**
* Holds if an external allocation model exists for the given parameters.
*/
extensible predicate allocationFunctionModel(
string namespace, string type, boolean subtypes, string name, string sizeArg, string multArg,
string reallocPtrArg, boolean requiresDealloc
);
/**
* An `operator new` or `operator new[]` function that may be associated with
* `new` or `new[]` expressions. Note that `new` and `new[]` are not function

View File

@@ -34,6 +34,13 @@ abstract class DeallocationFunction extends Function {
int getFreedArg() { none() }
}
/**
* Holds if an external deallocation model exists for the given parameters.
*/
extensible predicate deallocationFunctionModel(
string namespace, string type, boolean subtypes, string name, string freedArg
);
/**
* An `operator delete` or `operator delete[]` function that may be associated
* with `delete` or `delete[]` expressions. Note that `delete` and `delete[]`

View File

@@ -95,7 +95,7 @@ module FlowFromFree<FlowFromFreeParamSig P> {
e = any(StoreInstruction store).getDestinationAddress().getUnconvertedResultExpression()
)
or
n.asExpr() instanceof ArrayExpr
[n.asExpr(), n.asIndirectExpr()] instanceof ArrayExpr
}
}

View File

@@ -215,13 +215,18 @@ predicate noThrowInTryBlock(NewOrNewArrayExpr newExpr, BadAllocCatchBlock catchB
*/
predicate nullCheckInThrowingNew(NewOrNewArrayExpr newExpr, GuardCondition guard) {
newExpr.getAllocator() instanceof ThrowingAllocator and
(
// Handles null comparisons.
guard.ensuresEq(globalValueNumber(newExpr).getAnExpr(), any(NullValue null), _, _, _)
or
// Handles `if(ptr)` and `if(!ptr)` cases.
guard = globalValueNumber(newExpr).getAnExpr()
)
// There can be many guard conditions that compares `newExpr` againgst 0.
// For example, for `if(!p)` both `p` and `!p` are guard conditions. To not
// produce duplicates results we pick the "first" guard condition according
// to some arbitrary ordering (i.e., location information). This means `!p` is the
// element that we use to construct the alert.
guard =
min(GuardCondition gc, int startline, int startcolumn, int endline, int endcolumn |
gc.comparesEq(globalValueNumber(newExpr).getAnExpr(), 0, _, _) and
gc.getLocation().hasLocationInfo(_, startline, startcolumn, endline, endcolumn)
|
gc order by startline, startcolumn, endline, endcolumn
)
}
from NewOrNewArrayExpr newExpr, Element element, string msg, string elementString

View File

@@ -3,4 +3,4 @@
#include "b.h"
static int has_angle_b = __has_include(<b.h>);
// semmle-extractor-options: -I${testdir}/dir2 -iquote ${testdir}/dir1 --edg --clang
// semmle-extractor-options: -I${testdir}/dir2 -iquote ${testdir}/dir1 --clang

View File

@@ -1 +1 @@
semmle-extractor-options: --edg --microsoft
semmle-extractor-options: --microsoft

View File

@@ -1,22 +1,21 @@
| arguments.c | 1 | --preprocessArgs |
| arguments.c | 2 | --force-recompute |
| arguments.c | 3 | --edg |
| arguments.c | 4 | --disable_system_macros |
| arguments.c | 5 | --edg |
| arguments.c | 6 | --codeql-verbosity |
| arguments.c | 7 | --edg |
| arguments.c | 8 | 2 |
| arguments.c | 9 | --edg |
| arguments.c | 10 | --target |
| arguments.c | 11 | --edg |
| arguments.c | 12 | linux_x86_64 |
| arguments.c | 13 | --edg |
| arguments.c | 14 | -D |
| arguments.c | 15 | --edg |
| arguments.c | 16 | __CODEQL_TEST__ |
| arguments.c | 17 | --gcc |
| arguments.c | 18 | --predefined_macros |
| arguments.c | 19 | <tools>/qltest/predefined_macros |
| arguments.c | 20 | -w |
| arguments.c | 21 | -Werror |
| arguments.c | 22 | arguments.c |
| arguments.c | 2 | --edg |
| arguments.c | 3 | --force-recompute |
| arguments.c | 4 | --edg |
| arguments.c | 5 | --disable_system_macros |
| arguments.c | 6 | --edg |
| arguments.c | 7 | --codeql-verbosity |
| arguments.c | 8 | --edg |
| arguments.c | 9 | 2 |
| arguments.c | 10 | --edg |
| arguments.c | 11 | --target |
| arguments.c | 12 | --edg |
| arguments.c | 13 | linux_x86_64 |
| arguments.c | 14 | --edg |
| arguments.c | 15 | -D |
| arguments.c | 16 | --edg |
| arguments.c | 17 | __CODEQL_TEST__ |
| arguments.c | 18 | --gcc |
| arguments.c | 19 | -w |
| arguments.c | 20 | -Werror |
| arguments.c | 21 | arguments.c |

View File

@@ -4,8 +4,5 @@ from Compilation c, int i, string s
// Skip the extractor name; it'll vary depending on platform
where
i > 0 and
s =
c.getArgument(i)
.replaceAll("\\", "/")
.regexpReplaceAll(".*(/qltest/predefined_macros)", "<tools>$1")
s = c.getArgument(i).replaceAll("\\", "/")
select c.getAFileCompiled().toString(), i, s

View File

@@ -1 +1 @@
semmle-extractor-options: --edg --clang
semmle-extractor-options: --clang

View File

@@ -1,4 +1,8 @@
| declspec.cpp:4:23:4:43 | Use fatal() instead | declspec.cpp:4:59:4:62 | exit | declspec.cpp:4:12:4:21 | deprecated | Use fatal() instead |
| routine_attributes2.cpp:5:6:5:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility | hidden |
| routine_attributes2.cpp:5:6:5:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility | hidden |
| routine_attributes2.h:3:6:3:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility | hidden |
| routine_attributes2.h:3:6:3:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility | hidden |
| routine_attributes.c:3:53:3:59 | dummy | routine_attributes.c:3:12:3:24 | named_weakref | routine_attributes.c:3:44:3:50 | weakref | dummy |
| routine_attributes.c:4:62:4:68 | dummy | routine_attributes.c:4:12:4:26 | aliased_weakref | routine_attributes.c:4:55:4:59 | alias | dummy |
| routine_attributes.c:6:49:6:55 | dummy | routine_attributes.c:6:12:6:22 | plain_alias | routine_attributes.c:6:42:6:46 | alias | dummy |

View File

@@ -18,6 +18,10 @@
| header_export.cpp:14:16:14:26 | myFunction4 | header_export.cpp:14:1:14:9 | dllexport |
| header_export.cpp:18:6:18:16 | myFunction5 | header.h:10:2:10:10 | dllexport |
| header_export.cpp:18:6:18:16 | myFunction5 | header.h:10:2:10:10 | dllimport |
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility |
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility |
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility |
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility |
| routine_attributes.c:3:12:3:24 | named_weakref | routine_attributes.c:3:44:3:50 | weakref |
| routine_attributes.c:4:12:4:26 | aliased_weakref | routine_attributes.c:4:46:4:52 | weakref |
| routine_attributes.c:4:12:4:26 | aliased_weakref | routine_attributes.c:4:55:4:59 | alias |

View File

@@ -0,0 +1,7 @@
#define HIDDEN __attribute__((visibility("hidden")))
#include "routine_attributes2.h"
void HIDDEN a_routine() {
return;
}

View File

@@ -0,0 +1,3 @@
#pragma once
void HIDDEN a_routine();

View File

@@ -0,0 +1,3 @@
#define HIDDEN __attribute__((visibility("hidden")))
#include "routine_attributes2.h"

View File

@@ -1,3 +1,6 @@
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.cpp:5:7:5:12 | visibility | type_attributes2.cpp:5:7:5:12 | hidden |
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility | type_attributes2.h:3:7:3:12 | hidden |
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility | type_attributes2.h:3:7:3:12 | hidden |
| type_attributes_ms.cpp:4:67:4:75 | IDispatch | type_attributes_ms.cpp:4:19:4:22 | uuid | type_attributes_ms.cpp:4:24:4:63 | {00020400-0000-0000-c000-000000000046} |
| type_attributes_ms.cpp:5:30:5:33 | Str1 | type_attributes_ms.cpp:5:12:5:16 | align | type_attributes_ms.cpp:5:18:5:19 | 32 |
| type_attributes_ms.cpp:6:55:6:62 | IUnknown | type_attributes_ms.cpp:6:2:6:2 | uuid | type_attributes_ms.cpp:6:2:6:2 | 00000000-0000-0000-c000-000000000046 |

View File

@@ -1,4 +1,7 @@
| file://:0:0:0:0 | short __attribute((__may_alias__)) | type_attributes.c:25:30:25:42 | may_alias |
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.cpp:5:7:5:12 | visibility |
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility |
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility |
| type_attributes.c:5:36:5:51 | my_packed_struct | type_attributes.c:5:23:5:32 | packed |
| type_attributes.c:10:54:10:54 | (unnamed class/struct/union) | type_attributes.c:10:30:10:50 | transparent_union |
| type_attributes.c:16:54:16:54 | (unnamed class/struct/union) | type_attributes.c:16:30:16:50 | transparent_union |

View File

@@ -0,0 +1,6 @@
#define HIDDEN __attribute__((visibility("hidden")))
#include "type_attributes2.h"
class HIDDEN a_class {
};

View File

@@ -0,0 +1,3 @@
#pragma once
class HIDDEN a_class;

View File

@@ -0,0 +1,3 @@
#define HIDDEN __attribute__((visibility("hidden")))
#include "type_attributes2.h"

View File

@@ -6,6 +6,10 @@
| ms_var_attributes.cpp:12:42:12:46 | field | ms_var_attributes.cpp:12:14:12:21 | property |
| ms_var_attributes.cpp:20:34:20:37 | pBuf | ms_var_attributes.cpp:20:12:20:12 | SAL_volatile |
| ms_var_attributes.h:5:22:5:27 | myInt3 | ms_var_attributes.h:5:1:5:9 | dllexport |
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.cpp:5:5:5:10 | visibility |
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.cpp:5:5:5:10 | visibility |
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.h:3:12:3:17 | visibility |
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.h:3:12:3:17 | visibility |
| 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 |
| var_attributes.c:3:12:3:19 | used_var | var_attributes.c:3:36:3:39 | used |

View File

@@ -0,0 +1,5 @@
#define HIDDEN __attribute__((visibility("hidden")))
#include "var_attributes2.h"
int HIDDEN a_variable;

View File

@@ -0,0 +1,3 @@
#pragma once
extern int HIDDEN a_variable;

View File

@@ -0,0 +1,3 @@
#define HIDDEN __attribute__((visibility("hidden")))
#include "var_attributes2.h"

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --edg --clang
// semmle-extractor-options: --clang
int x = 0;

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --edg --clang --edg --c++11 --edg --nullptr
// semmle-extractor-options: --clang --edg --c++11 --edg --nullptr
static int has_nullptr_f = __has_feature(cxx_nullptr);
static int has_nullptr_e = __has_extension(cxx_nullptr);

View File

@@ -1 +1 @@
semmle-extractor-options: --edg --clang
semmle-extractor-options: --clang

View File

@@ -1,7 +1,7 @@
// For the canonical behaviour, run: clang -E -w test.cpp
#define __builtin_TRAP __builtin_trap
#define BAR "bar.h"
// semmle-extractor-options: --edg --clang --expect_errors
// semmle-extractor-options: --clang --expect_errors
#if defined(__has_include)
static int has_include = 1;
#else

View File

@@ -1 +1 @@
semmle-extractor-options: --edg --clang --edg --ms_extensions
semmle-extractor-options: --clang --edg --ms_extensions

View File

@@ -45,3 +45,7 @@
| test.cpp:122:9:122:9 | b |
| test.cpp:125:13:125:20 | ! ... |
| test.cpp:125:14:125:17 | call to safe |
| test.cpp:131:6:131:21 | call to __builtin_expect |
| test.cpp:135:6:135:21 | call to __builtin_expect |
| test.cpp:141:6:141:21 | call to __builtin_expect |
| test.cpp:145:6:145:21 | call to __builtin_expect |

View File

@@ -164,10 +164,46 @@
| 126 | call to test3_condition != 0 when ... && ... is true |
| 126 | call to test3_condition != 0 when call to test3_condition is true |
| 126 | call to test3_condition == 0 when call to test3_condition is false |
| 131 | ... + ... != a+0 when call to __builtin_expect is false |
| 131 | ... + ... == a+0 when call to __builtin_expect is true |
| 131 | a != ... + ...+0 when call to __builtin_expect is false |
| 131 | a != b+42 when call to __builtin_expect is false |
| 131 | a == ... + ...+0 when call to __builtin_expect is true |
| 131 | a == b+42 when call to __builtin_expect is true |
| 131 | b != 0 when b is true |
| 131 | b != a+-42 when call to __builtin_expect is false |
| 131 | b == 0 when b is false |
| 131 | b == a+-42 when call to __builtin_expect is true |
| 131 | call to __builtin_expect != 0 when call to __builtin_expect is true |
| 131 | call to __builtin_expect == 0 when call to __builtin_expect is false |
| 135 | ... + ... != a+0 when call to __builtin_expect is true |
| 135 | ... + ... == a+0 when call to __builtin_expect is false |
| 135 | a != ... + ...+0 when call to __builtin_expect is true |
| 135 | a != b+42 when call to __builtin_expect is true |
| 135 | a == ... + ...+0 when call to __builtin_expect is false |
| 135 | a == b+42 when call to __builtin_expect is false |
| 135 | b != a+-42 when call to __builtin_expect is true |
| 135 | b == a+-42 when call to __builtin_expect is false |
| 135 | call to __builtin_expect != 0 when call to __builtin_expect is true |
| 135 | call to __builtin_expect == 0 when call to __builtin_expect is false |
| 137 | 0 != 0 when 0 is true |
| 137 | 0 == 0 when 0 is false |
| 141 | 42 != a+0 when call to __builtin_expect is false |
| 141 | 42 == a+0 when call to __builtin_expect is true |
| 141 | a != 42 when call to __builtin_expect is false |
| 141 | a != 42+0 when call to __builtin_expect is false |
| 141 | a == 42 when call to __builtin_expect is true |
| 141 | a == 42+0 when call to __builtin_expect is true |
| 141 | call to __builtin_expect != 0 when call to __builtin_expect is true |
| 141 | call to __builtin_expect == 0 when call to __builtin_expect is false |
| 145 | 42 != a+0 when call to __builtin_expect is true |
| 145 | 42 == a+0 when call to __builtin_expect is false |
| 145 | a != 42 when call to __builtin_expect is true |
| 145 | a != 42+0 when call to __builtin_expect is true |
| 145 | a == 42 when call to __builtin_expect is false |
| 145 | a == 42+0 when call to __builtin_expect is false |
| 145 | call to __builtin_expect != 0 when call to __builtin_expect is true |
| 145 | call to __builtin_expect == 0 when call to __builtin_expect is false |
| 146 | ! ... != 0 when ! ... is true |
| 146 | ! ... == 0 when ! ... is false |
| 146 | x != 0 when ! ... is false |

View File

@@ -104,3 +104,7 @@
| test.cpp:122:9:122:9 | b | true | 125 | 125 |
| test.cpp:125:13:125:20 | ! ... | true | 125 | 125 |
| test.cpp:125:14:125:17 | call to safe | false | 125 | 125 |
| test.cpp:131:6:131:21 | call to __builtin_expect | true | 131 | 132 |
| test.cpp:135:6:135:21 | call to __builtin_expect | true | 135 | 136 |
| test.cpp:141:6:141:21 | call to __builtin_expect | true | 141 | 142 |
| test.cpp:145:6:145:21 | call to __builtin_expect | true | 145 | 146 |

View File

@@ -159,6 +159,18 @@ binary
| test.cpp:105:6:105:14 | ... != ... | test.cpp:105:11:105:14 | 0.0 | != | test.cpp:105:6:105:6 | f | 0 | 105 | 106 |
| test.cpp:111:6:111:14 | ... != ... | test.cpp:111:6:111:6 | i | != | test.cpp:111:11:111:14 | 0.0 | 0 | 111 | 112 |
| test.cpp:111:6:111:14 | ... != ... | test.cpp:111:11:111:14 | 0.0 | != | test.cpp:111:6:111:6 | i | 0 | 111 | 112 |
| test.cpp:131:6:131:21 | call to __builtin_expect | test.cpp:131:23:131:23 | a | == | test.cpp:131:28:131:28 | b | 42 | 131 | 132 |
| test.cpp:131:6:131:21 | call to __builtin_expect | test.cpp:131:23:131:23 | a | == | test.cpp:131:28:131:33 | ... + ... | 0 | 131 | 132 |
| test.cpp:131:6:131:21 | call to __builtin_expect | test.cpp:131:28:131:28 | b | == | test.cpp:131:23:131:23 | a | -42 | 131 | 132 |
| test.cpp:131:6:131:21 | call to __builtin_expect | test.cpp:131:28:131:33 | ... + ... | == | test.cpp:131:23:131:23 | a | 0 | 131 | 132 |
| test.cpp:135:6:135:21 | call to __builtin_expect | test.cpp:135:23:135:23 | a | != | test.cpp:135:28:135:28 | b | 42 | 135 | 136 |
| test.cpp:135:6:135:21 | call to __builtin_expect | test.cpp:135:23:135:23 | a | != | test.cpp:135:28:135:33 | ... + ... | 0 | 135 | 136 |
| test.cpp:135:6:135:21 | call to __builtin_expect | test.cpp:135:28:135:28 | b | != | test.cpp:135:23:135:23 | a | -42 | 135 | 136 |
| test.cpp:135:6:135:21 | call to __builtin_expect | test.cpp:135:28:135:33 | ... + ... | != | test.cpp:135:23:135:23 | a | 0 | 135 | 136 |
| test.cpp:141:6:141:21 | call to __builtin_expect | test.cpp:141:23:141:23 | a | == | test.cpp:141:28:141:29 | 42 | 0 | 141 | 142 |
| test.cpp:141:6:141:21 | call to __builtin_expect | test.cpp:141:28:141:29 | 42 | == | test.cpp:141:23:141:23 | a | 0 | 141 | 142 |
| test.cpp:145:6:145:21 | call to __builtin_expect | test.cpp:145:23:145:23 | a | != | test.cpp:145:28:145:29 | 42 | 0 | 145 | 146 |
| test.cpp:145:6:145:21 | call to __builtin_expect | test.cpp:145:28:145:29 | 42 | != | test.cpp:145:23:145:23 | a | 0 | 145 | 146 |
unary
| test.c:7:9:7:13 | ... > ... | test.c:7:9:7:9 | x | < | 1 | 10 | 11 |
| test.c:7:9:7:13 | ... > ... | test.c:7:9:7:9 | x | >= | 1 | 7 | 9 |
@@ -270,3 +282,9 @@ unary
| test.cpp:122:9:122:9 | b | test.cpp:122:9:122:9 | b | != | 0 | 125 | 125 |
| test.cpp:125:13:125:20 | ! ... | test.cpp:125:13:125:20 | ! ... | != | 0 | 125 | 125 |
| test.cpp:125:14:125:17 | call to safe | test.cpp:125:14:125:17 | call to safe | == | 0 | 125 | 125 |
| test.cpp:131:6:131:21 | call to __builtin_expect | test.cpp:131:6:131:21 | call to __builtin_expect | != | 0 | 131 | 132 |
| test.cpp:135:6:135:21 | call to __builtin_expect | test.cpp:135:6:135:21 | call to __builtin_expect | != | 0 | 135 | 136 |
| test.cpp:141:6:141:21 | call to __builtin_expect | test.cpp:141:6:141:21 | call to __builtin_expect | != | 0 | 141 | 142 |
| test.cpp:141:6:141:21 | call to __builtin_expect | test.cpp:141:23:141:23 | a | == | 42 | 141 | 142 |
| test.cpp:145:6:145:21 | call to __builtin_expect | test.cpp:145:6:145:21 | call to __builtin_expect | != | 0 | 145 | 146 |
| test.cpp:145:6:145:21 | call to __builtin_expect | test.cpp:145:23:145:23 | a | != | 42 | 145 | 146 |

View File

@@ -125,4 +125,24 @@ void test(bool b)
if (!safe(x)) return;
}
use(x);
}
void binary_test_builtin_expected(int a, int b) {
if(__builtin_expect(a == b + 42, 0)) {
use(a);
}
if(__builtin_expect(a != b + 42, 0)) {
use(a);
}
}
void unary_test_builtin_expected(int a) {
if(__builtin_expect(a == 42, 0)) {
use(a);
}
if(__builtin_expect(a != 42, 0)) {
use(a);
}
}

View File

@@ -1,6 +1,6 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (additionalEdges.ql:31,6-14)
WARNING: Module DataFlow has been deprecated and may be removed in future (additionalEdges.ql:31,31-39)
WARNING: Module DataFlow has been deprecated and may be removed in future (additionalEdges.ql:32,7-15)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (additionalEdges.ql:31,6-14)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (additionalEdges.ql:31,31-39)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (additionalEdges.ql:32,7-15)
| tryExcept.c:7:7:7:7 | x | tryExcept.c:14:10:14:10 | x |
| tryExcept.c:7:13:7:14 | 0 | tryExcept.c:10:9:10:9 | y |
| tryExcept.c:10:9:10:9 | y | tryExcept.c:10:5:10:9 | ... = ... |

View File

@@ -1,5 +1,5 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (standardEdges.ql:4,6-14)
WARNING: Module DataFlow has been deprecated and may be removed in future (standardEdges.ql:4,31-39)
WARNING: Module DataFlow has been deprecated and may be removed in future (standardEdges.ql:5,7-15)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (standardEdges.ql:4,6-14)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (standardEdges.ql:4,31-39)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (standardEdges.ql:5,7-15)
| tryExcept.c:7:13:7:14 | 0 | tryExcept.c:10:9:10:9 | y |
| tryExcept.c:10:9:10:9 | y | tryExcept.c:10:5:10:9 | ... = ... |

View File

@@ -151,6 +151,9 @@ module IRTest {
or
call.getTarget().getName() = "indirect_sink" and
sink.asIndirectExpr() = e
or
call.getTarget().getName() = "indirect_sink_const_ref" and
sink.asIndirectExpr() = e
)
}

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --edg --clang
// semmle-extractor-options: --clang
int source();
void sink(int); void sink(const int *); void sink(int **); void indirect_sink(...);

View File

@@ -1,3 +1,3 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (has-parameter-flow-out.ql:5,18-61)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (has-parameter-flow-out.ql:5,18-61)
testFailures
failures

View File

@@ -1,6 +1,6 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (localFlow.ql:4,6-14)
WARNING: Module DataFlow has been deprecated and may be removed in future (localFlow.ql:4,31-39)
WARNING: Module DataFlow has been deprecated and may be removed in future (localFlow.ql:6,3-11)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (localFlow.ql:4,6-14)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (localFlow.ql:4,31-39)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (localFlow.ql:6,3-11)
| example.c:15:37:15:37 | b | example.c:15:37:15:37 | b |
| example.c:15:37:15:37 | b | example.c:19:6:19:6 | b |
| example.c:15:44:15:46 | pos | example.c:24:24:24:26 | pos |

View File

@@ -1,3 +1,3 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (test-number-of-outnodes.ql:5,18-61)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (test-number-of-outnodes.ql:5,18-61)
failures
testFailures

View File

@@ -1,5 +1,5 @@
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)
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 |
@@ -313,6 +313,7 @@ irFlow
| test.cpp:1021:18:1021:32 | *call to indirect_source | test.cpp:1027:19:1027:28 | *translated |
| test.cpp:1021:18:1021:32 | *call to indirect_source | test.cpp:1031:19:1031:28 | *translated |
| test.cpp:1045:14:1045:19 | call to source | test.cpp:1046:7:1046:10 | * ... |
| test.cpp:1081:27:1081:34 | call to source | test.cpp:1081:27:1081:34 | call to source |
| 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 |

View File

@@ -1073,3 +1073,10 @@ void single_object_in_both_cases(bool b, int x, int y) {
*p = 0;
sink(*p); // clean
}
template<typename T>
void indirect_sink_const_ref(const T&);
void test_temp_with_conversion_from_materialization() {
indirect_sink_const_ref(source()); // $ ir MISSING: ast
}

View File

@@ -1,4 +1,4 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (partial-definition-diff.ql:7,8-51)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (partial-definition-diff.ql:7,8-51)
| A.cpp:25:13:25:13 | c | AST only |
| A.cpp:27:28:27:28 | c | AST only |
| A.cpp:28:23:28:26 | this | IR only |

View File

@@ -1,4 +1,4 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (partial-definition.ql:6,8-51)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (partial-definition.ql:6,8-51)
| A.cpp:25:7:25:10 | this |
| A.cpp:25:13:25:13 | c |
| A.cpp:27:22:27:25 | this |

View File

@@ -1,6 +1,6 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (taint.ql:6,48-56)
WARNING: Module DataFlow has been deprecated and may be removed in future (taint.ql:7,24-32)
WARNING: Module DataFlow has been deprecated and may be removed in future (taint.ql:11,22-30)
WARNING: Module TaintTracking has been deprecated and may be removed in future (taint.ql:19,20-33)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (taint.ql:6,48-56)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (taint.ql:7,24-32)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (taint.ql:11,22-30)
WARNING: module 'TaintTracking' has been deprecated and may be removed in future (taint.ql:19,20-33)
failures
testFailures

View File

@@ -1,7 +1,7 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (localTaint.ql:4,6-14)
WARNING: Module DataFlow has been deprecated and may be removed in future (localTaint.ql:4,31-39)
WARNING: Module DataFlow has been deprecated and may be removed in future (localTaint.ql:7,6-14)
WARNING: Module TaintTracking has been deprecated and may be removed in future (localTaint.ql:6,3-16)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (localTaint.ql:4,6-14)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (localTaint.ql:4,31-39)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (localTaint.ql:7,6-14)
WARNING: module 'TaintTracking' has been deprecated and may be removed in future (localTaint.ql:6,3-16)
| arrayassignment.cpp:9:9:9:10 | 0 | arrayassignment.cpp:10:14:10:14 | x | |
| arrayassignment.cpp:9:9:9:10 | 0 | arrayassignment.cpp:11:15:11:15 | x | |
| arrayassignment.cpp:9:9:9:10 | 0 | arrayassignment.cpp:12:13:12:13 | x | |

View File

@@ -1,7 +1,7 @@
WARNING: Module DataFlow has been deprecated and may be removed in future (taint.ql:46,45-53)
WARNING: Module DataFlow has been deprecated and may be removed in future (taint.ql:47,24-32)
WARNING: Module DataFlow has been deprecated and may be removed in future (taint.ql:61,22-30)
WARNING: Module DataFlow has been deprecated and may be removed in future (taint.ql:68,25-33)
WARNING: Module TaintTracking has been deprecated and may be removed in future (taint.ql:73,20-33)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (taint.ql:46,45-53)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (taint.ql:47,24-32)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (taint.ql:61,22-30)
WARNING: module 'DataFlow' has been deprecated and may be removed in future (taint.ql:68,25-33)
WARNING: module 'TaintTracking' has been deprecated and may be removed in future (taint.ql:73,20-33)
testFailures
failures

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --edg --microsoft
// semmle-extractor-options: --microsoft
void f(__declspec(guard(overflow)) size_t length) {
}

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --edg --clang --edg --c++20
// semmle-extractor-options: --clang --edg --c++20
namespace cpp20 {

View File

@@ -7,4 +7,4 @@ struct Kiwi {
struct Lemon {
unsigned int __attribute__ ((vector_size (16))) lemon_x;
};
// semmle-extractor-options: --edg --c99 --edg --clang --edg --clang_vector_types --gnu_version 40700
// semmle-extractor-options: --edg --c99 --clang --edg --clang_vector_types --gnu_version 40700

View File

@@ -7,4 +7,4 @@ struct Kiwi {
struct Lemon {
signed int __attribute__ ((vector_size (16))) lemon_x;
};
// semmle-extractor-options: --edg --c99 --edg --clang --edg --clang_vector_types --gnu_version 40700
// semmle-extractor-options: --edg --c99 --clang --edg --clang_vector_types --gnu_version 40700

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --edg --clang --edg --ms_extensions
// semmle-extractor-options: --clang --edg --ms_extensions
template <int a> class b {
template <bool> struct c;

View File

@@ -1 +1 @@
semmle-extractor-options: --edg --clang --edg --clang_builtin_functions --edg --clang_vector_types --gnu_version 40600
semmle-extractor-options: --clang --edg --clang_builtin_functions --edg --clang_vector_types --gnu_version 40600

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --edg --clang --edg --clang_version --edg 30801
// semmle-extractor-options: --clang --edg --clang_version --edg 30801
// Compilable with: clang --std=c++0x -msse4.1 vector_types.cpp
// (some bits also compilable with gcc)
int printf(...);

View File

@@ -13,21 +13,6 @@ edges
| test_free.cpp:207:10:207:10 | pointer to free output argument | test_free.cpp:209:10:209:10 | a | provenance | |
| test_free.cpp:301:12:301:14 | pointer to g_free output argument | test_free.cpp:302:12:302:14 | buf | provenance | |
| test_free.cpp:319:16:319:16 | pointer to operator delete output argument | test_free.cpp:322:12:322:12 | a | provenance | |
| test_free.cpp:343:12:343:24 | *access to array [post update] [ptr] | test_free.cpp:344:12:344:24 | *access to array [ptr] | provenance | |
| test_free.cpp:343:12:343:24 | *access to array [post update] [ptr] | test_free.cpp:345:12:345:24 | *access to array [ptr] | provenance | |
| test_free.cpp:343:12:343:24 | *access to array [post update] [ptr] | test_free.cpp:346:12:346:24 | *access to array [ptr] | provenance | |
| test_free.cpp:343:26:343:28 | pointer to operator delete output argument | test_free.cpp:343:12:343:24 | *access to array [post update] [ptr] | provenance | |
| test_free.cpp:344:12:344:24 | *access to array [post update] [ptr] | test_free.cpp:345:12:345:24 | *access to array [ptr] | provenance | |
| test_free.cpp:344:12:344:24 | *access to array [post update] [ptr] | test_free.cpp:346:12:346:24 | *access to array [ptr] | provenance | |
| test_free.cpp:344:12:344:24 | *access to array [ptr] | test_free.cpp:344:26:344:28 | ptr | provenance | |
| test_free.cpp:344:26:344:28 | pointer to operator delete output argument | test_free.cpp:344:12:344:24 | *access to array [post update] [ptr] | provenance | |
| test_free.cpp:345:12:345:24 | *access to array [post update] [ptr] | test_free.cpp:346:12:346:24 | *access to array [ptr] | provenance | |
| test_free.cpp:345:12:345:24 | *access to array [ptr] | test_free.cpp:345:26:345:28 | ptr | provenance | |
| test_free.cpp:345:12:345:24 | *access to array [ptr] | test_free.cpp:345:26:345:28 | ptr | provenance | |
| test_free.cpp:345:26:345:28 | pointer to operator delete output argument | test_free.cpp:345:12:345:24 | *access to array [post update] [ptr] | provenance | |
| test_free.cpp:346:12:346:24 | *access to array [ptr] | test_free.cpp:346:26:346:28 | ptr | provenance | |
| test_free.cpp:346:12:346:24 | *access to array [ptr] | test_free.cpp:346:26:346:28 | ptr | provenance | |
| test_free.cpp:346:12:346:24 | *access to array [ptr] | test_free.cpp:346:26:346:28 | ptr | provenance | |
nodes
| test_free.cpp:11:10:11:10 | pointer to free output argument | semmle.label | pointer to free output argument |
| test_free.cpp:14:10:14:10 | a | semmle.label | a |
@@ -57,24 +42,6 @@ nodes
| test_free.cpp:302:12:302:14 | buf | semmle.label | buf |
| test_free.cpp:319:16:319:16 | pointer to operator delete output argument | semmle.label | pointer to operator delete output argument |
| test_free.cpp:322:12:322:12 | a | semmle.label | a |
| test_free.cpp:343:12:343:24 | *access to array [post update] [ptr] | semmle.label | *access to array [post update] [ptr] |
| test_free.cpp:343:26:343:28 | pointer to operator delete output argument | semmle.label | pointer to operator delete output argument |
| test_free.cpp:344:12:344:24 | *access to array [post update] [ptr] | semmle.label | *access to array [post update] [ptr] |
| test_free.cpp:344:12:344:24 | *access to array [ptr] | semmle.label | *access to array [ptr] |
| test_free.cpp:344:26:344:28 | pointer to operator delete output argument | semmle.label | pointer to operator delete output argument |
| test_free.cpp:344:26:344:28 | ptr | semmle.label | ptr |
| test_free.cpp:345:12:345:24 | *access to array [post update] [ptr] | semmle.label | *access to array [post update] [ptr] |
| test_free.cpp:345:12:345:24 | *access to array [ptr] | semmle.label | *access to array [ptr] |
| test_free.cpp:345:12:345:24 | *access to array [ptr] | semmle.label | *access to array [ptr] |
| test_free.cpp:345:26:345:28 | pointer to operator delete output argument | semmle.label | pointer to operator delete output argument |
| test_free.cpp:345:26:345:28 | ptr | semmle.label | ptr |
| test_free.cpp:345:26:345:28 | ptr | semmle.label | ptr |
| test_free.cpp:346:12:346:24 | *access to array [ptr] | semmle.label | *access to array [ptr] |
| test_free.cpp:346:12:346:24 | *access to array [ptr] | semmle.label | *access to array [ptr] |
| test_free.cpp:346:12:346:24 | *access to array [ptr] | semmle.label | *access to array [ptr] |
| test_free.cpp:346:26:346:28 | ptr | semmle.label | ptr |
| test_free.cpp:346:26:346:28 | ptr | semmle.label | ptr |
| test_free.cpp:346:26:346:28 | ptr | semmle.label | ptr |
subpaths
#select
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:14:10:14:10 | a | Memory pointed to by $@ may already have been freed by $@. | test_free.cpp:14:10:14:10 | a | a | test_free.cpp:11:5:11:8 | call to free | call to free |
@@ -91,9 +58,3 @@ subpaths
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | pointer to free output argument | test_free.cpp:209:10:209:10 | a | Memory pointed to by $@ may already have been freed by $@. | test_free.cpp:209:10:209:10 | a | a | test_free.cpp:207:5:207:8 | call to free | call to free |
| test_free.cpp:302:12:302:14 | buf | test_free.cpp:301:12:301:14 | pointer to g_free output argument | test_free.cpp:302:12:302:14 | buf | Memory pointed to by $@ may already have been freed by $@. | test_free.cpp:302:12:302:14 | buf | buf | test_free.cpp:301:5:301:10 | call to g_free | call to g_free |
| test_free.cpp:322:12:322:12 | a | test_free.cpp:319:16:319:16 | pointer to operator delete output argument | test_free.cpp:322:12:322:12 | a | Memory pointed to by $@ may already have been freed by $@. | test_free.cpp:322:12:322:12 | a | a | test_free.cpp:319:9:319:16 | delete | delete |
| test_free.cpp:344:26:344:28 | ptr | test_free.cpp:343:26:343:28 | pointer to operator delete output argument | test_free.cpp:344:26:344:28 | ptr | Memory pointed to by $@ may already have been freed by $@. | test_free.cpp:344:26:344:28 | ptr | ptr | test_free.cpp:343:5:343:28 | delete | delete |
| test_free.cpp:345:26:345:28 | ptr | test_free.cpp:343:26:343:28 | pointer to operator delete output argument | test_free.cpp:345:26:345:28 | ptr | Memory pointed to by $@ may already have been freed by $@. | test_free.cpp:345:26:345:28 | ptr | ptr | test_free.cpp:343:5:343:28 | delete | delete |
| test_free.cpp:345:26:345:28 | ptr | test_free.cpp:344:26:344:28 | pointer to operator delete output argument | test_free.cpp:345:26:345:28 | ptr | Memory pointed to by $@ may already have been freed by $@. | test_free.cpp:345:26:345:28 | ptr | ptr | test_free.cpp:344:5:344:28 | delete | delete |
| test_free.cpp:346:26:346:28 | ptr | test_free.cpp:343:26:343:28 | pointer to operator delete output argument | test_free.cpp:346:26:346:28 | ptr | Memory pointed to by $@ may already have been freed by $@. | test_free.cpp:346:26:346:28 | ptr | ptr | test_free.cpp:343:5:343:28 | delete | delete |
| test_free.cpp:346:26:346:28 | ptr | test_free.cpp:344:26:344:28 | pointer to operator delete output argument | test_free.cpp:346:26:346:28 | ptr | Memory pointed to by $@ may already have been freed by $@. | test_free.cpp:346:26:346:28 | ptr | ptr | test_free.cpp:344:5:344:28 | delete | delete |
| test_free.cpp:346:26:346:28 | ptr | test_free.cpp:345:26:345:28 | pointer to operator delete output argument | test_free.cpp:346:26:346:28 | ptr | Memory pointed to by $@ may already have been freed by $@. | test_free.cpp:346:26:346:28 | ptr | ptr | test_free.cpp:345:5:345:28 | delete | delete |

View File

@@ -115,6 +115,8 @@
| test_free.cpp:344:26:344:28 | ptr |
| test_free.cpp:345:26:345:28 | ptr |
| test_free.cpp:346:26:346:28 | ptr |
| test_free.cpp:356:19:356:19 | a |
| test_free.cpp:357:19:357:19 | a |
| virtual.cpp:18:10:18:10 | a |
| virtual.cpp:19:10:19:10 | c |
| virtual.cpp:38:10:38:10 | b |

View File

@@ -341,7 +341,18 @@ struct PtrContainer {
void test_array(PtrContainer *containers) {
delete containers[0].ptr; // GOOD
delete containers[1].ptr; // GOOD [FALSE POSITIVE]
delete containers[2].ptr; // GOOD [FALSE POSITIVE]
delete containers[2].ptr; // BAD (double free)
delete containers[1].ptr; // GOOD
delete containers[2].ptr; // GOOD
delete containers[2].ptr; // BAD (double free) [NOT DETECTED]
}
struct E {
struct EC {
int* a;
} ec[2];
};
void test(E* e) {
free(e->ec[0].a);
free(e->ec[1].a); // GOOD
}

View File

@@ -1,15 +1,15 @@
| test.cpp:21:9:21:15 | new | This allocation cannot return null. $@ is unnecessary. | test.cpp:21:9:21:15 | new | This check |
| test.cpp:21:9:21:15 | new | This allocation cannot return null. $@ is unnecessary. | test.cpp:21:7:21:16 | ! ... | This check |
| test.cpp:29:13:29:24 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:30:7:30:13 | ... == ... | This check |
| test.cpp:33:13:33:24 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:34:8:34:9 | p2 | This check |
| test.cpp:33:13:33:24 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:34:7:34:9 | ! ... | This check |
| test.cpp:37:13:37:24 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:38:7:38:16 | ... == ... | This check |
| test.cpp:41:13:41:24 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:42:7:42:19 | ... == ... | This check |
| test.cpp:45:13:45:24 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:46:7:46:8 | p5 | This check |
| test.cpp:49:8:49:19 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:50:7:50:13 | ... == ... | This check |
| test.cpp:53:8:53:19 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:54:8:54:9 | p7 | This check |
| test.cpp:53:8:53:19 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:54:7:54:9 | ! ... | This check |
| test.cpp:58:8:58:19 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:59:7:59:16 | ... == ... | This check |
| test.cpp:63:8:63:19 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:64:7:64:19 | ... != ... | This check |
| test.cpp:69:9:69:20 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:70:7:70:14 | ... != ... | This check |
| test.cpp:75:11:75:22 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:76:13:76:15 | p11 | This check |
| test.cpp:75:11:75:22 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:76:12:76:15 | ! ... | This check |
| test.cpp:92:5:92:31 | new[] | This allocation cannot throw. $@ is unnecessary. | test.cpp:97:36:98:3 | { ... } | This catch block |
| test.cpp:93:15:93:41 | new[] | This allocation cannot throw. $@ is unnecessary. | test.cpp:97:36:98:3 | { ... } | This catch block |
| test.cpp:96:10:96:36 | new[] | This allocation cannot throw. $@ is unnecessary. | test.cpp:97:36:98:3 | { ... } | This catch block |