mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge branch 'master' into init-dynamic-alloc-newexpr
This commit is contained in:
@@ -30,7 +30,13 @@ predicate functionsMissingReturnStmt(Function f, ControlFlowNode blame) {
|
||||
) and
|
||||
exists(ReturnStmt s |
|
||||
f.getAPredecessor() = s and
|
||||
blame = s.getAPredecessor()
|
||||
(
|
||||
blame = s.getAPredecessor() and
|
||||
count(blame.getASuccessor()) = 1
|
||||
or
|
||||
blame = s and
|
||||
exists(ControlFlowNode pred | pred = s.getAPredecessor() | count(pred.getASuccessor()) != 1)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
override string toString() { result = p + ": " + ap }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
@@ -2482,13 +2484,15 @@ pragma[nomagic]
|
||||
private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret |
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret, int pos |
|
||||
mid.getNode() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
config = mid.getConfiguration() and
|
||||
ap = mid.getAp()
|
||||
ap = mid.getAp() and
|
||||
pos = sc.getParameterPos() and
|
||||
not kind.(ParamUpdateReturnKind).getPosition() = pos
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
override string toString() { result = p + ": " + ap }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
@@ -2482,13 +2484,15 @@ pragma[nomagic]
|
||||
private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret |
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret, int pos |
|
||||
mid.getNode() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
config = mid.getConfiguration() and
|
||||
ap = mid.getAp()
|
||||
ap = mid.getAp() and
|
||||
pos = sc.getParameterPos() and
|
||||
not kind.(ParamUpdateReturnKind).getPosition() = pos
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
override string toString() { result = p + ": " + ap }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
@@ -2482,13 +2484,15 @@ pragma[nomagic]
|
||||
private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret |
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret, int pos |
|
||||
mid.getNode() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
config = mid.getConfiguration() and
|
||||
ap = mid.getAp()
|
||||
ap = mid.getAp() and
|
||||
pos = sc.getParameterPos() and
|
||||
not kind.(ParamUpdateReturnKind).getPosition() = pos
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
override string toString() { result = p + ": " + ap }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
@@ -2482,13 +2484,15 @@ pragma[nomagic]
|
||||
private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret |
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret, int pos |
|
||||
mid.getNode() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
config = mid.getConfiguration() and
|
||||
ap = mid.getAp()
|
||||
ap = mid.getAp() and
|
||||
pos = sc.getParameterPos() and
|
||||
not kind.(ParamUpdateReturnKind).getPosition() = pos
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
override string toString() { result = p + ": " + ap }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
@@ -2482,13 +2484,15 @@ pragma[nomagic]
|
||||
private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret |
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret, int pos |
|
||||
mid.getNode() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
config = mid.getConfiguration() and
|
||||
ap = mid.getAp()
|
||||
ap = mid.getAp() and
|
||||
pos = sc.getParameterPos() and
|
||||
not kind.(ParamUpdateReturnKind).getPosition() = pos
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import semmle.code.cpp.Element
|
||||
private import semmle.code.cpp.Enclosing
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
private import semmle.code.cpp.internal.AddressConstantExpression
|
||||
private import semmle.code.cpp.models.implementations.Allocation
|
||||
|
||||
/**
|
||||
* A C/C++ expression.
|
||||
@@ -804,8 +805,10 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
|
||||
* call the constructor of `T` but will not allocate memory.
|
||||
*/
|
||||
Expr getPlacementPointer() {
|
||||
isStandardPlacementNewAllocator(this.getAllocator()) and
|
||||
result = this.getAllocatorCall().getArgument(1)
|
||||
result =
|
||||
this
|
||||
.getAllocatorCall()
|
||||
.getArgument(this.getAllocator().(OperatorNewAllocationFunction).getPlacementArgument())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1194,12 +1197,6 @@ private predicate convparents(Expr child, int idx, Element parent) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isStandardPlacementNewAllocator(Function operatorNew) {
|
||||
operatorNew.getName().matches("operator new%") and
|
||||
operatorNew.getNumberOfParameters() = 2 and
|
||||
operatorNew.getParameter(1).getType() instanceof VoidPointerType
|
||||
}
|
||||
|
||||
// Pulled out for performance. See QL-796.
|
||||
private predicate hasNoConversions(Expr e) { not e.hasConversion() }
|
||||
|
||||
|
||||
@@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
override string toString() { result = p + ": " + ap }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
@@ -2482,13 +2484,15 @@ pragma[nomagic]
|
||||
private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret |
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret, int pos |
|
||||
mid.getNode() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
config = mid.getConfiguration() and
|
||||
ap = mid.getAp()
|
||||
ap = mid.getAp() and
|
||||
pos = sc.getParameterPos() and
|
||||
not kind.(ParamUpdateReturnKind).getPosition() = pos
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
override string toString() { result = p + ": " + ap }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
@@ -2482,13 +2484,15 @@ pragma[nomagic]
|
||||
private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret |
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret, int pos |
|
||||
mid.getNode() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
config = mid.getConfiguration() and
|
||||
ap = mid.getAp()
|
||||
ap = mid.getAp() and
|
||||
pos = sc.getParameterPos() and
|
||||
not kind.(ParamUpdateReturnKind).getPosition() = pos
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
override string toString() { result = p + ": " + ap }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
@@ -2482,13 +2484,15 @@ pragma[nomagic]
|
||||
private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret |
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret, int pos |
|
||||
mid.getNode() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
config = mid.getConfiguration() and
|
||||
ap = mid.getAp()
|
||||
ap = mid.getAp() and
|
||||
pos = sc.getParameterPos() and
|
||||
not kind.(ParamUpdateReturnKind).getPosition() = pos
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
override string toString() { result = p + ": " + ap }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
@@ -2482,13 +2484,15 @@ pragma[nomagic]
|
||||
private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret |
|
||||
exists(PathNodeMid mid, ReturnNodeExt ret, int pos |
|
||||
mid.getNode() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
sc = mid.getSummaryCtx() and
|
||||
config = mid.getConfiguration() and
|
||||
ap = mid.getAp()
|
||||
ap = mid.getAp() and
|
||||
pos = sc.getParameterPos() and
|
||||
not kind.(ParamUpdateReturnKind).getPosition() = pos
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -215,6 +215,40 @@ class SizelessAllocationFunction extends AllocationFunction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An `operator new` or `operator new[]` function that may be associated with `new` or
|
||||
* `new[]` expressions. Note that `new` and `new[]` are not function calls, but these
|
||||
* functions may also be called directly.
|
||||
*/
|
||||
class OperatorNewAllocationFunction extends AllocationFunction {
|
||||
OperatorNewAllocationFunction() {
|
||||
exists(string name |
|
||||
hasGlobalName(name) and
|
||||
(
|
||||
// operator new(bytes, ...)
|
||||
name = "operator new"
|
||||
or
|
||||
// operator new[](bytes, ...)
|
||||
name = "operator new[]"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override int getSizeArg() { result = 0 }
|
||||
|
||||
override predicate requiresDealloc() { not exists(getPlacementArgument()) }
|
||||
|
||||
/**
|
||||
* Gets the position of the placement pointer if this is a placement
|
||||
* `operator new` function.
|
||||
*/
|
||||
int getPlacementArgument() {
|
||||
getNumberOfParameters() = 2 and
|
||||
getParameter(1).getType() instanceof VoidPointerType and
|
||||
result = 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An allocation expression that is a function call, such as call to `malloc`.
|
||||
*/
|
||||
@@ -227,7 +261,9 @@ class CallAllocationExpr extends AllocationExpr, FunctionCall {
|
||||
not (
|
||||
exists(target.getReallocPtrArg()) and
|
||||
getArgument(target.getSizeArg()).getValue().toInt() = 0
|
||||
)
|
||||
) and
|
||||
// these are modelled directly (and more accurately), avoid duplication
|
||||
not exists(NewOrNewArrayExpr new | new.getAllocatorCall() = this)
|
||||
}
|
||||
|
||||
override Expr getSizeExpr() { result = getArgument(target.getSizeArg()) }
|
||||
|
||||
@@ -79,6 +79,28 @@ class StandardDeallocationFunction extends DeallocationFunction {
|
||||
override int getFreedArg() { result = freedArg }
|
||||
}
|
||||
|
||||
/**
|
||||
* An `operator delete` or `operator delete[]` function that may be associated
|
||||
* with `delete` or `delete[]` expressions. Note that `delete` and `delete[]`
|
||||
* are not function calls, but these functions may also be called directly.
|
||||
*/
|
||||
class OperatorDeleteDeallocationFunction extends DeallocationFunction {
|
||||
OperatorDeleteDeallocationFunction() {
|
||||
exists(string name |
|
||||
hasGlobalName(name) and
|
||||
(
|
||||
// operator delete(pointer, ...)
|
||||
name = "operator delete"
|
||||
or
|
||||
// operator delete[](pointer, ...)
|
||||
name = "operator delete[]"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override int getFreedArg() { result = 0 }
|
||||
}
|
||||
|
||||
/**
|
||||
* An deallocation expression that is a function call, such as call to `free`.
|
||||
*/
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/**
|
||||
* The standard function `strcat` and its wide, sized, and Microsoft variants.
|
||||
*/
|
||||
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction {
|
||||
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction {
|
||||
StrcatFunction() {
|
||||
exists(string name | name = getName() |
|
||||
name = "strcat" or // strcat(dst, src)
|
||||
@@ -56,4 +57,19 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction {
|
||||
override predicate hasArrayWithNullTerminator(int param) { param = 1 }
|
||||
|
||||
override predicate hasArrayWithUnknownSize(int param) { param = 0 }
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = 0 and
|
||||
buffer = true and
|
||||
mustWrite = false
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
(i = 0 or i = 1) and
|
||||
buffer = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/**
|
||||
* The standard function `strcpy` and its wide, sized, and Microsoft variants.
|
||||
*/
|
||||
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction {
|
||||
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
|
||||
StrcpyFunction() {
|
||||
this.hasName("strcpy") or
|
||||
this.hasName("_mbscpy") or
|
||||
@@ -74,4 +75,23 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction {
|
||||
output.isReturnValueDeref()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = 0 and
|
||||
buffer = true and
|
||||
mustWrite = false
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = 1 and
|
||||
buffer = true
|
||||
}
|
||||
|
||||
override ParameterIndex getParameterSizeIndex(ParameterIndex i) {
|
||||
hasArrayWithVariableSize(i, result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,3 +143,9 @@ void multidimensionalNew(int x, int y) {
|
||||
auto p2 = new char[20][20];
|
||||
auto p3 = new char[x][30][30];
|
||||
}
|
||||
|
||||
void directOperatorCall() {
|
||||
void *ptr;
|
||||
ptr = operator new(sizeof(int));
|
||||
operator delete(ptr);
|
||||
}
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
newExprs
|
||||
| allocators.cpp:49:3:49:9 | new | int | operator new(unsigned long) -> void * | 4 | 4 | |
|
||||
| allocators.cpp:50:3:50:15 | new | int | operator new(size_t, float) -> void * | 4 | 4 | |
|
||||
| allocators.cpp:51:3:51:11 | new | int | operator new(unsigned long) -> void * | 4 | 4 | |
|
||||
| allocators.cpp:52:3:52:14 | new | String | operator new(unsigned long) -> void * | 8 | 8 | |
|
||||
| allocators.cpp:53:3:53:27 | new | String | operator new(size_t, float) -> void * | 8 | 8 | |
|
||||
| allocators.cpp:54:3:54:17 | new | Overaligned | operator new(unsigned long, align_val_t) -> void * | 256 | 128 | aligned |
|
||||
| allocators.cpp:55:3:55:25 | new | Overaligned | operator new(size_t, align_val_t, float) -> void * | 256 | 128 | aligned |
|
||||
| allocators.cpp:107:3:107:18 | new | FailedInit | FailedInit::operator new(size_t) -> void * | 1 | 1 | |
|
||||
| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | FailedInitOveraligned::operator new(size_t, align_val_t, float) -> void * | 128 | 128 | aligned |
|
||||
| allocators.cpp:129:3:129:21 | new | int | operator new(size_t, void *) -> void * | 4 | 4 | |
|
||||
| allocators.cpp:135:3:135:26 | new | int | operator new(size_t, const nothrow_t &) -> void * | 4 | 4 | |
|
||||
| allocators.cpp:49:3:49:9 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | |
|
||||
| allocators.cpp:50:3:50:15 | new | int | operator new(size_t, float) -> void * | 4 | 4 | | |
|
||||
| allocators.cpp:51:3:51:11 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | |
|
||||
| allocators.cpp:52:3:52:14 | new | String | operator new(unsigned long) -> void * | 8 | 8 | | |
|
||||
| allocators.cpp:53:3:53:27 | new | String | operator new(size_t, float) -> void * | 8 | 8 | | |
|
||||
| allocators.cpp:54:3:54:17 | new | Overaligned | operator new(unsigned long, align_val_t) -> void * | 256 | 128 | aligned | |
|
||||
| allocators.cpp:55:3:55:25 | new | Overaligned | operator new(size_t, align_val_t, float) -> void * | 256 | 128 | aligned | |
|
||||
| allocators.cpp:107:3:107:18 | new | FailedInit | FailedInit::operator new(size_t) -> void * | 1 | 1 | | |
|
||||
| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | FailedInitOveraligned::operator new(size_t, align_val_t, float) -> void * | 128 | 128 | aligned | |
|
||||
| allocators.cpp:129:3:129:21 | new | int | operator new(size_t, void *) -> void * | 4 | 4 | | & ... |
|
||||
| allocators.cpp:135:3:135:26 | new | int | operator new(size_t, const nothrow_t &) -> void * | 4 | 4 | | |
|
||||
newArrayExprs
|
||||
| allocators.cpp:68:3:68:12 | new[] | int[] | int | operator new[](unsigned long) -> void * | 4 | 4 | | n |
|
||||
| allocators.cpp:69:3:69:18 | new[] | int[] | int | operator new[](size_t, float) -> void * | 4 | 4 | | n |
|
||||
| allocators.cpp:70:3:70:15 | new[] | String[] | String | operator new[](unsigned long) -> void * | 8 | 8 | | n |
|
||||
| allocators.cpp:71:3:71:20 | new[] | Overaligned[] | Overaligned | operator new[](unsigned long, align_val_t) -> void * | 256 | 128 | aligned | n |
|
||||
| allocators.cpp:72:3:72:16 | new[] | String[10] | String | operator new[](unsigned long) -> void * | 8 | 8 | | |
|
||||
| allocators.cpp:108:3:108:19 | new[] | FailedInit[] | FailedInit | FailedInit::operator new[](size_t) -> void * | 1 | 1 | | n |
|
||||
| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | FailedInitOveraligned::operator new[](size_t, align_val_t, float) -> void * | 128 | 128 | aligned | |
|
||||
| allocators.cpp:132:3:132:17 | new[] | int[1] | int | operator new[](size_t, void *) -> void * | 4 | 4 | | |
|
||||
| allocators.cpp:136:3:136:26 | new[] | int[2] | int | operator new[](size_t, const nothrow_t &) -> void * | 4 | 4 | | |
|
||||
| allocators.cpp:142:13:142:27 | new[] | char[][10] | char[10] | operator new[](unsigned long) -> void * | 10 | 1 | | x |
|
||||
| allocators.cpp:143:13:143:28 | new[] | char[20][20] | char[20] | operator new[](unsigned long) -> void * | 20 | 1 | | |
|
||||
| allocators.cpp:144:13:144:31 | new[] | char[][30][30] | char[30][30] | operator new[](unsigned long) -> void * | 900 | 1 | | x |
|
||||
| allocators.cpp:68:3:68:12 | new[] | int[] | int | operator new[](unsigned long) -> void * | 4 | 4 | | n | |
|
||||
| allocators.cpp:69:3:69:18 | new[] | int[] | int | operator new[](size_t, float) -> void * | 4 | 4 | | n | |
|
||||
| allocators.cpp:70:3:70:15 | new[] | String[] | String | operator new[](unsigned long) -> void * | 8 | 8 | | n | |
|
||||
| allocators.cpp:71:3:71:20 | new[] | Overaligned[] | Overaligned | operator new[](unsigned long, align_val_t) -> void * | 256 | 128 | aligned | n | |
|
||||
| allocators.cpp:72:3:72:16 | new[] | String[10] | String | operator new[](unsigned long) -> void * | 8 | 8 | | | |
|
||||
| allocators.cpp:108:3:108:19 | new[] | FailedInit[] | FailedInit | FailedInit::operator new[](size_t) -> void * | 1 | 1 | | n | |
|
||||
| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | FailedInitOveraligned::operator new[](size_t, align_val_t, float) -> void * | 128 | 128 | aligned | | |
|
||||
| allocators.cpp:132:3:132:17 | new[] | int[1] | int | operator new[](size_t, void *) -> void * | 4 | 4 | | | buf |
|
||||
| allocators.cpp:136:3:136:26 | new[] | int[2] | int | operator new[](size_t, const nothrow_t &) -> void * | 4 | 4 | | | |
|
||||
| allocators.cpp:142:13:142:27 | new[] | char[][10] | char[10] | operator new[](unsigned long) -> void * | 10 | 1 | | x | |
|
||||
| allocators.cpp:143:13:143:28 | new[] | char[20][20] | char[20] | operator new[](unsigned long) -> void * | 20 | 1 | | | |
|
||||
| allocators.cpp:144:13:144:31 | new[] | char[][30][30] | char[30][30] | operator new[](unsigned long) -> void * | 900 | 1 | | x | |
|
||||
newExprDeallocators
|
||||
| allocators.cpp:52:3:52:14 | new | String | operator delete(void *, unsigned long) -> void | 8 | 8 | sized |
|
||||
| allocators.cpp:53:3:53:27 | new | String | operator delete(void *, float) -> void | 8 | 8 | |
|
||||
@@ -46,3 +46,65 @@ deleteArrayExprs
|
||||
| allocators.cpp:81:3:81:45 | delete[] | Overaligned | operator delete[](void *, unsigned long, align_val_t) -> void | 256 | 128 | sized aligned |
|
||||
| allocators.cpp:82:3:82:49 | delete[] | PolymorphicBase | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized |
|
||||
| allocators.cpp:83:3:83:23 | delete[] | int | operator delete[](void *, unsigned long) -> void | 4 | 4 | sized |
|
||||
allocationFunctions
|
||||
| allocators.cpp:7:7:7:18 | operator new | getSizeArg = 0, requiresDealloc |
|
||||
| allocators.cpp:8:7:8:20 | operator new[] | getSizeArg = 0, requiresDealloc |
|
||||
| allocators.cpp:9:7:9:18 | operator new | getSizeArg = 0, requiresDealloc |
|
||||
| allocators.cpp:10:7:10:20 | operator new[] | getSizeArg = 0, requiresDealloc |
|
||||
| allocators.cpp:121:7:121:18 | operator new | getPlacementArgument = 1, getSizeArg = 0 |
|
||||
| allocators.cpp:122:7:122:20 | operator new[] | getPlacementArgument = 1, getSizeArg = 0 |
|
||||
| allocators.cpp:123:7:123:18 | operator new | getSizeArg = 0, requiresDealloc |
|
||||
| allocators.cpp:124:7:124:20 | operator new[] | getSizeArg = 0, requiresDealloc |
|
||||
| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc |
|
||||
| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc |
|
||||
| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc |
|
||||
| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc |
|
||||
allocationExprs
|
||||
| allocators.cpp:49:3:49:9 | new | getSizeBytes = 4, requiresDealloc |
|
||||
| allocators.cpp:50:3:50:15 | new | getSizeBytes = 4, requiresDealloc |
|
||||
| allocators.cpp:51:3:51:11 | new | getSizeBytes = 4, requiresDealloc |
|
||||
| allocators.cpp:52:3:52:14 | new | getSizeBytes = 8, requiresDealloc |
|
||||
| allocators.cpp:53:3:53:27 | new | getSizeBytes = 8, requiresDealloc |
|
||||
| allocators.cpp:54:3:54:17 | new | getSizeBytes = 256, requiresDealloc |
|
||||
| allocators.cpp:55:3:55:25 | new | getSizeBytes = 256, requiresDealloc |
|
||||
| allocators.cpp:68:3:68:12 | new[] | getSizeExpr = n, getSizeMult = 4, requiresDealloc |
|
||||
| allocators.cpp:69:3:69:18 | new[] | getSizeExpr = n, getSizeMult = 4, requiresDealloc |
|
||||
| allocators.cpp:70:3:70:15 | new[] | getSizeExpr = n, getSizeMult = 8, requiresDealloc |
|
||||
| allocators.cpp:71:3:71:20 | new[] | getSizeExpr = n, getSizeMult = 256, requiresDealloc |
|
||||
| allocators.cpp:72:3:72:16 | new[] | getSizeBytes = 80, requiresDealloc |
|
||||
| allocators.cpp:107:3:107:18 | new | getSizeBytes = 1, requiresDealloc |
|
||||
| allocators.cpp:108:3:108:19 | new[] | getSizeExpr = n, getSizeMult = 1, requiresDealloc |
|
||||
| allocators.cpp:109:3:109:35 | new | getSizeBytes = 128, requiresDealloc |
|
||||
| allocators.cpp:110:3:110:37 | new[] | getSizeBytes = 1280, requiresDealloc |
|
||||
| allocators.cpp:129:3:129:21 | new | getSizeBytes = 4 |
|
||||
| allocators.cpp:132:3:132:17 | new[] | getSizeBytes = 4 |
|
||||
| allocators.cpp:135:3:135:26 | new | getSizeBytes = 4, requiresDealloc |
|
||||
| allocators.cpp:136:3:136:26 | new[] | getSizeBytes = 8, requiresDealloc |
|
||||
| allocators.cpp:142:13:142:27 | new[] | getSizeExpr = x, getSizeMult = 10, requiresDealloc |
|
||||
| allocators.cpp:143:13:143:28 | new[] | getSizeBytes = 400, requiresDealloc |
|
||||
| allocators.cpp:144:13:144:31 | new[] | getSizeExpr = x, getSizeMult = 900, requiresDealloc |
|
||||
| allocators.cpp:149:8:149:19 | call to operator new | getSizeBytes = 4, getSizeExpr = sizeof(int), getSizeMult = 1, requiresDealloc |
|
||||
deallocationFunctions
|
||||
| allocators.cpp:11:6:11:20 | operator delete | getFreedArg = 0 |
|
||||
| allocators.cpp:12:6:12:22 | operator delete[] | getFreedArg = 0 |
|
||||
| allocators.cpp:13:6:13:20 | operator delete | getFreedArg = 0 |
|
||||
| allocators.cpp:14:6:14:22 | operator delete[] | getFreedArg = 0 |
|
||||
| file://:0:0:0:0 | operator delete | getFreedArg = 0 |
|
||||
| file://:0:0:0:0 | operator delete | getFreedArg = 0 |
|
||||
| file://:0:0:0:0 | operator delete | getFreedArg = 0 |
|
||||
| file://:0:0:0:0 | operator delete[] | getFreedArg = 0 |
|
||||
| file://:0:0:0:0 | operator delete[] | getFreedArg = 0 |
|
||||
deallocationExprs
|
||||
| allocators.cpp:59:3:59:35 | delete | getFreedExpr = 0 |
|
||||
| allocators.cpp:60:3:60:38 | delete | getFreedExpr = 0 |
|
||||
| allocators.cpp:61:3:61:44 | delete | getFreedExpr = 0 |
|
||||
| allocators.cpp:62:3:62:43 | delete | getFreedExpr = 0 |
|
||||
| allocators.cpp:63:3:63:47 | delete | getFreedExpr = 0 |
|
||||
| allocators.cpp:64:3:64:44 | delete | getFreedExpr = 0 |
|
||||
| allocators.cpp:78:3:78:37 | delete[] | getFreedExpr = 0 |
|
||||
| allocators.cpp:79:3:79:40 | delete[] | getFreedExpr = 0 |
|
||||
| allocators.cpp:80:3:80:46 | delete[] | getFreedExpr = 0 |
|
||||
| allocators.cpp:81:3:81:45 | delete[] | getFreedExpr = 0 |
|
||||
| allocators.cpp:82:3:82:49 | delete[] | getFreedExpr = 0 |
|
||||
| allocators.cpp:83:3:83:23 | delete[] | getFreedExpr = call to GetPointer |
|
||||
| allocators.cpp:150:2:150:16 | call to operator delete | getFreedExpr = ptr |
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import default
|
||||
import semmle.code.cpp.models.implementations.Allocation
|
||||
|
||||
query predicate newExprs(NewExpr expr, string type, string sig, int size, int alignment, string form) {
|
||||
query predicate newExprs(
|
||||
NewExpr expr, string type, string sig, int size, int alignment, string form, string placement
|
||||
) {
|
||||
exists(Function allocator, Type allocatedType |
|
||||
expr.getAllocator() = allocator and
|
||||
sig = allocator.getFullSignature() and
|
||||
@@ -8,13 +11,16 @@ query predicate newExprs(NewExpr expr, string type, string sig, int size, int al
|
||||
type = allocatedType.toString() and
|
||||
size = allocatedType.getSize() and
|
||||
alignment = allocatedType.getAlignment() and
|
||||
if expr.hasAlignedAllocation() then form = "aligned" else form = ""
|
||||
(if expr.hasAlignedAllocation() then form = "aligned" else form = "") and
|
||||
if exists(expr.getPlacementPointer())
|
||||
then placement = expr.getPlacementPointer().toString()
|
||||
else placement = ""
|
||||
)
|
||||
}
|
||||
|
||||
query predicate newArrayExprs(
|
||||
NewArrayExpr expr, string t1, string t2, string sig, int size, int alignment, string form,
|
||||
string extents
|
||||
string extents, string placement
|
||||
) {
|
||||
exists(Function allocator, Type arrayType, Type elementType |
|
||||
expr.getAllocator() = allocator and
|
||||
@@ -26,7 +32,10 @@ query predicate newArrayExprs(
|
||||
size = elementType.getSize() and
|
||||
alignment = elementType.getAlignment() and
|
||||
(if expr.hasAlignedAllocation() then form = "aligned" else form = "") and
|
||||
extents = concat(Expr e | e = expr.getExtent() | e.toString(), ", ")
|
||||
extents = concat(Expr e | e = expr.getExtent() | e.toString(), ", ") and
|
||||
if exists(expr.getPlacementPointer())
|
||||
then placement = expr.getPlacementPointer().toString()
|
||||
else placement = ""
|
||||
)
|
||||
}
|
||||
|
||||
@@ -101,3 +110,54 @@ query predicate deleteArrayExprs(
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
string describeAllocationFunction(AllocationFunction f) {
|
||||
result = "getSizeArg = " + f.getSizeArg().toString()
|
||||
or
|
||||
result = "getSizeMult = " + f.getSizeMult().toString()
|
||||
or
|
||||
result = "getReallocPtrArg = " + f.getReallocPtrArg().toString()
|
||||
or
|
||||
f.requiresDealloc() and
|
||||
result = "requiresDealloc"
|
||||
or
|
||||
result =
|
||||
"getPlacementArgument = " + f.(OperatorNewAllocationFunction).getPlacementArgument().toString()
|
||||
}
|
||||
|
||||
query predicate allocationFunctions(AllocationFunction f, string descr) {
|
||||
descr = concat(describeAllocationFunction(f), ", ")
|
||||
}
|
||||
|
||||
string describeAllocationExpr(AllocationExpr e) {
|
||||
result = "getSizeExpr = " + e.getSizeExpr().toString()
|
||||
or
|
||||
result = "getSizeMult = " + e.getSizeMult().toString()
|
||||
or
|
||||
result = "getSizeBytes = " + e.getSizeBytes().toString()
|
||||
or
|
||||
result = "getReallocPtr = " + e.getReallocPtr().toString()
|
||||
or
|
||||
e.requiresDealloc() and
|
||||
result = "requiresDealloc"
|
||||
}
|
||||
|
||||
query predicate allocationExprs(AllocationExpr e, string descr) {
|
||||
descr = concat(describeAllocationExpr(e), ", ")
|
||||
}
|
||||
|
||||
string describeDeallocationFunction(DeallocationFunction f) {
|
||||
result = "getFreedArg = " + f.getFreedArg().toString()
|
||||
}
|
||||
|
||||
query predicate deallocationFunctions(DeallocationFunction f, string descr) {
|
||||
descr = concat(describeDeallocationFunction(f), ", ")
|
||||
}
|
||||
|
||||
string describeDeallocationExpr(DeallocationExpr e) {
|
||||
result = "getFreedExpr = " + e.getFreedExpr().toString()
|
||||
}
|
||||
|
||||
query predicate deallocationExprs(DeallocationExpr e, string descr) {
|
||||
descr = concat(describeDeallocationExpr(e), ", ")
|
||||
}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
| allocators.cpp:129:3:129:21 | new | allocators.cpp:129:7:129:13 | & ... |
|
||||
| allocators.cpp:132:3:132:17 | new[] | allocators.cpp:132:7:132:9 | buf |
|
||||
@@ -1,4 +0,0 @@
|
||||
import cpp
|
||||
|
||||
from NewOrNewArrayExpr new
|
||||
select new, new.getPlacementPointer() as placement
|
||||
@@ -512,3 +512,20 @@
|
||||
| taint.cpp:444:7:444:7 | d [post update] | taint.cpp:447:7:447:7 | d | |
|
||||
| taint.cpp:445:2:445:2 | d [post update] | taint.cpp:446:7:446:7 | d | |
|
||||
| taint.cpp:445:2:445:2 | d [post update] | taint.cpp:447:7:447:7 | d | |
|
||||
| taint.cpp:452:16:452:16 | a | taint.cpp:454:10:454:10 | a | |
|
||||
| taint.cpp:452:24:452:24 | b | taint.cpp:455:6:455:6 | b | |
|
||||
| taint.cpp:454:10:454:10 | a | taint.cpp:456:6:456:6 | c | |
|
||||
| taint.cpp:455:6:455:6 | b | taint.cpp:452:16:452:16 | a | |
|
||||
| taint.cpp:455:6:455:6 | b | taint.cpp:455:2:455:6 | ... = ... | |
|
||||
| taint.cpp:456:6:456:6 | c | taint.cpp:452:24:452:24 | b | |
|
||||
| taint.cpp:456:6:456:6 | c | taint.cpp:456:2:456:6 | ... = ... | |
|
||||
| taint.cpp:462:6:462:11 | call to source | taint.cpp:462:2:462:13 | ... = ... | |
|
||||
| taint.cpp:462:6:462:11 | call to source | taint.cpp:465:7:465:7 | x | |
|
||||
| taint.cpp:462:6:462:11 | call to source | taint.cpp:468:7:468:7 | x | |
|
||||
| taint.cpp:462:6:462:11 | call to source | taint.cpp:470:7:470:7 | x | |
|
||||
| taint.cpp:463:6:463:6 | 0 | taint.cpp:463:2:463:6 | ... = ... | |
|
||||
| taint.cpp:463:6:463:6 | 0 | taint.cpp:466:7:466:7 | y | |
|
||||
| taint.cpp:463:6:463:6 | 0 | taint.cpp:468:10:468:10 | y | |
|
||||
| taint.cpp:463:6:463:6 | 0 | taint.cpp:471:7:471:7 | y | |
|
||||
| taint.cpp:468:7:468:7 | ref arg x | taint.cpp:470:7:470:7 | x | |
|
||||
| taint.cpp:468:10:468:10 | ref arg y | taint.cpp:471:7:471:7 | y | |
|
||||
|
||||
@@ -195,7 +195,7 @@ void test_memcpy(int *source) {
|
||||
sink(x);
|
||||
}
|
||||
|
||||
// --- swap ---
|
||||
// --- std::swap ---
|
||||
|
||||
namespace std {
|
||||
template<class T> constexpr void swap(T& a, T& b);
|
||||
@@ -446,3 +446,27 @@ void test_qualifiers()
|
||||
sink(d); // tainted
|
||||
sink(d.getString()); // tainted
|
||||
}
|
||||
|
||||
// --- non-standard swap ---
|
||||
|
||||
void swop(int &a, int &b)
|
||||
{
|
||||
int c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
|
||||
void test_swop() {
|
||||
int x, y;
|
||||
|
||||
x = source();
|
||||
y = 0;
|
||||
|
||||
sink(x); // tainted
|
||||
sink(y); // clean
|
||||
|
||||
swop(x, y);
|
||||
|
||||
sink(x); // clean [FALSE POSITIVE]
|
||||
sink(y); // tainted
|
||||
}
|
||||
|
||||
@@ -58,3 +58,6 @@
|
||||
| taint.cpp:439:10:439:18 | call to getMember | taint.cpp:437:15:437:20 | call to source |
|
||||
| taint.cpp:446:7:446:7 | d | taint.cpp:445:14:445:28 | call to source |
|
||||
| taint.cpp:447:9:447:17 | call to getString | taint.cpp:445:14:445:28 | call to source |
|
||||
| taint.cpp:465:7:465:7 | x | taint.cpp:462:6:462:11 | call to source |
|
||||
| taint.cpp:470:7:470:7 | x | taint.cpp:462:6:462:11 | call to source |
|
||||
| taint.cpp:471:7:471:7 | y | taint.cpp:462:6:462:11 | call to source |
|
||||
|
||||
@@ -42,3 +42,4 @@
|
||||
| taint.cpp:439:10:439:18 | taint.cpp:437:15:437:20 | AST only |
|
||||
| taint.cpp:446:7:446:7 | taint.cpp:445:14:445:28 | AST only |
|
||||
| taint.cpp:447:9:447:17 | taint.cpp:445:14:445:28 | AST only |
|
||||
| taint.cpp:471:7:471:7 | taint.cpp:462:6:462:11 | AST only |
|
||||
|
||||
@@ -20,3 +20,5 @@
|
||||
| taint.cpp:382:7:382:7 | a | taint.cpp:377:23:377:28 | source |
|
||||
| taint.cpp:429:7:429:7 | b | taint.cpp:428:13:428:18 | call to source |
|
||||
| taint.cpp:430:9:430:14 | member | taint.cpp:428:13:428:18 | call to source |
|
||||
| taint.cpp:465:7:465:7 | x | taint.cpp:462:6:462:11 | call to source |
|
||||
| taint.cpp:470:7:470:7 | x | taint.cpp:462:6:462:11 | call to source |
|
||||
|
||||
@@ -8475,6 +8475,76 @@ ir.cpp:
|
||||
# 1243| Type = [PointerType] const char *
|
||||
# 1243| ValueCategory = prvalue(load)
|
||||
# 1244| 3: [ReturnStmt] return ...
|
||||
# 1248| [TopLevelFunction] char* strcpy(char*, char const*)
|
||||
# 1248| params:
|
||||
# 1248| 0: [Parameter] destination
|
||||
# 1248| Type = [CharPointerType] char *
|
||||
# 1248| 1: [Parameter] source
|
||||
# 1248| Type = [PointerType] const char *
|
||||
# 1249| [TopLevelFunction] char* strcat(char*, char const*)
|
||||
# 1249| params:
|
||||
# 1249| 0: [Parameter] destination
|
||||
# 1249| Type = [CharPointerType] char *
|
||||
# 1249| 1: [Parameter] source
|
||||
# 1249| Type = [PointerType] const char *
|
||||
# 1251| [TopLevelFunction] void test_strings(char*, char*)
|
||||
# 1251| params:
|
||||
# 1251| 0: [Parameter] s1
|
||||
# 1251| Type = [CharPointerType] char *
|
||||
# 1251| 1: [Parameter] s2
|
||||
# 1251| Type = [CharPointerType] char *
|
||||
# 1251| body: [Block] { ... }
|
||||
# 1252| 0: [DeclStmt] declaration
|
||||
# 1252| 0: [VariableDeclarationEntry] definition of buffer
|
||||
# 1252| Type = [ArrayType] char[1024]
|
||||
# 1252| init: [Initializer] initializer for buffer
|
||||
# 1252| expr: [ArrayAggregateLiteral] {...}
|
||||
# 1252| Type = [ArrayType] char[1024]
|
||||
# 1252| ValueCategory = prvalue
|
||||
# 1252| [0]: [CStyleCast] (char)...
|
||||
# 1252| Conversion = [IntegralConversion] integral conversion
|
||||
# 1252| Type = [PlainCharType] char
|
||||
# 1252| Value = [CStyleCast] 0
|
||||
# 1252| ValueCategory = prvalue
|
||||
# 1252| expr: [Literal] 0
|
||||
# 1252| Type = [IntType] int
|
||||
# 1252| Value = [Literal] 0
|
||||
# 1252| ValueCategory = prvalue
|
||||
# 1254| 1: [ExprStmt] ExprStmt
|
||||
# 1254| 0: [FunctionCall] call to strcpy
|
||||
# 1254| Type = [CharPointerType] char *
|
||||
# 1254| ValueCategory = prvalue
|
||||
# 1254| 0: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 1254| Type = [CharPointerType] char *
|
||||
# 1254| ValueCategory = prvalue
|
||||
# 1254| expr: [VariableAccess] buffer
|
||||
# 1254| Type = [ArrayType] char[1024]
|
||||
# 1254| ValueCategory = lvalue
|
||||
# 1254| 1: [CStyleCast] (const char *)...
|
||||
# 1254| Conversion = [PointerConversion] pointer conversion
|
||||
# 1254| Type = [PointerType] const char *
|
||||
# 1254| ValueCategory = prvalue
|
||||
# 1254| expr: [VariableAccess] s1
|
||||
# 1254| Type = [CharPointerType] char *
|
||||
# 1254| ValueCategory = prvalue(load)
|
||||
# 1255| 2: [ExprStmt] ExprStmt
|
||||
# 1255| 0: [FunctionCall] call to strcat
|
||||
# 1255| Type = [CharPointerType] char *
|
||||
# 1255| ValueCategory = prvalue
|
||||
# 1255| 0: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 1255| Type = [CharPointerType] char *
|
||||
# 1255| ValueCategory = prvalue
|
||||
# 1255| expr: [VariableAccess] buffer
|
||||
# 1255| Type = [ArrayType] char[1024]
|
||||
# 1255| ValueCategory = lvalue
|
||||
# 1255| 1: [CStyleCast] (const char *)...
|
||||
# 1255| Conversion = [PointerConversion] pointer conversion
|
||||
# 1255| Type = [PointerType] const char *
|
||||
# 1255| ValueCategory = prvalue
|
||||
# 1255| expr: [VariableAccess] s2
|
||||
# 1255| Type = [CharPointerType] char *
|
||||
# 1255| ValueCategory = prvalue(load)
|
||||
# 1256| 3: [ReturnStmt] return ...
|
||||
perf-regression.cpp:
|
||||
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
|
||||
# 4| params:
|
||||
|
||||
@@ -1243,4 +1243,16 @@ void staticLocalWithConstructor(const char* dynamic) {
|
||||
static String c(dynamic);
|
||||
}
|
||||
|
||||
// --- strings ---
|
||||
|
||||
char *strcpy(char *destination, const char *source);
|
||||
char *strcat(char *destination, const char *source);
|
||||
|
||||
void test_strings(char *s1, char *s2) {
|
||||
char buffer[1024] = {0};
|
||||
|
||||
strcpy(buffer, s1);
|
||||
strcat(buffer, s2);
|
||||
}
|
||||
|
||||
// semmle-extractor-options: -std=c++17 --clang
|
||||
|
||||
@@ -6432,6 +6432,57 @@ ir.cpp:
|
||||
# 1241| mu1241_6(bool) = Store : &:r1241_1, r1241_5
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1251| void test_strings(char*, char*)
|
||||
# 1251| Block 0
|
||||
# 1251| v1251_1(void) = EnterFunction :
|
||||
# 1251| mu1251_2(unknown) = AliasedDefinition :
|
||||
# 1251| mu1251_3(unknown) = InitializeNonLocal :
|
||||
# 1251| mu1251_4(unknown) = UnmodeledDefinition :
|
||||
# 1251| r1251_5(glval<char *>) = VariableAddress[s1] :
|
||||
# 1251| mu1251_6(char *) = InitializeParameter[s1] : &:r1251_5
|
||||
# 1251| r1251_7(char *) = Load : &:r1251_5, ~mu1251_6
|
||||
# 1251| mu1251_8(unknown) = InitializeIndirection[s1] : &:r1251_7
|
||||
# 1251| r1251_9(glval<char *>) = VariableAddress[s2] :
|
||||
# 1251| mu1251_10(char *) = InitializeParameter[s2] : &:r1251_9
|
||||
# 1251| r1251_11(char *) = Load : &:r1251_9, ~mu1251_10
|
||||
# 1251| mu1251_12(unknown) = InitializeIndirection[s2] : &:r1251_11
|
||||
# 1252| r1252_1(glval<char[1024]>) = VariableAddress[buffer] :
|
||||
# 1252| mu1252_2(char[1024]) = Uninitialized[buffer] : &:r1252_1
|
||||
# 1252| r1252_3(int) = Constant[0] :
|
||||
# 1252| r1252_4(glval<char>) = PointerAdd[1] : r1252_1, r1252_3
|
||||
# 1252| r1252_5(char) = Constant[0] :
|
||||
# 1252| mu1252_6(char) = Store : &:r1252_4, r1252_5
|
||||
# 1252| r1252_7(int) = Constant[1] :
|
||||
# 1252| r1252_8(glval<char>) = PointerAdd[1] : r1252_1, r1252_7
|
||||
# 1252| r1252_9(unknown[1023]) = Constant[0] :
|
||||
# 1252| mu1252_10(unknown[1023]) = Store : &:r1252_8, r1252_9
|
||||
# 1254| r1254_1(glval<unknown>) = FunctionAddress[strcpy] :
|
||||
# 1254| r1254_2(glval<char[1024]>) = VariableAddress[buffer] :
|
||||
# 1254| r1254_3(char *) = Convert : r1254_2
|
||||
# 1254| r1254_4(glval<char *>) = VariableAddress[s1] :
|
||||
# 1254| r1254_5(char *) = Load : &:r1254_4, ~mu1251_4
|
||||
# 1254| r1254_6(char *) = Convert : r1254_5
|
||||
# 1254| r1254_7(char *) = Call : func:r1254_1, 0:r1254_3, 1:r1254_6
|
||||
# 1254| v1254_8(void) = ^BufferReadSideEffect[1] : &:r1254_6, ~mu1251_4
|
||||
# 1254| mu1254_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r1254_3
|
||||
# 1255| r1255_1(glval<unknown>) = FunctionAddress[strcat] :
|
||||
# 1255| r1255_2(glval<char[1024]>) = VariableAddress[buffer] :
|
||||
# 1255| r1255_3(char *) = Convert : r1255_2
|
||||
# 1255| r1255_4(glval<char *>) = VariableAddress[s2] :
|
||||
# 1255| r1255_5(char *) = Load : &:r1255_4, ~mu1251_4
|
||||
# 1255| r1255_6(char *) = Convert : r1255_5
|
||||
# 1255| r1255_7(char *) = Call : func:r1255_1, 0:r1255_3, 1:r1255_6
|
||||
# 1255| v1255_8(void) = ^BufferReadSideEffect[0] : &:r1255_3, ~mu1251_4
|
||||
# 1255| v1255_9(void) = ^BufferReadSideEffect[1] : &:r1255_6, ~mu1251_4
|
||||
# 1255| mu1255_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r1255_3
|
||||
# 1256| v1256_1(void) = NoOp :
|
||||
# 1251| v1251_13(void) = ReturnIndirection : &:r1251_7, ~mu1251_4
|
||||
# 1251| v1251_14(void) = ReturnIndirection : &:r1251_11, ~mu1251_4
|
||||
# 1251| v1251_15(void) = ReturnVoid :
|
||||
# 1251| v1251_16(void) = UnmodeledUse : mu*
|
||||
# 1251| v1251_17(void) = AliasedUse : ~mu1251_4
|
||||
# 1251| v1251_18(void) = ExitFunction :
|
||||
|
||||
perf-regression.cpp:
|
||||
# 6| void Big::Big()
|
||||
# 6| Block 0
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
| test.c:25:9:25:14 | ExprStmt | Function f4 should return a value of type int but does not return a value here |
|
||||
| test.c:39:9:39:14 | ExprStmt | Function f6 should return a value of type int but does not return a value here |
|
||||
| test.cpp:16:1:18:1 | { ... } | Function g2 should return a value of type MyValue but does not return a value here |
|
||||
| test.cpp:48:2:48:26 | if (...) ... | Function g7 should return a value of type MyValue but does not return a value here |
|
||||
| test.cpp:52:1:52:1 | return ... | Function g7 should return a value of type MyValue but does not return a value here |
|
||||
| test.cpp:74:1:76:1 | { ... } | Function g10 should return a value of type second but does not return a value here |
|
||||
| test.cpp:86:1:88:1 | { ... } | Function g12 should return a value of type second but does not return a value here |
|
||||
| test.cpp:108:2:111:2 | if (...) ... | Function g14 should return a value of type int but does not return a value here |
|
||||
| test.cpp:112:1:112:1 | return ... | Function g14 should return a value of type int but does not return a value here |
|
||||
| test.cpp:134:2:134:36 | ExprStmt | Function g16 should return a value of type int but does not return a value here |
|
||||
| test.cpp:141:3:141:37 | ExprStmt | Function g17 should return a value of type int but does not return a value here |
|
||||
|
||||
@@ -48,7 +48,7 @@ MyValue g7(bool c)
|
||||
if (c) return MyValue(7);
|
||||
DONOTHING
|
||||
DONOTHING
|
||||
// BAD [the alert here is unfortunately placed]
|
||||
// BAD
|
||||
}
|
||||
|
||||
typedef void MYVOID;
|
||||
|
||||
Reference in New Issue
Block a user