mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #19535 from geoffw0/operations2
Rust: Add ComparisonOperation library.
This commit is contained in:
101
rust/ql/lib/codeql/rust/elements/ComparisonOperation.qll
Normal file
101
rust/ql/lib/codeql/rust/elements/ComparisonOperation.qll
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Provides classes for comparison operations.
|
||||
*/
|
||||
|
||||
private import codeql.rust.elements.BinaryExpr
|
||||
private import codeql.rust.elements.Operation
|
||||
|
||||
/**
|
||||
* A comparison operation, such as `==`, `<`, or `>=`.
|
||||
*/
|
||||
abstract private class ComparisonOperationImpl extends Operation { }
|
||||
|
||||
final class ComparisonOperation = ComparisonOperationImpl;
|
||||
|
||||
/**
|
||||
* An equality comparison operation, `==` or `!=`.
|
||||
*/
|
||||
abstract private class EqualityOperationImpl extends BinaryExpr, ComparisonOperationImpl { }
|
||||
|
||||
final class EqualityOperation = EqualityOperationImpl;
|
||||
|
||||
/**
|
||||
* The equal comparison operation, `==`.
|
||||
*/
|
||||
final class EqualsOperation extends EqualityOperationImpl {
|
||||
EqualsOperation() { this.getOperatorName() = "==" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The not equal comparison operation, `!=`.
|
||||
*/
|
||||
final class NotEqualsOperation extends EqualityOperationImpl {
|
||||
NotEqualsOperation() { this.getOperatorName() = "!=" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A relational comparison operation, that is, one of `<=`, `<`, `>`, or `>=`.
|
||||
*/
|
||||
abstract private class RelationalOperationImpl extends BinaryExpr, ComparisonOperationImpl {
|
||||
/**
|
||||
* Gets the operand on the "greater" (or "greater-or-equal") side
|
||||
* of this relational expression, that is, the side that is larger
|
||||
* if the overall expression evaluates to `true`; for example on
|
||||
* `x <= 20` this is the `20`, and on `y > 0` it is `y`.
|
||||
*/
|
||||
abstract Expr getGreaterOperand();
|
||||
|
||||
/**
|
||||
* Gets the operand on the "lesser" (or "lesser-or-equal") side
|
||||
* of this relational expression, that is, the side that is smaller
|
||||
* if the overall expression evaluates to `true`; for example on
|
||||
* `x <= 20` this is `x`, and on `y > 0` it is the `0`.
|
||||
*/
|
||||
abstract Expr getLesserOperand();
|
||||
}
|
||||
|
||||
final class RelationalOperation = RelationalOperationImpl;
|
||||
|
||||
/**
|
||||
* The less than comparison operation, `<`.
|
||||
*/
|
||||
final class LessThanOperation extends RelationalOperationImpl {
|
||||
LessThanOperation() { this.getOperatorName() = "<" }
|
||||
|
||||
override Expr getGreaterOperand() { result = this.getRhs() }
|
||||
|
||||
override Expr getLesserOperand() { result = this.getLhs() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The greater than comparison operation, `>`.
|
||||
*/
|
||||
final class GreaterThanOperation extends RelationalOperationImpl {
|
||||
GreaterThanOperation() { this.getOperatorName() = ">" }
|
||||
|
||||
override Expr getGreaterOperand() { result = this.getLhs() }
|
||||
|
||||
override Expr getLesserOperand() { result = this.getRhs() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The less than or equal comparison operation, `<=`.
|
||||
*/
|
||||
final class LessOrEqualsOperation extends RelationalOperationImpl {
|
||||
LessOrEqualsOperation() { this.getOperatorName() = "<=" }
|
||||
|
||||
override Expr getGreaterOperand() { result = this.getRhs() }
|
||||
|
||||
override Expr getLesserOperand() { result = this.getLhs() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The greater than or equal comparison operation, `>=`.
|
||||
*/
|
||||
final class GreaterOrEqualsOperation extends RelationalOperationImpl {
|
||||
GreaterOrEqualsOperation() { this.getOperatorName() = ">=" }
|
||||
|
||||
override Expr getGreaterOperand() { result = this.getLhs() }
|
||||
|
||||
override Expr getLesserOperand() { result = this.getRhs() }
|
||||
}
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* Provides classes for logical operations.
|
||||
*/
|
||||
|
||||
private import codeql.rust.elements.Expr
|
||||
private import codeql.rust.elements.BinaryExpr
|
||||
private import codeql.rust.elements.PrefixExpr
|
||||
|
||||
@@ -43,51 +43,23 @@ module UncontrolledAllocationSize {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the operand on the "greater" (or "greater-or-equal") side
|
||||
* of this relational expression, that is, the side that is larger
|
||||
* if the overall expression evaluates to `true`; for example on
|
||||
* `x <= 20` this is the `20`, and on `y > 0` it is `y`.
|
||||
*/
|
||||
private Expr getGreaterOperand(BinaryExpr op) {
|
||||
op.getOperatorName() = ["<", "<="] and
|
||||
result = op.getRhs()
|
||||
or
|
||||
op.getOperatorName() = [">", ">="] and
|
||||
result = op.getLhs()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the operand on the "lesser" (or "lesser-or-equal") side
|
||||
* of this relational expression, that is, the side that is smaller
|
||||
* if the overall expression evaluates to `true`; for example on
|
||||
* `x <= 20` this is `x`, and on `y > 0` it is the `0`.
|
||||
*/
|
||||
private Expr getLesserOperand(BinaryExpr op) {
|
||||
op.getOperatorName() = ["<", "<="] and
|
||||
result = op.getLhs()
|
||||
or
|
||||
op.getOperatorName() = [">", ">="] and
|
||||
result = op.getRhs()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if comparison `g` having result `branch` indicates an upper bound for the sub-expression
|
||||
* `node`. For example when the comparison `x < 10` is true, we have an upper bound for `x`.
|
||||
*/
|
||||
private predicate isUpperBoundCheck(CfgNodes::AstCfgNode g, Cfg::CfgNode node, boolean branch) {
|
||||
exists(BinaryExpr cmp | g = cmp.getACfgNode() |
|
||||
node = getLesserOperand(cmp).getACfgNode() and
|
||||
node = cmp.(RelationalOperation).getLesserOperand().getACfgNode() and
|
||||
branch = true
|
||||
or
|
||||
node = getGreaterOperand(cmp).getACfgNode() and
|
||||
node = cmp.(RelationalOperation).getGreaterOperand().getACfgNode() and
|
||||
branch = false
|
||||
or
|
||||
cmp.getOperatorName() = "==" and
|
||||
cmp instanceof EqualsOperation and
|
||||
[cmp.getLhs(), cmp.getRhs()].getACfgNode() = node and
|
||||
branch = true
|
||||
or
|
||||
cmp.getOperatorName() = "!=" and
|
||||
cmp instanceof NotEqualsOperation and
|
||||
[cmp.getLhs(), cmp.getRhs()].getACfgNode() = node and
|
||||
branch = false
|
||||
)
|
||||
|
||||
@@ -5,6 +5,7 @@ import codeql.Locations
|
||||
import codeql.files.FileSystem
|
||||
import codeql.rust.elements.Operation
|
||||
import codeql.rust.elements.AssignmentOperation
|
||||
import codeql.rust.elements.ComparisonOperation
|
||||
import codeql.rust.elements.LiteralExprExt
|
||||
import codeql.rust.elements.LogicalOperation
|
||||
import codeql.rust.elements.AsyncBlockExpr
|
||||
|
||||
@@ -13,10 +13,30 @@ string describe(Expr op) {
|
||||
op instanceof LogicalOperation and result = "LogicalOperation"
|
||||
or
|
||||
op instanceof RefExpr and result = "RefExpr"
|
||||
or
|
||||
op instanceof ComparisonOperation and result = "ComparisonOperation"
|
||||
or
|
||||
op instanceof EqualityOperation and result = "EqualityOperation"
|
||||
or
|
||||
op instanceof EqualsOperation and result = "EqualsOperation"
|
||||
or
|
||||
op instanceof NotEqualsOperation and result = "NotEqualsOperation"
|
||||
or
|
||||
op instanceof RelationalOperation and result = "RelationalOperation"
|
||||
or
|
||||
op instanceof LessThanOperation and result = "LessThanOperation"
|
||||
or
|
||||
op instanceof GreaterThanOperation and result = "GreaterThanOperation"
|
||||
or
|
||||
op instanceof LessOrEqualsOperation and result = "LessOrEqualsOperation"
|
||||
or
|
||||
op instanceof GreaterOrEqualsOperation and result = "GreaterOrEqualsOperation"
|
||||
}
|
||||
|
||||
module OperationsTest implements TestSig {
|
||||
string getARelevantTag() { result = describe(_) or result = ["Op", "Operands"] }
|
||||
string getARelevantTag() {
|
||||
result = describe(_) or result = ["Op", "Operands", "Greater", "Lesser"]
|
||||
}
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(Expr op |
|
||||
@@ -33,6 +53,14 @@ module OperationsTest implements TestSig {
|
||||
op instanceof Operation and
|
||||
tag = "Operands" and
|
||||
value = count(op.(Operation).getAnOperand()).toString()
|
||||
or
|
||||
op instanceof RelationalOperation and
|
||||
tag = "Greater" and
|
||||
value = op.(RelationalOperation).getGreaterOperand().toString()
|
||||
or
|
||||
op instanceof RelationalOperation and
|
||||
tag = "Lesser" and
|
||||
value = op.(RelationalOperation).getLesserOperand().toString()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,12 +11,12 @@ fn test_operations(
|
||||
x = y; // $ Operation Op== Operands=2 AssignmentOperation BinaryExpr
|
||||
|
||||
// comparison operations
|
||||
x == y; // $ Operation Op=== Operands=2 BinaryExpr
|
||||
x != y; // $ Operation Op=!= Operands=2 BinaryExpr
|
||||
x < y; // $ Operation Op=< Operands=2 BinaryExpr
|
||||
x <= y; // $ Operation Op=<= Operands=2 BinaryExpr
|
||||
x > y; // $ Operation Op=> Operands=2 BinaryExpr
|
||||
x >= y; // $ Operation Op=>= Operands=2 BinaryExpr
|
||||
x == y; // $ Operation Op=== Operands=2 BinaryExpr ComparisonOperation EqualityOperation EqualsOperation
|
||||
x != y; // $ Operation Op=!= Operands=2 BinaryExpr ComparisonOperation EqualityOperation NotEqualsOperation
|
||||
x < y; // $ Operation Op=< Operands=2 BinaryExpr ComparisonOperation RelationalOperation LessThanOperation Greater=y Lesser=x
|
||||
x <= y; // $ Operation Op=<= Operands=2 BinaryExpr ComparisonOperation RelationalOperation LessOrEqualsOperation Greater=y Lesser=x
|
||||
x > y; // $ Operation Op=> Operands=2 BinaryExpr ComparisonOperation RelationalOperation GreaterThanOperation Greater=x Lesser=y
|
||||
x >= y; // $ Operation Op=>= Operands=2 BinaryExpr ComparisonOperation RelationalOperation GreaterOrEqualsOperation Greater=x Lesser=y
|
||||
|
||||
// arithmetic operations
|
||||
x + y; // $ Operation Op=+ Operands=2 BinaryExpr
|
||||
|
||||
Reference in New Issue
Block a user