mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Add files via upload
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
bool a=1,b=0,c=1,res;
|
||||
...
|
||||
res = a||b^c; // BAD: possible priority error `res==1`
|
||||
...
|
||||
res = a||(b^c); // GOOD: `res==1`
|
||||
...
|
||||
res = (a||b)^c; // GOOD: `res==0`
|
||||
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Find places of confusing use of logical and bitwise operations.</p>
|
||||
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>We recommend using parentheses to explicitly emphasize priority.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>The following example demonstrates fallacious and fixed methods of using logical and bitwise operations.</p>
|
||||
<sample src="OperatorPrecedenceLogicErrorWhenUseBitwiseOrLogicalOperations.c" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
CERT C Coding Standard:
|
||||
<a href="https://wiki.sei.cmu.edu/confluence/display/c/EXP00-C.+Use+parentheses+for+precedence+of+operation">EXP00-C. Use parentheses for precedence of operation</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* @name Operator Precedence Logic Error When Use Bitwise Or Logical Operations
|
||||
* @description --Finding places to use bit and logical operations, without explicit priority allocation.
|
||||
* --For example, `a || b ^ c` and `(a || b) ^ c` give different results when `b` is zero.
|
||||
* @kind problem
|
||||
* @id cpp/operator-precedence-logic-error-when-use-bitwise-logical-operations
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @tags correctness
|
||||
* security
|
||||
* external/cwe/cwe-783
|
||||
* external/cwe/cwe-480
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
|
||||
|
||||
/** Holds if `exptmp` equals expression logical or followed by logical and. */
|
||||
predicate isLogicalOrAndExpr(Expr exptmp) {
|
||||
not exptmp.(LogicalOrExpr).getLeftOperand() instanceof BinaryOperation and
|
||||
not exptmp.(LogicalOrExpr).getRightOperand().isParenthesised() and
|
||||
exptmp.(LogicalOrExpr).getRightOperand() instanceof LogicalAndExpr
|
||||
}
|
||||
|
||||
/** Holds if `exptmp` equals expression logical or followed by bit operation. */
|
||||
predicate isLogicalOrandBitwise(Expr exptmp) {
|
||||
not exptmp.(LogicalOrExpr).getLeftOperand() instanceof BinaryOperation and
|
||||
not exptmp.(LogicalOrExpr).getRightOperand().isParenthesised() and
|
||||
(
|
||||
exptmp.(LogicalOrExpr).getRightOperand().(BinaryBitwiseOperation).getLeftOperand().getType()
|
||||
instanceof BoolType and
|
||||
not exptmp
|
||||
.(LogicalOrExpr)
|
||||
.getRightOperand()
|
||||
.(BinaryBitwiseOperation)
|
||||
.getRightOperand()
|
||||
.getValue() = "0" and
|
||||
not exptmp
|
||||
.(LogicalOrExpr)
|
||||
.getRightOperand()
|
||||
.(BinaryBitwiseOperation)
|
||||
.getRightOperand()
|
||||
.getValue() = "1"
|
||||
)
|
||||
or
|
||||
not exptmp.(LogicalAndExpr).getLeftOperand() instanceof BinaryOperation and
|
||||
not exptmp.(LogicalAndExpr).getRightOperand().isParenthesised() and
|
||||
(
|
||||
exptmp.(LogicalAndExpr).getRightOperand().(BinaryBitwiseOperation).getLeftOperand().getType()
|
||||
instanceof BoolType and
|
||||
not exptmp
|
||||
.(LogicalAndExpr)
|
||||
.getRightOperand()
|
||||
.(BinaryBitwiseOperation)
|
||||
.getRightOperand()
|
||||
.getValue() = "0" and
|
||||
not exptmp
|
||||
.(LogicalAndExpr)
|
||||
.getRightOperand()
|
||||
.(BinaryBitwiseOperation)
|
||||
.getRightOperand()
|
||||
.getValue() = "1"
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `exptmp` equals expression bit operations in reverse priority order. */
|
||||
predicate isBitwiseandBitwise(Expr exptmp) {
|
||||
not exptmp.(BitwiseOrExpr).getLeftOperand() instanceof BinaryOperation and
|
||||
not exptmp.(BitwiseOrExpr).getRightOperand().isParenthesised() and
|
||||
(
|
||||
exptmp.(BitwiseOrExpr).getRightOperand() instanceof BitwiseAndExpr or
|
||||
exptmp.(BitwiseOrExpr).getRightOperand() instanceof BitwiseXorExpr
|
||||
)
|
||||
or
|
||||
not exptmp.(BitwiseXorExpr).getLeftOperand() instanceof BinaryOperation and
|
||||
not exptmp.(BitwiseXorExpr).getRightOperand().isParenthesised() and
|
||||
exptmp.(BitwiseXorExpr).getRightOperand() instanceof BitwiseAndExpr
|
||||
}
|
||||
|
||||
/** Holds if the range contains no boundary values. */
|
||||
predicate isRealRange(Expr exp) {
|
||||
upperBound(exp).toString() != "18446744073709551616" and
|
||||
upperBound(exp).toString() != "9223372036854775807" and
|
||||
upperBound(exp).toString() != "4294967295" and
|
||||
upperBound(exp).toString() != "Infinity" and
|
||||
upperBound(exp).toString() != "NaN" and
|
||||
lowerBound(exp).toString() != "-9223372036854775808" and
|
||||
lowerBound(exp).toString() != "-4294967296" and
|
||||
lowerBound(exp).toString() != "-Infinity" and
|
||||
lowerBound(exp).toString() != "NaN" and
|
||||
upperBound(exp) != 2147483647 and
|
||||
upperBound(exp) != 268435455 and
|
||||
upperBound(exp) != 33554431 and
|
||||
upperBound(exp) != 8388607 and
|
||||
upperBound(exp) != 65535 and
|
||||
upperBound(exp) != 32767 and
|
||||
upperBound(exp) != 255 and
|
||||
upperBound(exp) != 127 and
|
||||
lowerBound(exp) != -2147483648 and
|
||||
lowerBound(exp) != -268435456 and
|
||||
lowerBound(exp) != -33554432 and
|
||||
lowerBound(exp) != -8388608 and
|
||||
lowerBound(exp) != -65536 and
|
||||
lowerBound(exp) != -32768 and
|
||||
lowerBound(exp) != -128
|
||||
or
|
||||
lowerBound(exp) = 0 and
|
||||
upperBound(exp) = 1
|
||||
}
|
||||
|
||||
/** Holds if expressions are of different size or range */
|
||||
predicate isDifferentSize(Expr exp1, Expr exp2, Expr exp3) {
|
||||
exp1.getType().getSize() = exp2.getType().getSize() and
|
||||
exp1.getType().getSize() != exp3.getType().getSize()
|
||||
or
|
||||
(
|
||||
isRealRange(exp1) and
|
||||
isRealRange(exp2) and
|
||||
isRealRange(exp3)
|
||||
) and
|
||||
upperBound(exp1).maximum(upperBound(exp2)) - upperBound(exp1).minimum(upperBound(exp2)) < 16 and
|
||||
lowerBound(exp1).maximum(lowerBound(exp2)) - lowerBound(exp1).minimum(lowerBound(exp2)) < 16 and
|
||||
(
|
||||
upperBound(exp1).maximum(upperBound(exp3)) - upperBound(exp1).minimum(upperBound(exp3)) > 256 or
|
||||
lowerBound(exp1).maximum(lowerBound(exp2)) - lowerBound(exp1).minimum(lowerBound(exp2)) > 256
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if it is possible to get different values of the expression */
|
||||
predicate isDifferentResults(
|
||||
Expr exp1, Expr exp2, Expr exp3, BinaryBitwiseOperation op1, BinaryBitwiseOperation op2
|
||||
) {
|
||||
(
|
||||
isRealRange(exp1) and
|
||||
isRealRange(exp2) and
|
||||
isRealRange(exp3)
|
||||
) and
|
||||
exists(int i1, int i2, int i3 |
|
||||
i1 in [lowerBound(exp1).floor() .. upperBound(exp1).floor()] and
|
||||
i2 in [lowerBound(exp2).floor() .. upperBound(exp2).floor()] and
|
||||
i3 in [lowerBound(exp3).floor() .. upperBound(exp3).floor()] and
|
||||
(
|
||||
op1 instanceof BitwiseOrExpr and
|
||||
op2 instanceof BitwiseAndExpr and
|
||||
i1.bitOr(i2).bitAnd(i3) != i2.bitAnd(i3).bitOr(i1)
|
||||
or
|
||||
op1 instanceof BitwiseOrExpr and
|
||||
op2 instanceof BitwiseXorExpr and
|
||||
i1.bitOr(i2).bitXor(i3) != i2.bitXor(i3).bitOr(i1)
|
||||
or
|
||||
op1 instanceof BitwiseXorExpr and
|
||||
op2 instanceof BitwiseAndExpr and
|
||||
i1.bitXor(i2).bitAnd(i3) != i2.bitAnd(i3).bitXor(i1)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
from Expr exp, string msg
|
||||
where
|
||||
isLogicalOrAndExpr(exp) and
|
||||
msg = "Logical and has a higher priority."
|
||||
or
|
||||
isLogicalOrandBitwise(exp) and
|
||||
msg = "Binary operations has higher priority."
|
||||
or
|
||||
isBitwiseandBitwise(exp) and
|
||||
isDifferentSize(exp.(BinaryBitwiseOperation).getLeftOperand(),
|
||||
exp.(BinaryBitwiseOperation).getRightOperand().(BinaryBitwiseOperation).getLeftOperand(),
|
||||
exp.(BinaryBitwiseOperation).getRightOperand().(BinaryBitwiseOperation).getRightOperand()) and
|
||||
msg = "Expression ranges do not match operation precedence."
|
||||
or
|
||||
isBitwiseandBitwise(exp) and
|
||||
isDifferentResults(exp.(BinaryBitwiseOperation).getLeftOperand(),
|
||||
exp.(BinaryBitwiseOperation).getRightOperand().(BinaryBitwiseOperation).getLeftOperand(),
|
||||
exp.(BinaryBitwiseOperation).getRightOperand().(BinaryBitwiseOperation).getRightOperand(),
|
||||
exp.(BinaryBitwiseOperation),
|
||||
exp.(BinaryBitwiseOperation).getRightOperand().(BinaryBitwiseOperation)) and
|
||||
msg = "specify the priority with parentheses."
|
||||
select exp, msg
|
||||
Reference in New Issue
Block a user