Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Rust: Add ComparisonOperation library. #19535

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 22, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions 98 rust/ql/lib/codeql/rust/elements/ComparisonOperation.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
private import codeql.rust.elements.Expr

Check warning on line 1 in rust/ql/lib/codeql/rust/elements/ComparisonOperation.qll

View workflow job for this annotation

GitHub Actions / qldoc

Missing QLdoc for file ComparisonOperation
Fixed Show fixed Hide fixed
private import codeql.rust.elements.BinaryExpr
private import codeql.rust.elements.Operation

/**
* A comparison operation, such as `==`, `<` or `>=`.
geoffw0 marked this conversation as resolved.
Show resolved Hide resolved
*/
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 EqualOperation extends EqualityOperationImpl, BinaryExpr {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BinaryExpr can be removed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I prefer EqualityOperation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EqualityOperation is "an operation to do with equality", i.e. == or !=.

EqualOperation is specifically ==.

We can't use "EqualityOperation" to describe both.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed redundant BinaryExpr.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. Then I think I slightly prefer Equal_s_Operation over EqualOperation, but I'll let you decide.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I agree that's a better name. Updated.

EqualOperation() { this.getOperatorName() = "==" }
}

/**
* The not equal comparison operation, `!=`.
*/
final class NotEqualOperation extends EqualityOperationImpl {
geoffw0 marked this conversation as resolved.
Show resolved Hide resolved
NotEqualOperation() { 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, BinaryExpr {
geoffw0 marked this conversation as resolved.
Show resolved Hide resolved
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, BinaryExpr {
GreaterThanOperation() { this.getOperatorName() = ">" }

override Expr getGreaterOperand() { result = this.getLhs() }

override Expr getLesserOperand() { result = this.getRhs() }
}

/**
* The less than or equal comparison operation, `<=`.
*/
final class LessOrEqualOperation extends RelationalOperationImpl, BinaryExpr {
LessOrEqualOperation() { this.getOperatorName() = "<=" }

override Expr getGreaterOperand() { result = this.getRhs() }

override Expr getLesserOperand() { result = this.getLhs() }
}

/**
* The less than or equal comparison operation, `>=`.
geoffw0 marked this conversation as resolved.
Show resolved Hide resolved
*/
final class GreaterOrEqualOperation extends RelationalOperationImpl, BinaryExpr {
GreaterOrEqualOperation() { this.getOperatorName() = ">=" }

override Expr getGreaterOperand() { result = this.getLhs() }

override Expr getLesserOperand() { result = this.getRhs() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,44 +43,16 @@ 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
geoffw0 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
1 change: 1 addition & 0 deletions 1 rust/ql/lib/rust.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 29 additions & 1 deletion 30 rust/ql/test/library-tests/operations/Operations.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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 EqualOperation and result = "EqualOperation"
or
op instanceof NotEqualOperation and result = "NotEqualOperation"
or
op instanceof RelationalOperation and result = "RelationalOperation"
or
op instanceof LessThanOperation and result = "LessThanOperation"
or
op instanceof GreaterThanOperation and result = "GreaterThanOperation"
or
op instanceof LessOrEqualOperation and result = "LessOrEqualOperation"
or
op instanceof GreaterOrEqualOperation and result = "GreaterOrEqualOperation"
}

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 |
Expand All @@ -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()
)
)
}
Expand Down
12 changes: 6 additions & 6 deletions 12 rust/ql/test/library-tests/operations/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 EqualOperation
x != y; // $ Operation Op=!= Operands=2 BinaryExpr ComparisonOperation EqualityOperation NotEqualOperation
x < y; // $ Operation Op=< Operands=2 BinaryExpr ComparisonOperation RelationalOperation LessThanOperation Greater=y Lesser=x
x <= y; // $ Operation Op=<= Operands=2 BinaryExpr ComparisonOperation RelationalOperation LessOrEqualOperation 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 GreaterOrEqualOperation Greater=x Lesser=y

// arithmetic operations
x + y; // $ Operation Op=+ Operands=2 BinaryExpr
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.