Skip to content

Commit 92508be

Browse files
authored
Merge pull request github#5600 from ihsinme/ihsinme-patch-258
CPP: Add query for CWE-691 Insufficient Control Flow Management When Using Bit Operations
2 parents f43d427 + a436988 commit 92508be

6 files changed

+141
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
if(len>0 & memset(buf,0,len)) return 1; // BAD: `memset` will be called regardless of the value of the `len` variable. moreover, one cannot be sure that it will happen after verification
2+
...
3+
if(len>0 && memset(buf,0,len)) return 1; // GOOD: `memset` will be called after the `len` variable has been checked.
4+
...
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>Using bitwise operations can be a mistake in some situations. For example, if parameters are evaluated in an expression and the function should be called only upon certain test results. These bitwise operations look suspicious and require developer attention.</p>
7+
8+
9+
</overview>
10+
<recommendation>
11+
12+
<p>We recommend that you evaluate the correctness of using the specified bit operations.</p>
13+
14+
</recommendation>
15+
<example>
16+
<p>The following example demonstrates the erroneous and fixed use of bit and logical operations.</p>
17+
<sample src="InsufficientControlFlowManagementWhenUsingBitOperations.c" />
18+
19+
</example>
20+
<references>
21+
22+
<li>
23+
CWE Common Weakness Enumeration:
24+
<a href="https://cwe.mitre.org/data/definitions/691.html"> CWE-691: Insufficient Control Flow Management</a>.
25+
</li>
26+
27+
</references>
28+
</qhelp>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* @name Errors When Using Bit Operations
3+
* @description Unlike the binary operations `||` and `&&`, there is no sequence point after evaluating an
4+
* operand of a bitwise operation like `|` or `&`. If left-to-right evaluation is expected this may be confusing.
5+
* @kind problem
6+
* @id cpp/errors-when-using-bit-operations
7+
* @problem.severity warning
8+
* @precision medium
9+
* @tags correctness
10+
* security
11+
* external/cwe/cwe-691
12+
*/
13+
14+
import cpp
15+
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
16+
17+
/**
18+
* Dangerous uses of bit operations.
19+
* For example: `if(intA>0 & intA<10 & charBuf&myFunc(charBuf[intA]))`.
20+
* In this case, the function will be called in any case, and even the sequence of the call is not guaranteed.
21+
*/
22+
class DangerousBitOperations extends BinaryBitwiseOperation {
23+
FunctionCall bfc;
24+
25+
/**
26+
* The assignment indicates the conscious use of the bit operator.
27+
* Use in comparison, conversion, or return value indicates conscious use of the bit operator.
28+
* The use of shifts and bitwise operations on any element of an expression indicates a conscious use of the bitwise operator.
29+
*/
30+
DangerousBitOperations() {
31+
bfc = this.getRightOperand() and
32+
not this.getParent*() instanceof Assignment and
33+
not this.getParent*() instanceof Initializer and
34+
not this.getParent*() instanceof ReturnStmt and
35+
not this.getParent*() instanceof EqualityOperation and
36+
not this.getParent*() instanceof UnaryLogicalOperation and
37+
not this.getParent*() instanceof BinaryLogicalOperation and
38+
not this.getAChild*() instanceof BitwiseXorExpr and
39+
not this.getAChild*() instanceof LShiftExpr and
40+
not this.getAChild*() instanceof RShiftExpr
41+
}
42+
43+
/** Holds when part of a bit expression is used in a logical operation. */
44+
predicate useInLogicalOperations() {
45+
exists(BinaryLogicalOperation blop, Expr exp |
46+
blop.getAChild*() = exp and
47+
exp.(FunctionCall).getTarget() = bfc.getTarget() and
48+
not exp.getParent() instanceof ComparisonOperation and
49+
not exp.getParent() instanceof BinaryBitwiseOperation
50+
)
51+
}
52+
53+
/** Holds when part of a bit expression is used as part of another supply. For example, as an argument to another function. */
54+
predicate useInOtherCalls() {
55+
bfc.hasQualifier() or
56+
bfc.getTarget() instanceof Operator or
57+
exists(FunctionCall fc | fc.getAnArgument().getAChild*() = this) or
58+
bfc.getTarget() instanceof BuiltInFunction
59+
}
60+
61+
/** Holds when the bit expression contains both arguments and a function call. */
62+
predicate dangerousArgumentChecking() {
63+
not this.getLeftOperand() instanceof Call and
64+
globalValueNumber(this.getLeftOperand().getAChild*()) = globalValueNumber(bfc.getAnArgument())
65+
}
66+
67+
/** Holds when function calls are present in the bit expression. */
68+
predicate functionCallsInBitsExpression() {
69+
this.getLeftOperand().getAChild*() instanceof FunctionCall
70+
}
71+
}
72+
73+
from DangerousBitOperations dbo
74+
where
75+
not dbo.useInOtherCalls() and
76+
dbo.useInLogicalOperations() and
77+
(not dbo.functionCallsInBitsExpression() or dbo.dangerousArgumentChecking())
78+
select dbo, "This bitwise operation appears in a context where a Boolean operation is expected."
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.c:8:6:8:51 | ... & ... | This bitwise operation appears in a context where a Boolean operation is expected. |
2+
| test.c:10:6:10:30 | ... & ... | This bitwise operation appears in a context where a Boolean operation is expected. |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
experimental/Security/CWE/CWE-691/InsufficientControlFlowManagementWhenUsingBitOperations.ql
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
int tmpFunction(){
2+
return 5;
3+
}
4+
void workFunction_0(char *s) {
5+
int intSize;
6+
char buf[80];
7+
if(intSize>0 && intSize<80 && memset(buf,0,intSize)) return; // GOOD
8+
if(intSize>0 & intSize<80 & memset(buf,0,intSize)) return; // BAD
9+
if(intSize>0 && tmpFunction()) return;
10+
if(intSize<0 & tmpFunction()) return; // BAD
11+
}
12+
void workFunction_1(char *s) {
13+
int intA,intB;
14+
15+
if(intA + intB) return; // BAD [NOT DETECTED]
16+
if(intA + intB>4) return; // GOOD
17+
if(intA>0 && (intA + intB)) return; // BAD [NOT DETECTED]
18+
while(intA>0)
19+
{
20+
if(intB - intA<10) break;
21+
intA--;
22+
}while(intA>0); // BAD [NOT DETECTED]
23+
while(intA>0)
24+
{
25+
if(intB - intA<10) break;
26+
intA--;
27+
} // GOOD
28+
}

0 commit comments

Comments
 (0)