Skip to content

Commit ad626ac

Browse files
committed
Adding ArgumentIsSizeofOrOperation.qhelp, ql, and example files.
1 parent 0f8f96c commit ad626ac

File tree

4 files changed

+90
-0
lines changed

4 files changed

+90
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>If the argument for a <code>sizeof</code> call is a binary operation or a <code>sizeof</code> call, it is typically a sign that there is a confusion on the usage of the sizeof usage.</p>
7+
</overview>
8+
9+
<recommendation>
10+
<p>Any findings from this rule may indicate that the <code>sizeof</code> is being used incorrectly.</p>
11+
<p>Review the logic of the call.</p>
12+
</recommendation>
13+
14+
<example>
15+
<p>The following example shows a case where <code>sizeof</code> a binary operation by mistake.</p>
16+
<sample src="ArgumentIsSizeofOrOperationBad.c" />
17+
18+
<p>In this example, the fix is to multiply the result of <code>sizeof</code> by the number of elements.</p>
19+
<sample src="ArgumentIsSizeofOrOperationGood.c" />
20+
</example>
21+
22+
</qhelp>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* @id cpp/sizeof/sizeof-or-operation-as-argument
3+
* @name Usage of an expression that is a binary operation, or sizeof call passed as an argument to a sizeof call
4+
* @description When the `expr` passed to `sizeof` is a binary operation, or a sizeof call, this is typically a sign that there is a confusion on the usage of sizeof.
5+
* @tags security
6+
*/
7+
8+
import cpp
9+
import SizeOfTypeUtils
10+
11+
/**
12+
* Windows SDK corecrt_math.h defines a macro _CLASS_ARG that
13+
* intentionally misuses sizeof to determine the size of a floating point type.
14+
* Explicitly ignoring any hit in this macro.
15+
*/
16+
predicate isPartOfCrtFloatingPointMacroExpansion(Expr e) {
17+
exists(MacroInvocation mi |
18+
mi.getMacroName() = "_CLASS_ARG" and
19+
mi.getMacro().getFile().getBaseName() = "corecrt_math.h" and
20+
mi.getAnExpandedElement() = e
21+
)
22+
}
23+
24+
/**
25+
* Determines if the sizeOfExpr is ignorable.
26+
*/
27+
predicate ignorableSizeof(SizeofExprOperator sizeofExpr) {
28+
// a common pattern found is to sizeof a binary operation to check a type
29+
// to then perfomr an onperaiton for a 32 or 64 bit type.
30+
// these cases often look like sizeof(x) >=4
31+
// more generally we see binary operations frequently used in different type
32+
// checks, where the sizeof is part of some comparison operation of a switch statement guard.
33+
// sizeof as an argument is also similarly used, but seemingly less frequently.
34+
exists(ComparisonOperation comp | comp.getAnOperand() = sizeofExpr)
35+
or
36+
exists(ConditionalStmt s | s.getControllingExpr() = sizeofExpr)
37+
or
38+
// another common practice is to use bit-wise operations in sizeof to allow the compiler to
39+
// 'pack' the size appropriate but get the size of the result out of a sizeof operation.
40+
sizeofExpr.getExprOperand() instanceof BinaryBitwiseOperation
41+
}
42+
43+
from SizeofExprOperator sizeofExpr, string message, Expr op
44+
where
45+
exists(string tmpMsg |
46+
(
47+
op instanceof BinaryOperation and tmpMsg = "binary operator"
48+
or
49+
op instanceof SizeofOperator and tmpMsg = "sizeof"
50+
) and
51+
if sizeofExpr.isInMacroExpansion()
52+
then message = tmpMsg + "(in a macro expansion)"
53+
else message = tmpMsg
54+
) and
55+
op = sizeofExpr.getExprOperand() and
56+
not isPartOfCrtFloatingPointMacroExpansion(op) and
57+
not ignorableSizeof(sizeofExpr)
58+
select sizeofExpr, "$@: $@ of $@ inside sizeof.", sizeofExpr, message,
59+
sizeofExpr.getEnclosingFunction(), "Usage", op, message
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#define SIZEOF_CHAR sizeof(char)
2+
3+
char* buffer;
4+
// bug - the code is really going to allocate sizeof(size_t) instead o fthe intended sizeof(char) * 10
5+
buffer = (char*) malloc(sizeof(SIZEOF_CHAR * 10));
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#define SIZEOF_CHAR sizeof(char)
2+
3+
char* buffer;
4+
buffer = (char*) malloc(SIZEOF_CHAR * 10);

0 commit comments

Comments
 (0)