mirror of
https://github.com/github/codeql.git
synced 2026-04-29 02:35:15 +02:00
Java: Add new query for large left shifts and bugfix ConstantExpAppearsNonConstant.
This commit is contained in:
@@ -14,10 +14,6 @@ Some expressions always evaluate to the same result, no matter what their subexp
|
||||
</li>
|
||||
<li><code>x % 1</code> always evaluates to <code>0</code>.
|
||||
</li>
|
||||
<li><code>x << 64</code> (when <code>x</code> is of type <code>long</code>) always evaluates to <code>0</code>.
|
||||
</li>
|
||||
<li><code>x << 32</code> (when <code>x</code> is not of type <code>long</code>) always evaluates to <code>0</code>.
|
||||
</li>
|
||||
<li><code>x & 0</code> always evaluates to <code>0</code>.
|
||||
</li>
|
||||
<li><code>x || true</code> always evaluates to <code>true</code>.
|
||||
@@ -58,7 +54,7 @@ an integer. The correct check is <code>x % 2 == 0</code>.
|
||||
|
||||
<li>
|
||||
The Java Language Specification:
|
||||
<a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.1">Multiplication operator *</a>, <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.3">Remainder operator %</a>, <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.19">Left shift operator <<</a>, <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.22.1">Bitwise AND operator &</a>, <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.23">Conditional-and operator &&</a> and <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.24">Conditional-or operator ||</a>.
|
||||
<a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.1">Multiplication operator *</a>, <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.3">Remainder operator %</a>, <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.22.1">Bitwise AND operator &</a>, <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.23">Conditional-and operator &&</a> and <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.24">Conditional-or operator ||</a>.
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
@@ -11,10 +11,6 @@
|
||||
|
||||
import java
|
||||
|
||||
int integralTypeWidth(IntegralType t) {
|
||||
if t.hasName("long") or t.hasName("Long") then result = 64 else result = 32
|
||||
}
|
||||
|
||||
int eval(Expr e) { result = e.(CompileTimeConstantExpr).getIntValue() }
|
||||
|
||||
predicate isConstantExp(Expr e) {
|
||||
@@ -48,13 +44,6 @@ predicate isConstantExp(Expr e) {
|
||||
eval(r.getRightOperand().getProperExpr()) = 1
|
||||
)
|
||||
or
|
||||
// Left shift by 64 (longs) or 32 (all other integer types) is constant.
|
||||
exists(LShiftExpr s | s = e |
|
||||
exists(IntegralType t | t = s.getLeftOperand().getType() |
|
||||
eval(s.getRightOperand().getProperExpr()) = integralTypeWidth(t)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(AndBitwiseExpr a | a = e | eval(a.getAnOperand().getProperExpr()) = 0)
|
||||
or
|
||||
exists(AndLogicalExpr a | a = e |
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
long longVal = intVal << 32; // BAD
|
||||
@@ -0,0 +1,47 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
The left shift operator only uses the lowest 5 bits of its right-hand side
|
||||
when the promoted type of its left-hand side is <code>int</code> and the
|
||||
lowest 6 bits when the type is <code>long</code>.
|
||||
</p>
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>
|
||||
Restrict the shift amount of <code>int</code>s to the range 0-31, or cast to <code>long</code> before left-shifting.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>
|
||||
The following line tries to left-shift an <code>int</code> 32 bits.
|
||||
</p>
|
||||
|
||||
<sample src="LShiftLargerThanTypeWidth.java" />
|
||||
|
||||
<p>
|
||||
However, left-shifting an <code>int</code> 32 bits is equivalent to
|
||||
left-shifting 0 bits, that is, not shifting at all. Instead the value should
|
||||
be cast to <code>long</code> before shifting to actually left-shift 32 bits.
|
||||
</p>
|
||||
|
||||
<sample src="LShiftLargerThanTypeWidthGood.java" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
|
||||
<li>
|
||||
The Java Language Specification:
|
||||
<a href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.19">Shift Operators</a>.
|
||||
</li>
|
||||
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @name Left shift by more than the type width
|
||||
* @description Left-shifting an integer by more than its type width indicates a mistake.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision very-high
|
||||
* @id java/lshift-larger-than-type-width
|
||||
* @tags correctness
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
int integralTypeWidth(IntegralType t) {
|
||||
if t.hasName("long") or t.hasName("Long") then result = 64 else result = 32
|
||||
}
|
||||
|
||||
from LShiftExpr shift, IntegralType t, int v, string typname, int width
|
||||
where
|
||||
shift.getLeftOperand().getType() = t and
|
||||
shift.getRightOperand().(CompileTimeConstantExpr).getIntValue() = v and
|
||||
width = integralTypeWidth(t) and
|
||||
v >= width and
|
||||
typname = ("a " + t.toString()).regexpReplaceAll("a ([aeiouAEIOU])", "an $1")
|
||||
select shift,
|
||||
"Left-shifting " + typname + " by more than " + width + " truncates the shift amount from " + v +
|
||||
" to " + (v % width)
|
||||
@@ -0,0 +1 @@
|
||||
long longVal = ((long)intVal) << 32; // GOOD
|
||||
Reference in New Issue
Block a user