mirror of
https://github.com/github/codeql.git
synced 2026-03-01 05:13:41 +01:00
Refactor specificSubExprSign
This commit is contained in:
@@ -3,6 +3,25 @@ newtype TSign =
|
||||
TZero() or
|
||||
TPos()
|
||||
|
||||
newtype TUnarySignOperation =
|
||||
TNegOp() or
|
||||
TIncOp() or
|
||||
TDecOp() or
|
||||
TBitNotOp()
|
||||
|
||||
newtype TBinarySignOperation =
|
||||
TAddOp() or
|
||||
TSubOp() or
|
||||
TMulOp() or
|
||||
TDivOp() or
|
||||
TRemOp() or
|
||||
TBitAndOp() or
|
||||
TBitOrOp() or
|
||||
TBitXorOp() or
|
||||
TLShiftOp() or
|
||||
TRShiftOp() or
|
||||
TURShiftOp()
|
||||
|
||||
/** Class representing expression signs (+, -, 0). */
|
||||
class Sign extends TSign {
|
||||
/** Gets the string representation of this sign. */
|
||||
@@ -67,6 +86,12 @@ class Sign extends TSign {
|
||||
this = TNeg() and s = TPos()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a possible sign after subtracting an expression with sign `s` from an expression
|
||||
* that has this sign.
|
||||
*/
|
||||
Sign sub(Sign s) { result = add(s.neg()) }
|
||||
|
||||
/**
|
||||
* Gets a possible sign after multiplying an expression with sign `s` to an expression
|
||||
* that has this sign.
|
||||
@@ -216,4 +241,40 @@ class Sign extends TSign {
|
||||
or
|
||||
result != TNeg() and this = TPos() and s != TZero()
|
||||
}
|
||||
|
||||
/** Perform `op` on this sign. */
|
||||
Sign applyUnaryOp(TUnarySignOperation op) {
|
||||
op = TIncOp() and result = inc()
|
||||
or
|
||||
op = TDecOp() and result = dec()
|
||||
or
|
||||
op = TNegOp() and result = neg()
|
||||
or
|
||||
op = TBitNotOp() and result = bitnot()
|
||||
}
|
||||
|
||||
/** Perform `op` on this sign and sign `s`. */
|
||||
Sign applyBinaryOp(Sign s, TBinarySignOperation op) {
|
||||
op = TAddOp() and result = add(s)
|
||||
or
|
||||
op = TSubOp() and result = sub(s)
|
||||
or
|
||||
op = TMulOp() and result = mul(s)
|
||||
or
|
||||
op = TDivOp() and result = div(s)
|
||||
or
|
||||
op = TRemOp() and result = rem(s)
|
||||
or
|
||||
op = TBitAndOp() and result = bitand(s)
|
||||
or
|
||||
op = TBitOrOp() and result = bitor(s)
|
||||
or
|
||||
op = TBitXorOp() and result = bitxor(s)
|
||||
or
|
||||
op = TLShiftOp() and result = lshift(s)
|
||||
or
|
||||
op = TRShiftOp() and result = rshift(s)
|
||||
or
|
||||
op = TURShiftOp() and result = urshift(s)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,6 +326,36 @@ Sign exprSign(Expr e) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a possible sign for `e` from the signs of its child nodes. */
|
||||
Sign specificSubExprSign(Expr e) {
|
||||
result = exprSign(getASubExpr(e))
|
||||
or
|
||||
e =
|
||||
any(DivExpr div |
|
||||
result = exprSign(div.getLeftOperand()) and
|
||||
result != TZero() and
|
||||
div.getRightOperand().(RealLiteral).getValue().toFloat() = 0
|
||||
)
|
||||
or
|
||||
exists(UnaryExpr unary | unary = e |
|
||||
result = exprSign(unary.getOperand()).applyUnaryOp(unary.getOp())
|
||||
)
|
||||
or
|
||||
exists(Sign s1, Sign s2 | binaryOpSigns(e, s1, s2) |
|
||||
result = s1.applyBinaryOp(s2, e.(BinaryExpr).getOp())
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate binaryOpSigns(Expr e, Sign lhs, Sign rhs) {
|
||||
lhs = binaryOpLhsSign(e) and
|
||||
rhs = binaryOpRhsSign(e)
|
||||
}
|
||||
|
||||
Sign binaryOpLhsSign(BinaryOperation e) { result = exprSign(e.getLeftOperand()) }
|
||||
|
||||
Sign binaryOpRhsSign(BinaryOperation e) { result = exprSign(e.getRightOperand()) }
|
||||
|
||||
/**
|
||||
* Dummy predicate that holds for any sign. This is added to improve readability
|
||||
* of cases where the sign is unrestricted.
|
||||
|
||||
@@ -6,6 +6,7 @@ module Private {
|
||||
private import semmle.code.java.dataflow.SSA as Ssa
|
||||
private import semmle.code.java.controlflow.Guards as G
|
||||
private import java as J
|
||||
private import Sign
|
||||
import Impl
|
||||
|
||||
class ConstantIntegerExpr = RU::ConstantIntegerExpr;
|
||||
@@ -42,6 +43,135 @@ module Private {
|
||||
|
||||
class Field = J::Field;
|
||||
|
||||
class DivExpr = J::DivExpr;
|
||||
|
||||
class BinaryOperation extends J::Expr {
|
||||
BinaryOperation() {
|
||||
this instanceof J::BinaryExpr or
|
||||
this instanceof J::AssignOp
|
||||
}
|
||||
|
||||
Expr getLeftOperand() {
|
||||
result = this.(J::BinaryExpr).getLeftOperand() or result = this.(J::AssignOp).getDest()
|
||||
}
|
||||
|
||||
Expr getRightOperand() {
|
||||
result = this.(J::BinaryExpr).getRightOperand() or result = this.(J::AssignOp).getRhs()
|
||||
}
|
||||
}
|
||||
|
||||
/** Class to represent float and double literals. */
|
||||
class RealLiteral extends J::Literal {
|
||||
RealLiteral() {
|
||||
this instanceof J::FloatingPointLiteral or
|
||||
this instanceof J::DoubleLiteral
|
||||
}
|
||||
}
|
||||
|
||||
/** Class to represent unary expressions. */
|
||||
class UnaryExpr extends J::Expr {
|
||||
UnaryExpr() {
|
||||
this instanceof J::PreIncExpr or
|
||||
this instanceof J::PreDecExpr or
|
||||
this instanceof J::MinusExpr or
|
||||
this instanceof J::BitNotExpr
|
||||
}
|
||||
|
||||
/** Returns the operand of this expression. */
|
||||
Expr getOperand() {
|
||||
result = this.(J::PreIncExpr).getExpr() or
|
||||
result = this.(J::PreDecExpr).getExpr() or
|
||||
result = this.(J::MinusExpr).getExpr() or
|
||||
result = this.(J::BitNotExpr).getExpr()
|
||||
}
|
||||
|
||||
/** Returns the operation representing this expression. */
|
||||
TUnarySignOperation getOp() {
|
||||
this instanceof J::PreIncExpr and result = TIncOp()
|
||||
or
|
||||
this instanceof J::PreDecExpr and result = TDecOp()
|
||||
or
|
||||
this instanceof J::MinusExpr and result = TNegOp()
|
||||
or
|
||||
this instanceof J::BitNotExpr and result = TBitNotOp()
|
||||
}
|
||||
}
|
||||
|
||||
/** Class to represent binary expressions. */
|
||||
class BinaryExpr extends J::Expr {
|
||||
BinaryExpr() {
|
||||
this instanceof J::AddExpr or
|
||||
this instanceof J::AssignAddExpr or
|
||||
this instanceof J::SubExpr or
|
||||
this instanceof J::AssignSubExpr or
|
||||
this instanceof J::MulExpr or
|
||||
this instanceof J::AssignMulExpr or
|
||||
this instanceof J::DivExpr or
|
||||
this instanceof J::AssignDivExpr or
|
||||
this instanceof J::RemExpr or
|
||||
this instanceof J::AssignRemExpr or
|
||||
this instanceof J::AndBitwiseExpr or
|
||||
this instanceof J::AssignAndExpr or
|
||||
this instanceof J::OrBitwiseExpr or
|
||||
this instanceof J::AssignOrExpr or
|
||||
this instanceof J::XorBitwiseExpr or
|
||||
this instanceof J::AssignXorExpr or
|
||||
this instanceof J::LShiftExpr or
|
||||
this instanceof J::AssignLShiftExpr or
|
||||
this instanceof J::RShiftExpr or
|
||||
this instanceof J::AssignRShiftExpr or
|
||||
this instanceof J::URShiftExpr or
|
||||
this instanceof J::AssignURShiftExpr
|
||||
}
|
||||
|
||||
/** Returns the operation representing this expression. */
|
||||
TBinarySignOperation getOp() {
|
||||
this instanceof J::AddExpr and result = TAddOp()
|
||||
or
|
||||
this instanceof J::AssignAddExpr and result = TAddOp()
|
||||
or
|
||||
this instanceof J::SubExpr and result = TSubOp()
|
||||
or
|
||||
this instanceof J::AssignSubExpr and result = TSubOp()
|
||||
or
|
||||
this instanceof J::MulExpr and result = TMulOp()
|
||||
or
|
||||
this instanceof J::AssignMulExpr and result = TMulOp()
|
||||
or
|
||||
this instanceof J::DivExpr and result = TDivOp()
|
||||
or
|
||||
this instanceof J::AssignDivExpr and result = TDivOp()
|
||||
or
|
||||
this instanceof J::RemExpr and result = TRemOp()
|
||||
or
|
||||
this instanceof J::AssignRemExpr and result = TRemOp()
|
||||
or
|
||||
this instanceof J::AndBitwiseExpr and result = TBitAndOp()
|
||||
or
|
||||
this instanceof J::AssignAndExpr and result = TBitAndOp()
|
||||
or
|
||||
this instanceof J::OrBitwiseExpr and result = TBitOrOp()
|
||||
or
|
||||
this instanceof J::AssignOrExpr and result = TBitOrOp()
|
||||
or
|
||||
this instanceof J::XorBitwiseExpr and result = TBitXorOp()
|
||||
or
|
||||
this instanceof J::AssignXorExpr and result = TBitXorOp()
|
||||
or
|
||||
this instanceof J::LShiftExpr and result = TLShiftOp()
|
||||
or
|
||||
this instanceof J::AssignLShiftExpr and result = TLShiftOp()
|
||||
or
|
||||
this instanceof J::RShiftExpr and result = TRShiftOp()
|
||||
or
|
||||
this instanceof J::AssignRShiftExpr and result = TRShiftOp()
|
||||
or
|
||||
this instanceof J::URShiftExpr and result = TURShiftOp()
|
||||
or
|
||||
this instanceof J::AssignURShiftExpr and result = TURShiftOp()
|
||||
}
|
||||
}
|
||||
|
||||
predicate ssaRead = RU::ssaRead/2;
|
||||
|
||||
predicate guardControlsSsaRead = RU::guardControlsSsaRead/3;
|
||||
@@ -169,87 +299,14 @@ private module Impl {
|
||||
else anySign(result)
|
||||
}
|
||||
|
||||
/** Gets a possible sign for `e` from the signs of its child nodes. */
|
||||
Sign specificSubExprSign(Expr e) {
|
||||
result = exprSign(e.(AssignExpr).getSource())
|
||||
or
|
||||
result = exprSign(e.(PlusExpr).getExpr())
|
||||
or
|
||||
result = exprSign(e.(PostIncExpr).getExpr())
|
||||
or
|
||||
result = exprSign(e.(PostDecExpr).getExpr())
|
||||
or
|
||||
result = exprSign(e.(PreIncExpr).getExpr()).inc()
|
||||
or
|
||||
result = exprSign(e.(PreDecExpr).getExpr()).dec()
|
||||
or
|
||||
result = exprSign(e.(MinusExpr).getExpr()).neg()
|
||||
or
|
||||
result = exprSign(e.(BitNotExpr).getExpr()).bitnot()
|
||||
or
|
||||
exists(DivExpr div |
|
||||
div = e and
|
||||
result = exprSign(div.getLeftOperand()) and
|
||||
result != TZero()
|
||||
|
|
||||
div.getRightOperand().(FloatingPointLiteral).getValue().toFloat() = 0 or
|
||||
div.getRightOperand().(DoubleLiteral).getValue().toFloat() = 0
|
||||
)
|
||||
or
|
||||
exists(Sign s1, Sign s2 | binaryOpSigns(e, s1, s2) |
|
||||
(e instanceof AssignAddExpr or e instanceof AddExpr) and
|
||||
result = s1.add(s2)
|
||||
or
|
||||
(e instanceof AssignSubExpr or e instanceof SubExpr) and
|
||||
result = s1.add(s2.neg())
|
||||
or
|
||||
(e instanceof AssignMulExpr or e instanceof MulExpr) and
|
||||
result = s1.mul(s2)
|
||||
or
|
||||
(e instanceof AssignDivExpr or e instanceof DivExpr) and
|
||||
result = s1.div(s2)
|
||||
or
|
||||
(e instanceof AssignRemExpr or e instanceof RemExpr) and
|
||||
result = s1.rem(s2)
|
||||
or
|
||||
(e instanceof AssignAndExpr or e instanceof AndBitwiseExpr) and
|
||||
result = s1.bitand(s2)
|
||||
or
|
||||
(e instanceof AssignOrExpr or e instanceof OrBitwiseExpr) and
|
||||
result = s1.bitor(s2)
|
||||
or
|
||||
(e instanceof AssignXorExpr or e instanceof XorBitwiseExpr) and
|
||||
result = s1.bitxor(s2)
|
||||
or
|
||||
(e instanceof AssignLShiftExpr or e instanceof LShiftExpr) and
|
||||
result = s1.lshift(s2)
|
||||
or
|
||||
(e instanceof AssignRShiftExpr or e instanceof RShiftExpr) and
|
||||
result = s1.rshift(s2)
|
||||
or
|
||||
(e instanceof AssignURShiftExpr or e instanceof URShiftExpr) and
|
||||
result = s1.urshift(s2)
|
||||
)
|
||||
or
|
||||
result = exprSign(e.(ChooseExpr).getAResultExpr())
|
||||
or
|
||||
result = exprSign(e.(CastExpr).getExpr())
|
||||
}
|
||||
|
||||
private Sign binaryOpLhsSign(Expr e) {
|
||||
result = exprSign(e.(BinaryExpr).getLeftOperand()) or
|
||||
result = exprSign(e.(AssignOp).getDest())
|
||||
}
|
||||
|
||||
private Sign binaryOpRhsSign(Expr e) {
|
||||
result = exprSign(e.(BinaryExpr).getRightOperand()) or
|
||||
result = exprSign(e.(AssignOp).getRhs())
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate binaryOpSigns(Expr e, Sign lhs, Sign rhs) {
|
||||
lhs = binaryOpLhsSign(e) and
|
||||
rhs = binaryOpRhsSign(e)
|
||||
/** Returns a sub expression of `e` for expression types where the sign depends on the child. */
|
||||
Expr getASubExpr(Expr e) {
|
||||
result = e.(AssignExpr).getSource() or
|
||||
result = e.(PlusExpr).getExpr() or
|
||||
result = e.(PostIncExpr).getExpr() or
|
||||
result = e.(PostDecExpr).getExpr() or
|
||||
result = e.(ChooseExpr).getAResultExpr() or
|
||||
result = e.(CastExpr).getExpr()
|
||||
}
|
||||
|
||||
Expr getARead(SsaVariable v) { result = v.getAUse() }
|
||||
|
||||
Reference in New Issue
Block a user