diff --git a/rust/ql/lib/codeql/rust/elements/ComparisonOperation.qll b/rust/ql/lib/codeql/rust/elements/ComparisonOperation.qll new file mode 100644 index 000000000000..24fe9b0b19d6 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/ComparisonOperation.qll @@ -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() } +} diff --git a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll index eaf1ff06b7d5..d0099be0b93c 100644 --- a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll @@ -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 diff --git a/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll b/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll index b8ab16090d19..2f4898f6e9da 100644 --- a/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll +++ b/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll @@ -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 ) diff --git a/rust/ql/lib/rust.qll b/rust/ql/lib/rust.qll index 7b97f68469ca..4a533b34badc 100644 --- a/rust/ql/lib/rust.qll +++ b/rust/ql/lib/rust.qll @@ -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 diff --git a/rust/ql/test/library-tests/operations/Operations.ql b/rust/ql/test/library-tests/operations/Operations.ql index cbb81bdcb025..482373c8d052 100644 --- a/rust/ql/test/library-tests/operations/Operations.ql +++ b/rust/ql/test/library-tests/operations/Operations.ql @@ -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() ) ) } diff --git a/rust/ql/test/library-tests/operations/test.rs b/rust/ql/test/library-tests/operations/test.rs index f82a9501fef4..dba47f5faa3d 100644 --- a/rust/ql/test/library-tests/operations/test.rs +++ b/rust/ql/test/library-tests/operations/test.rs @@ -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