mirror of
https://github.com/github/codeql.git
synced 2026-05-02 04:05:14 +02:00
Merge pull request #5600 from ihsinme/ihsinme-patch-258
CPP: Add query for CWE-691 Insufficient Control Flow Management When Using Bit Operations
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
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
|
||||
...
|
||||
if(len>0 && memset(buf,0,len)) return 1; // GOOD: `memset` will be called after the `len` variable has been checked.
|
||||
...
|
||||
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<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>
|
||||
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>We recommend that you evaluate the correctness of using the specified bit operations.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>The following example demonstrates the erroneous and fixed use of bit and logical operations.</p>
|
||||
<sample src="InsufficientControlFlowManagementWhenUsingBitOperations.c" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
CWE Common Weakness Enumeration:
|
||||
<a href="https://cwe.mitre.org/data/definitions/691.html"> CWE-691: Insufficient Control Flow Management</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @name Errors When Using Bit Operations
|
||||
* @description Unlike the binary operations `||` and `&&`, there is no sequence point after evaluating an
|
||||
* operand of a bitwise operation like `|` or `&`. If left-to-right evaluation is expected this may be confusing.
|
||||
* @kind problem
|
||||
* @id cpp/errors-when-using-bit-operations
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @tags correctness
|
||||
* security
|
||||
* external/cwe/cwe-691
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
|
||||
/**
|
||||
* Dangerous uses of bit operations.
|
||||
* For example: `if(intA>0 & intA<10 & charBuf&myFunc(charBuf[intA]))`.
|
||||
* In this case, the function will be called in any case, and even the sequence of the call is not guaranteed.
|
||||
*/
|
||||
class DangerousBitOperations extends BinaryBitwiseOperation {
|
||||
FunctionCall bfc;
|
||||
|
||||
/**
|
||||
* The assignment indicates the conscious use of the bit operator.
|
||||
* Use in comparison, conversion, or return value indicates conscious use of the bit operator.
|
||||
* The use of shifts and bitwise operations on any element of an expression indicates a conscious use of the bitwise operator.
|
||||
*/
|
||||
DangerousBitOperations() {
|
||||
bfc = this.getRightOperand() and
|
||||
not this.getParent*() instanceof Assignment and
|
||||
not this.getParent*() instanceof Initializer and
|
||||
not this.getParent*() instanceof ReturnStmt and
|
||||
not this.getParent*() instanceof EqualityOperation and
|
||||
not this.getParent*() instanceof UnaryLogicalOperation and
|
||||
not this.getParent*() instanceof BinaryLogicalOperation and
|
||||
not this.getAChild*() instanceof BitwiseXorExpr and
|
||||
not this.getAChild*() instanceof LShiftExpr and
|
||||
not this.getAChild*() instanceof RShiftExpr
|
||||
}
|
||||
|
||||
/** Holds when part of a bit expression is used in a logical operation. */
|
||||
predicate useInLogicalOperations() {
|
||||
exists(BinaryLogicalOperation blop, Expr exp |
|
||||
blop.getAChild*() = exp and
|
||||
exp.(FunctionCall).getTarget() = bfc.getTarget() and
|
||||
not exp.getParent() instanceof ComparisonOperation and
|
||||
not exp.getParent() instanceof BinaryBitwiseOperation
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds when part of a bit expression is used as part of another supply. For example, as an argument to another function. */
|
||||
predicate useInOtherCalls() {
|
||||
bfc.hasQualifier() or
|
||||
bfc.getTarget() instanceof Operator or
|
||||
exists(FunctionCall fc | fc.getAnArgument().getAChild*() = this) or
|
||||
bfc.getTarget() instanceof BuiltInFunction
|
||||
}
|
||||
|
||||
/** Holds when the bit expression contains both arguments and a function call. */
|
||||
predicate dangerousArgumentChecking() {
|
||||
not this.getLeftOperand() instanceof Call and
|
||||
globalValueNumber(this.getLeftOperand().getAChild*()) = globalValueNumber(bfc.getAnArgument())
|
||||
}
|
||||
|
||||
/** Holds when function calls are present in the bit expression. */
|
||||
predicate functionCallsInBitsExpression() {
|
||||
this.getLeftOperand().getAChild*() instanceof FunctionCall
|
||||
}
|
||||
}
|
||||
|
||||
from DangerousBitOperations dbo
|
||||
where
|
||||
not dbo.useInOtherCalls() and
|
||||
dbo.useInLogicalOperations() and
|
||||
(not dbo.functionCallsInBitsExpression() or dbo.dangerousArgumentChecking())
|
||||
select dbo, "This bitwise operation appears in a context where a Boolean operation is expected."
|
||||
@@ -0,0 +1,2 @@
|
||||
| test.c:8:6:8:51 | ... & ... | This bitwise operation appears in a context where a Boolean operation is expected. |
|
||||
| test.c:10:6:10:30 | ... & ... | This bitwise operation appears in a context where a Boolean operation is expected. |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-691/InsufficientControlFlowManagementWhenUsingBitOperations.ql
|
||||
@@ -0,0 +1,28 @@
|
||||
int tmpFunction(){
|
||||
return 5;
|
||||
}
|
||||
void workFunction_0(char *s) {
|
||||
int intSize;
|
||||
char buf[80];
|
||||
if(intSize>0 && intSize<80 && memset(buf,0,intSize)) return; // GOOD
|
||||
if(intSize>0 & intSize<80 & memset(buf,0,intSize)) return; // BAD
|
||||
if(intSize>0 && tmpFunction()) return;
|
||||
if(intSize<0 & tmpFunction()) return; // BAD
|
||||
}
|
||||
void workFunction_1(char *s) {
|
||||
int intA,intB;
|
||||
|
||||
if(intA + intB) return; // BAD [NOT DETECTED]
|
||||
if(intA + intB>4) return; // GOOD
|
||||
if(intA>0 && (intA + intB)) return; // BAD [NOT DETECTED]
|
||||
while(intA>0)
|
||||
{
|
||||
if(intB - intA<10) break;
|
||||
intA--;
|
||||
}while(intA>0); // BAD [NOT DETECTED]
|
||||
while(intA>0)
|
||||
{
|
||||
if(intB - intA<10) break;
|
||||
intA--;
|
||||
} // GOOD
|
||||
}
|
||||
Reference in New Issue
Block a user