Skip to content

Commit 9e7c9d0

Browse files
committed
C++: Respond to review comments. Relax the escaping requirements on the local variable being used in memset.
1 parent 3f26b29 commit 9e7c9d0

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

cpp/ql/src/Security/CWE/CWE-014/MemsetMayBeDeleted.ql

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @name Call to `memset` may be deleted
3-
* @description Using <code>memset</code> the function to clear private data in a variable that has no subsequent use
3+
* @description Using `memset` the function to clear private data in a variable that has no subsequent use
44
* can make information-leak vulnerabilities easier to exploit because the compiler can remove the call.
55
* @kind problem
66
* @id cpp/memset-may-be-deleted
@@ -13,6 +13,7 @@
1313
import cpp
1414
import semmle.code.cpp.dataflow.EscapesTree
1515
import semmle.code.cpp.commons.Exclusions
16+
import semmle.code.cpp.models.interfaces.Alias
1617

1718
class MemsetFunction extends Function {
1819
MemsetFunction() {
@@ -24,22 +25,33 @@ class MemsetFunction extends Function {
2425
}
2526
}
2627

28+
predicate isNonEscapingArgument(Expr escaped) {
29+
exists(Call call, AliasFunction aliasFunction, int i |
30+
aliasFunction = call.getTarget() and
31+
call.getArgument(i) = escaped.getUnconverted() and
32+
(
33+
aliasFunction.parameterNeverEscapes(i)
34+
or
35+
aliasFunction.parameterEscapesOnlyViaReturn(i) and
36+
(call instanceof ExprInVoidContext or call.getConversion*() instanceof BoolConversion)
37+
)
38+
)
39+
}
40+
2741
from FunctionCall call, LocalVariable v, MemsetFunction memset
2842
where
2943
call.getTarget() = memset and
3044
not isFromMacroDefinition(call) and
31-
// `v` only escapes as the argument to `memset`.
45+
// `v` escapes as the argument to `memset`
46+
variableAddressEscapesTree(v.getAnAccess(), call.getArgument(0).getFullyConverted()) and
47+
// ... and `v` doesn't escape anywhere else.
3248
forall(Expr escape | variableAddressEscapesTree(v.getAnAccess(), escape) |
33-
call.getArgument(0) = escape.getUnconverted()
49+
isNonEscapingArgument(escape)
3450
) and
35-
// `v` is a stack-allocated array or a struct, and `v` is not static.
3651
not v.isStatic() and
37-
(
38-
v.getUnspecifiedType() instanceof ArrayType and call.getArgument(0) = v.getAnAccess()
39-
or
40-
v.getUnspecifiedType() instanceof Struct and
41-
call.getArgument(0).(AddressOfExpr).getAddressable() = v
42-
) and
52+
// Reference-typed variables get special treatment in `variableAddressEscapesTree` so we leave them
53+
// out of this query.
54+
not v.getUnspecifiedType() instanceof ReferenceType and
4355
// There is no later use of `v`.
4456
not v.getAnAccess() = call.getASuccessor*() and
4557
// Not using the `-fno-builtin-memset` flag

0 commit comments

Comments
 (0)