mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge pull request #8321 from MathiasVP/improve-using-expired-address-query
C++: More TPs from `cpp/using-expired-stack-address`
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* @name Use of expired stack-address
|
||||
* @description Accessing the stack-allocated memory of a function
|
||||
* after it has returned can lead to memory corruption.
|
||||
* @kind problem
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.3
|
||||
* @precision high
|
||||
@@ -178,13 +178,10 @@ predicate blockStoresToAddress(
|
||||
globalAddress = globalAddress(store.getDestinationAddress())
|
||||
}
|
||||
|
||||
predicate blockLoadsFromAddress(
|
||||
IRBlock block, int index, LoadInstruction load, TGlobalAddress globalAddress
|
||||
) {
|
||||
block.getInstruction(index) = load and
|
||||
globalAddress = globalAddress(load.getSourceAddress())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `globalAddress` evaluates to the address of `var` (which escaped through `store` before
|
||||
* returning through `call`) when control reaches `block`.
|
||||
*/
|
||||
predicate globalAddressPointsToStack(
|
||||
StoreInstruction store, StackVariable var, CallInstruction call, IRBlock block,
|
||||
TGlobalAddress globalAddress, boolean isCallBlock, boolean isStoreBlock
|
||||
@@ -203,21 +200,127 @@ predicate globalAddressPointsToStack(
|
||||
)
|
||||
or
|
||||
isCallBlock = false and
|
||||
exists(IRBlock mid |
|
||||
mid.immediatelyDominates(block) and
|
||||
// Only recurse if there is no store to `globalAddress` in `mid`.
|
||||
globalAddressPointsToStack(store, var, call, mid, globalAddress, _, false)
|
||||
step(store, var, call, globalAddress, _, block)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
int getInstructionIndex(Instruction instr, IRBlock block) { block.getInstruction(result) = instr }
|
||||
|
||||
predicate step(
|
||||
StoreInstruction store, StackVariable var, CallInstruction call, TGlobalAddress globalAddress,
|
||||
IRBlock pred, IRBlock succ
|
||||
) {
|
||||
exists(boolean isCallBlock, boolean isStoreBlock |
|
||||
// Only recurse if there is no store to `globalAddress` in `mid`.
|
||||
globalAddressPointsToStack(store, var, call, pred, globalAddress, isCallBlock, isStoreBlock)
|
||||
|
|
||||
// Post domination ensures that `block` is always executed after `mid`
|
||||
// Domination ensures that `mid` is always executed before `block`
|
||||
isStoreBlock = false and
|
||||
succ.immediatelyPostDominates(pred) and
|
||||
pred.immediatelyDominates(succ)
|
||||
or
|
||||
exists(CallInstruction anotherCall, int anotherCallIndex |
|
||||
anotherCall = pred.getInstruction(anotherCallIndex) and
|
||||
succ.getFirstInstruction() instanceof EnterFunctionInstruction and
|
||||
succ.getEnclosingFunction() = anotherCall.getStaticCallTarget() and
|
||||
(if isCallBlock = true then getInstructionIndex(call, _) < anotherCallIndex else any()) and
|
||||
(
|
||||
if isStoreBlock = true
|
||||
then
|
||||
forex(int storeIndex | blockStoresToAddress(pred, storeIndex, _, globalAddress) |
|
||||
anotherCallIndex < storeIndex
|
||||
)
|
||||
else any()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
newtype TPathElement =
|
||||
TStore(StoreInstruction store) { globalAddressPointsToStack(store, _, _, _, _, _, _) } or
|
||||
TCall(CallInstruction call, IRBlock block) {
|
||||
globalAddressPointsToStack(_, _, call, block, _, _, _)
|
||||
} or
|
||||
TMid(IRBlock block) { step(_, _, _, _, _, block) } or
|
||||
TSink(LoadInstruction load, IRBlock block) {
|
||||
exists(TGlobalAddress address |
|
||||
globalAddressPointsToStack(_, _, _, block, address, _, _) and
|
||||
block.getAnInstruction() = load and
|
||||
globalAddress(load.getSourceAddress()) = address
|
||||
)
|
||||
}
|
||||
|
||||
class PathElement extends TPathElement {
|
||||
StoreInstruction asStore() { this = TStore(result) }
|
||||
|
||||
CallInstruction asCall(IRBlock block) { this = TCall(result, block) }
|
||||
|
||||
predicate isCall(IRBlock block) { exists(this.asCall(block)) }
|
||||
|
||||
IRBlock asMid() { this = TMid(result) }
|
||||
|
||||
LoadInstruction asSink(IRBlock block) { this = TSink(result, block) }
|
||||
|
||||
predicate isSink(IRBlock block) { exists(this.asSink(block)) }
|
||||
|
||||
string toString() {
|
||||
result = [asStore().toString(), asCall(_).toString(), asMid().toString(), asSink(_).toString()]
|
||||
}
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.asStore()
|
||||
.getLocation()
|
||||
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
or
|
||||
this.asCall(_)
|
||||
.getLocation()
|
||||
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
or
|
||||
this.asMid().getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
or
|
||||
this.asSink(_)
|
||||
.getLocation()
|
||||
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
predicate isSink(LoadInstruction load, IRBlock block, int index, TGlobalAddress globalAddress) {
|
||||
block.getInstruction(index) = load and
|
||||
globalAddress(load.getSourceAddress()) = globalAddress
|
||||
}
|
||||
|
||||
query predicate edges(PathElement pred, PathElement succ) {
|
||||
// Store -> caller
|
||||
globalAddressPointsToStack(pred.asStore(), _, succ.asCall(_), _, _, _, _)
|
||||
or
|
||||
// Call -> basic block
|
||||
pred.isCall(succ.asMid())
|
||||
or
|
||||
// Special case for when the caller goes directly to the load with no steps
|
||||
// across basic blocks (i.e., caller -> sink)
|
||||
exists(IRBlock block |
|
||||
pred.isCall(block) and
|
||||
succ.isSink(block)
|
||||
)
|
||||
or
|
||||
// Basic block -> basic block
|
||||
step(_, _, _, _, pred.asMid(), succ.asMid())
|
||||
or
|
||||
// Basic block -> load
|
||||
succ.isSink(pred.asMid())
|
||||
}
|
||||
|
||||
from
|
||||
StoreInstruction store, StackVariable var, LoadInstruction load, CallInstruction call,
|
||||
IRBlock block, boolean isCallBlock, TGlobalAddress address, boolean isStoreBlock
|
||||
IRBlock block, boolean isCallBlock, TGlobalAddress address, boolean isStoreBlock,
|
||||
PathElement source, PathElement sink, int loadIndex
|
||||
where
|
||||
globalAddressPointsToStack(store, var, call, block, address, isCallBlock, isStoreBlock) and
|
||||
block.getAnInstruction() = load and
|
||||
globalAddress(load.getSourceAddress()) = address and
|
||||
isSink(load, block, loadIndex, address) and
|
||||
(
|
||||
// We know that we have a sequence:
|
||||
// (1) store to `address` -> (2) return from `f` -> (3) load from `address`.
|
||||
@@ -226,22 +329,20 @@ where
|
||||
if isCallBlock = true
|
||||
then
|
||||
// If so, the load must happen after the call.
|
||||
exists(int callIndex, int loadIndex |
|
||||
blockLoadsFromAddress(_, loadIndex, load, _) and
|
||||
block.getInstruction(callIndex) = call and
|
||||
callIndex < loadIndex
|
||||
getInstructionIndex(call, _) < loadIndex
|
||||
else any()
|
||||
) and
|
||||
(
|
||||
// If there is a store to the address we need to make sure that the load we found was
|
||||
// before that store (So that the load doesn't read an overwritten value).
|
||||
if isStoreBlock = true
|
||||
then
|
||||
forex(int storeIndex | blockStoresToAddress(block, storeIndex, _, address) |
|
||||
loadIndex < storeIndex
|
||||
)
|
||||
else any()
|
||||
) and
|
||||
// If there is a store to the address we need to make sure that the load we found was
|
||||
// before that store (So that the load doesn't read an overwritten value).
|
||||
if isStoreBlock = true
|
||||
then
|
||||
exists(int storeIndex, int loadIndex |
|
||||
blockStoresToAddress(block, storeIndex, _, address) and
|
||||
block.getInstruction(loadIndex) = load and
|
||||
loadIndex < storeIndex
|
||||
)
|
||||
else any()
|
||||
select load, "Stack variable $@ escapes $@ and is used after it has expired.", var, var.toString(),
|
||||
store, "here"
|
||||
source.asStore() = store and
|
||||
sink.asSink(_) = load
|
||||
select sink, source, sink, "Stack variable $@ escapes $@ and is used after it has expired.", var,
|
||||
var.toString(), store, "here"
|
||||
|
||||
@@ -1,24 +1,92 @@
|
||||
| test.cpp:15:16:15:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
|
||||
| test.cpp:58:16:58:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:51:36:51:36 | y | y | test.cpp:52:3:52:13 | Store: ... = ... | here |
|
||||
| test.cpp:73:16:73:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:62:7:62:7 | x | x | test.cpp:68:3:68:13 | Store: ... = ... | here |
|
||||
| test.cpp:98:15:98:15 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:92:8:92:8 | s | s | test.cpp:93:3:93:15 | Store: ... = ... | here |
|
||||
| test.cpp:111:16:111:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:102:7:102:7 | x | x | test.cpp:106:3:106:14 | Store: ... = ... | here |
|
||||
| test.cpp:161:16:161:17 | Load: p1 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:132:7:132:8 | b1 | b1 | test.cpp:136:3:136:12 | Store: ... = ... | here |
|
||||
| test.cpp:162:16:162:17 | Load: p1 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:132:7:132:8 | b1 | b1 | test.cpp:137:3:137:16 | Store: ... = ... | here |
|
||||
| test.cpp:164:16:164:17 | Load: p2 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:139:3:139:12 | Store: ... = ... | here |
|
||||
| test.cpp:165:16:165:17 | Load: p2 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:139:3:139:12 | Store: ... = ... | here |
|
||||
| test.cpp:166:17:166:18 | Load: p2 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:140:3:140:16 | Store: ... = ... | here |
|
||||
| test.cpp:167:16:167:17 | Load: p1 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:141:3:141:15 | Store: ... = ... | here |
|
||||
| test.cpp:168:17:168:18 | Load: p1 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:142:3:142:19 | Store: ... = ... | here |
|
||||
| test.cpp:170:16:170:17 | Load: p3 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:144:3:144:12 | Store: ... = ... | here |
|
||||
| test.cpp:171:17:171:18 | Load: p3 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:145:3:145:16 | Store: ... = ... | here |
|
||||
| test.cpp:172:18:172:19 | Load: p2 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:146:3:146:15 | Store: ... = ... | here |
|
||||
| test.cpp:173:18:173:19 | Load: p2 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:147:3:147:19 | Store: ... = ... | here |
|
||||
| test.cpp:174:18:174:19 | Load: p1 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:142:3:142:19 | Store: ... = ... | here |
|
||||
| test.cpp:175:16:175:17 | Load: p1 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:148:3:148:18 | Store: ... = ... | here |
|
||||
| test.cpp:177:14:177:21 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:132:7:132:8 | b1 | b1 | test.cpp:151:3:151:15 | Store: ... = ... | here |
|
||||
| test.cpp:178:14:178:21 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:132:7:132:8 | b1 | b1 | test.cpp:152:3:152:19 | Store: ... = ... | here |
|
||||
| test.cpp:179:14:179:21 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:153:3:153:18 | Store: ... = ... | here |
|
||||
| test.cpp:180:14:180:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:154:3:154:22 | Store: ... = ... | here |
|
||||
| test.cpp:181:13:181:20 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:155:3:155:21 | Store: ... = ... | here |
|
||||
| test.cpp:182:14:182:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:156:3:156:25 | Store: ... = ... | here |
|
||||
edges
|
||||
| test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:14:3:14:9 | Call: call to escape1 |
|
||||
| test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:19:3:19:9 | Call: call to escape1 |
|
||||
| test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:28:3:28:9 | Call: call to escape1 |
|
||||
| test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:28:3:28:9 | Call: call to escape1 |
|
||||
| test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:37:3:37:9 | Call: call to escape1 |
|
||||
| test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:37:3:37:9 | Call: call to escape1 |
|
||||
| test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:210:3:210:9 | Call: call to escape1 |
|
||||
| test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:210:3:210:9 | Call: call to escape1 |
|
||||
| test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:210:3:210:9 | Call: call to escape1 |
|
||||
| test.cpp:14:3:14:9 | Call: call to escape1 | test.cpp:15:16:15:16 | Load: p |
|
||||
| test.cpp:23:5:23:11 | EnterFunction: deref_p | test.cpp:24:16:24:16 | Load: p |
|
||||
| test.cpp:28:3:28:9 | Call: call to escape1 | test.cpp:23:5:23:11 | EnterFunction: deref_p |
|
||||
| test.cpp:28:3:28:9 | Call: call to escape1 | test.cpp:24:16:24:16 | Load: p |
|
||||
| test.cpp:37:3:37:9 | Call: call to escape1 | test.cpp:32:5:32:11 | EnterFunction: deref_i |
|
||||
| test.cpp:52:3:52:13 | Store: ... = ... | test.cpp:57:3:57:27 | Call: call to store_address_of_argument |
|
||||
| test.cpp:57:3:57:27 | Call: call to store_address_of_argument | test.cpp:58:16:58:16 | Load: p |
|
||||
| test.cpp:68:3:68:13 | Store: ... = ... | test.cpp:72:3:72:39 | Call: call to address_escapes_through_pointer_arith |
|
||||
| test.cpp:68:3:68:13 | Store: ... = ... | test.cpp:78:3:78:39 | Call: call to address_escapes_through_pointer_arith |
|
||||
| test.cpp:68:3:68:13 | Store: ... = ... | test.cpp:86:5:86:41 | Call: call to address_escapes_through_pointer_arith |
|
||||
| test.cpp:72:3:72:39 | Call: call to address_escapes_through_pointer_arith | test.cpp:73:16:73:16 | Load: p |
|
||||
| test.cpp:78:3:78:39 | Call: call to address_escapes_through_pointer_arith | test.cpp:80:16:80:16 | Load: p |
|
||||
| test.cpp:93:3:93:15 | Store: ... = ... | test.cpp:97:3:97:23 | Call: call to field_address_escapes |
|
||||
| test.cpp:97:3:97:23 | Call: call to field_address_escapes | test.cpp:98:15:98:15 | Load: p |
|
||||
| test.cpp:106:3:106:14 | Store: ... = ... | test.cpp:110:3:110:26 | Call: call to escape_through_reference |
|
||||
| test.cpp:110:3:110:26 | Call: call to escape_through_reference | test.cpp:111:16:111:16 | Load: p |
|
||||
| test.cpp:136:3:136:12 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:137:3:137:16 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:139:3:139:12 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:140:3:140:16 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:141:3:141:15 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:142:3:142:19 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:144:3:144:12 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:145:3:145:16 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:146:3:146:15 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:147:3:147:19 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:148:3:148:18 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:149:3:149:22 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:151:3:151:15 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:152:3:152:19 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:153:3:153:18 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:154:3:154:22 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:155:3:155:21 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:156:3:156:25 | Store: ... = ... | test.cpp:160:3:160:23 | Call: call to escape_through_arrays |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:161:16:161:17 | Load: p1 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:162:16:162:17 | Load: p1 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:164:16:164:17 | Load: p2 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:165:16:165:17 | Load: p2 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:166:17:166:18 | Load: p2 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:167:16:167:17 | Load: p1 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:168:17:168:18 | Load: p1 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:170:16:170:17 | Load: p3 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:171:17:171:18 | Load: p3 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:172:18:172:19 | Load: p2 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:173:18:173:19 | Load: p2 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:174:18:174:19 | Load: p1 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:175:16:175:17 | Load: p1 |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:177:14:177:21 | Load: access to array |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:178:14:178:21 | Load: access to array |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:179:14:179:21 | Load: access to array |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:180:14:180:19 | Load: * ... |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:181:13:181:20 | Load: access to array |
|
||||
| test.cpp:160:3:160:23 | Call: call to escape_through_arrays | test.cpp:182:14:182:19 | Load: * ... |
|
||||
| test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p |
|
||||
| test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p |
|
||||
| test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p |
|
||||
#select
|
||||
| test.cpp:15:16:15:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:15:16:15:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
|
||||
| test.cpp:24:16:24:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:24:16:24:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
|
||||
| test.cpp:58:16:58:16 | Load: p | test.cpp:52:3:52:13 | Store: ... = ... | test.cpp:58:16:58:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:51:36:51:36 | y | y | test.cpp:52:3:52:13 | Store: ... = ... | here |
|
||||
| test.cpp:73:16:73:16 | Load: p | test.cpp:68:3:68:13 | Store: ... = ... | test.cpp:73:16:73:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:62:7:62:7 | x | x | test.cpp:68:3:68:13 | Store: ... = ... | here |
|
||||
| test.cpp:98:15:98:15 | Load: p | test.cpp:93:3:93:15 | Store: ... = ... | test.cpp:98:15:98:15 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:92:8:92:8 | s | s | test.cpp:93:3:93:15 | Store: ... = ... | here |
|
||||
| test.cpp:111:16:111:16 | Load: p | test.cpp:106:3:106:14 | Store: ... = ... | test.cpp:111:16:111:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:102:7:102:7 | x | x | test.cpp:106:3:106:14 | Store: ... = ... | here |
|
||||
| test.cpp:161:16:161:17 | Load: p1 | test.cpp:136:3:136:12 | Store: ... = ... | test.cpp:161:16:161:17 | Load: p1 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:132:7:132:8 | b1 | b1 | test.cpp:136:3:136:12 | Store: ... = ... | here |
|
||||
| test.cpp:162:16:162:17 | Load: p1 | test.cpp:137:3:137:16 | Store: ... = ... | test.cpp:162:16:162:17 | Load: p1 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:132:7:132:8 | b1 | b1 | test.cpp:137:3:137:16 | Store: ... = ... | here |
|
||||
| test.cpp:164:16:164:17 | Load: p2 | test.cpp:139:3:139:12 | Store: ... = ... | test.cpp:164:16:164:17 | Load: p2 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:139:3:139:12 | Store: ... = ... | here |
|
||||
| test.cpp:165:16:165:17 | Load: p2 | test.cpp:139:3:139:12 | Store: ... = ... | test.cpp:165:16:165:17 | Load: p2 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:139:3:139:12 | Store: ... = ... | here |
|
||||
| test.cpp:166:17:166:18 | Load: p2 | test.cpp:140:3:140:16 | Store: ... = ... | test.cpp:166:17:166:18 | Load: p2 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:140:3:140:16 | Store: ... = ... | here |
|
||||
| test.cpp:167:16:167:17 | Load: p1 | test.cpp:141:3:141:15 | Store: ... = ... | test.cpp:167:16:167:17 | Load: p1 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:141:3:141:15 | Store: ... = ... | here |
|
||||
| test.cpp:168:17:168:18 | Load: p1 | test.cpp:142:3:142:19 | Store: ... = ... | test.cpp:168:17:168:18 | Load: p1 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:142:3:142:19 | Store: ... = ... | here |
|
||||
| test.cpp:170:16:170:17 | Load: p3 | test.cpp:144:3:144:12 | Store: ... = ... | test.cpp:170:16:170:17 | Load: p3 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:144:3:144:12 | Store: ... = ... | here |
|
||||
| test.cpp:171:17:171:18 | Load: p3 | test.cpp:145:3:145:16 | Store: ... = ... | test.cpp:171:17:171:18 | Load: p3 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:145:3:145:16 | Store: ... = ... | here |
|
||||
| test.cpp:172:18:172:19 | Load: p2 | test.cpp:146:3:146:15 | Store: ... = ... | test.cpp:172:18:172:19 | Load: p2 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:146:3:146:15 | Store: ... = ... | here |
|
||||
| test.cpp:173:18:173:19 | Load: p2 | test.cpp:147:3:147:19 | Store: ... = ... | test.cpp:173:18:173:19 | Load: p2 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:147:3:147:19 | Store: ... = ... | here |
|
||||
| test.cpp:174:18:174:19 | Load: p1 | test.cpp:142:3:142:19 | Store: ... = ... | test.cpp:174:18:174:19 | Load: p1 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:142:3:142:19 | Store: ... = ... | here |
|
||||
| test.cpp:175:16:175:17 | Load: p1 | test.cpp:148:3:148:18 | Store: ... = ... | test.cpp:175:16:175:17 | Load: p1 | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:148:3:148:18 | Store: ... = ... | here |
|
||||
| test.cpp:177:14:177:21 | Load: access to array | test.cpp:151:3:151:15 | Store: ... = ... | test.cpp:177:14:177:21 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:132:7:132:8 | b1 | b1 | test.cpp:151:3:151:15 | Store: ... = ... | here |
|
||||
| test.cpp:178:14:178:21 | Load: access to array | test.cpp:152:3:152:19 | Store: ... = ... | test.cpp:178:14:178:21 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:132:7:132:8 | b1 | b1 | test.cpp:152:3:152:19 | Store: ... = ... | here |
|
||||
| test.cpp:179:14:179:21 | Load: access to array | test.cpp:153:3:153:18 | Store: ... = ... | test.cpp:179:14:179:21 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:153:3:153:18 | Store: ... = ... | here |
|
||||
| test.cpp:180:14:180:19 | Load: * ... | test.cpp:154:3:154:22 | Store: ... = ... | test.cpp:180:14:180:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:154:3:154:22 | Store: ... = ... | here |
|
||||
| test.cpp:181:13:181:20 | Load: access to array | test.cpp:155:3:155:21 | Store: ... = ... | test.cpp:181:13:181:20 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:155:3:155:21 | Store: ... = ... | here |
|
||||
| test.cpp:182:14:182:19 | Load: * ... | test.cpp:156:3:156:25 | Store: ... = ... | test.cpp:182:14:182:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:156:3:156:25 | Store: ... = ... | here |
|
||||
|
||||
@@ -21,12 +21,12 @@ int simple_field_good() {
|
||||
}
|
||||
|
||||
int deref_p() {
|
||||
return *s101.p;
|
||||
return *s101.p; // BAD
|
||||
}
|
||||
|
||||
int field_indirect_bad() {
|
||||
escape1();
|
||||
return deref_p(); // BAD [NOT DETECTED]
|
||||
return deref_p();
|
||||
}
|
||||
|
||||
int deref_i() {
|
||||
@@ -197,3 +197,16 @@ void test_not_escape_through_array() {
|
||||
int x21 = s1.a2[0][1]; // GOOD
|
||||
int* x22 = s1.a3[5][2]; // GOOD
|
||||
}
|
||||
|
||||
int maybe_deref_p(bool b) {
|
||||
if(b) {
|
||||
return *s101.p; // GOOD
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int field_indirect_maybe_bad(bool b) {
|
||||
escape1();
|
||||
return maybe_deref_p(b);
|
||||
}
|
||||
Reference in New Issue
Block a user