|
| 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 |
0 commit comments