Skip to content

Commit d27596a

Browse files
authored
Merge pull request #19535 from geoffw0/operations2
Rust: Add ComparisonOperation library.
2 parents c4bbfbc + 8522039 commit d27596a

File tree

6 files changed

+145
-39
lines changed

6 files changed

+145
-39
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* Provides classes for comparison operations.
3+
*/
4+
5+
private import codeql.rust.elements.BinaryExpr
6+
private import codeql.rust.elements.Operation
7+
8+
/**
9+
* A comparison operation, such as `==`, `<`, or `>=`.
10+
*/
11+
abstract private class ComparisonOperationImpl extends Operation { }
12+
13+
final class ComparisonOperation = ComparisonOperationImpl;
14+
15+
/**
16+
* An equality comparison operation, `==` or `!=`.
17+
*/
18+
abstract private class EqualityOperationImpl extends BinaryExpr, ComparisonOperationImpl { }
19+
20+
final class EqualityOperation = EqualityOperationImpl;
21+
22+
/**
23+
* The equal comparison operation, `==`.
24+
*/
25+
final class EqualsOperation extends EqualityOperationImpl {
26+
EqualsOperation() { this.getOperatorName() = "==" }
27+
}
28+
29+
/**
30+
* The not equal comparison operation, `!=`.
31+
*/
32+
final class NotEqualsOperation extends EqualityOperationImpl {
33+
NotEqualsOperation() { this.getOperatorName() = "!=" }
34+
}
35+
36+
/**
37+
* A relational comparison operation, that is, one of `<=`, `<`, `>`, or `>=`.
38+
*/
39+
abstract private class RelationalOperationImpl extends BinaryExpr, ComparisonOperationImpl {
40+
/**
41+
* Gets the operand on the "greater" (or "greater-or-equal") side
42+
* of this relational expression, that is, the side that is larger
43+
* if the overall expression evaluates to `true`; for example on
44+
* `x <= 20` this is the `20`, and on `y > 0` it is `y`.
45+
*/
46+
abstract Expr getGreaterOperand();
47+
48+
/**
49+
* Gets the operand on the "lesser" (or "lesser-or-equal") side
50+
* of this relational expression, that is, the side that is smaller
51+
* if the overall expression evaluates to `true`; for example on
52+
* `x <= 20` this is `x`, and on `y > 0` it is the `0`.
53+
*/
54+
abstract Expr getLesserOperand();
55+
}
56+
57+
final class RelationalOperation = RelationalOperationImpl;
58+
59+
/**
60+
* The less than comparison operation, `<`.
61+
*/
62+
final class LessThanOperation extends RelationalOperationImpl {
63+
LessThanOperation() { this.getOperatorName() = "<" }
64+
65+
override Expr getGreaterOperand() { result = this.getRhs() }
66+
67+
override Expr getLesserOperand() { result = this.getLhs() }
68+
}
69+
70+
/**
71+
* The greater than comparison operation, `>`.
72+
*/
73+
final class GreaterThanOperation extends RelationalOperationImpl {
74+
GreaterThanOperation() { this.getOperatorName() = ">" }
75+
76+
override Expr getGreaterOperand() { result = this.getLhs() }
77+
78+
override Expr getLesserOperand() { result = this.getRhs() }
79+
}
80+
81+
/**
82+
* The less than or equal comparison operation, `<=`.
83+
*/
84+
final class LessOrEqualsOperation extends RelationalOperationImpl {
85+
LessOrEqualsOperation() { this.getOperatorName() = "<=" }
86+
87+
override Expr getGreaterOperand() { result = this.getRhs() }
88+
89+
override Expr getLesserOperand() { result = this.getLhs() }
90+
}
91+
92+
/**
93+
* The greater than or equal comparison operation, `>=`.
94+
*/
95+
final class GreaterOrEqualsOperation extends RelationalOperationImpl {
96+
GreaterOrEqualsOperation() { this.getOperatorName() = ">=" }
97+
98+
override Expr getGreaterOperand() { result = this.getLhs() }
99+
100+
override Expr getLesserOperand() { result = this.getRhs() }
101+
}

rust/ql/lib/codeql/rust/elements/LogicalOperation.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/**
2+
* Provides classes for logical operations.
3+
*/
4+
15
private import codeql.rust.elements.Expr
26
private import codeql.rust.elements.BinaryExpr
37
private import codeql.rust.elements.PrefixExpr

rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -43,51 +43,23 @@ module UncontrolledAllocationSize {
4343
}
4444
}
4545

46-
/**
47-
* Gets the operand on the "greater" (or "greater-or-equal") side
48-
* of this relational expression, that is, the side that is larger
49-
* if the overall expression evaluates to `true`; for example on
50-
* `x <= 20` this is the `20`, and on `y > 0` it is `y`.
51-
*/
52-
private Expr getGreaterOperand(BinaryExpr op) {
53-
op.getOperatorName() = ["<", "<="] and
54-
result = op.getRhs()
55-
or
56-
op.getOperatorName() = [">", ">="] and
57-
result = op.getLhs()
58-
}
59-
60-
/**
61-
* Gets the operand on the "lesser" (or "lesser-or-equal") side
62-
* of this relational expression, that is, the side that is smaller
63-
* if the overall expression evaluates to `true`; for example on
64-
* `x <= 20` this is `x`, and on `y > 0` it is the `0`.
65-
*/
66-
private Expr getLesserOperand(BinaryExpr op) {
67-
op.getOperatorName() = ["<", "<="] and
68-
result = op.getLhs()
69-
or
70-
op.getOperatorName() = [">", ">="] and
71-
result = op.getRhs()
72-
}
73-
7446
/**
7547
* Holds if comparison `g` having result `branch` indicates an upper bound for the sub-expression
7648
* `node`. For example when the comparison `x < 10` is true, we have an upper bound for `x`.
7749
*/
7850
private predicate isUpperBoundCheck(CfgNodes::AstCfgNode g, Cfg::CfgNode node, boolean branch) {
7951
exists(BinaryExpr cmp | g = cmp.getACfgNode() |
80-
node = getLesserOperand(cmp).getACfgNode() and
52+
node = cmp.(RelationalOperation).getLesserOperand().getACfgNode() and
8153
branch = true
8254
or
83-
node = getGreaterOperand(cmp).getACfgNode() and
55+
node = cmp.(RelationalOperation).getGreaterOperand().getACfgNode() and
8456
branch = false
8557
or
86-
cmp.getOperatorName() = "==" and
58+
cmp instanceof EqualsOperation and
8759
[cmp.getLhs(), cmp.getRhs()].getACfgNode() = node and
8860
branch = true
8961
or
90-
cmp.getOperatorName() = "!=" and
62+
cmp instanceof NotEqualsOperation and
9163
[cmp.getLhs(), cmp.getRhs()].getACfgNode() = node and
9264
branch = false
9365
)

rust/ql/lib/rust.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import codeql.Locations
55
import codeql.files.FileSystem
66
import codeql.rust.elements.Operation
77
import codeql.rust.elements.AssignmentOperation
8+
import codeql.rust.elements.ComparisonOperation
89
import codeql.rust.elements.LiteralExprExt
910
import codeql.rust.elements.LogicalOperation
1011
import codeql.rust.elements.AsyncBlockExpr

rust/ql/test/library-tests/operations/Operations.ql

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,30 @@ string describe(Expr op) {
1313
op instanceof LogicalOperation and result = "LogicalOperation"
1414
or
1515
op instanceof RefExpr and result = "RefExpr"
16+
or
17+
op instanceof ComparisonOperation and result = "ComparisonOperation"
18+
or
19+
op instanceof EqualityOperation and result = "EqualityOperation"
20+
or
21+
op instanceof EqualsOperation and result = "EqualsOperation"
22+
or
23+
op instanceof NotEqualsOperation and result = "NotEqualsOperation"
24+
or
25+
op instanceof RelationalOperation and result = "RelationalOperation"
26+
or
27+
op instanceof LessThanOperation and result = "LessThanOperation"
28+
or
29+
op instanceof GreaterThanOperation and result = "GreaterThanOperation"
30+
or
31+
op instanceof LessOrEqualsOperation and result = "LessOrEqualsOperation"
32+
or
33+
op instanceof GreaterOrEqualsOperation and result = "GreaterOrEqualsOperation"
1634
}
1735

1836
module OperationsTest implements TestSig {
19-
string getARelevantTag() { result = describe(_) or result = ["Op", "Operands"] }
37+
string getARelevantTag() {
38+
result = describe(_) or result = ["Op", "Operands", "Greater", "Lesser"]
39+
}
2040

2141
predicate hasActualResult(Location location, string element, string tag, string value) {
2242
exists(Expr op |
@@ -33,6 +53,14 @@ module OperationsTest implements TestSig {
3353
op instanceof Operation and
3454
tag = "Operands" and
3555
value = count(op.(Operation).getAnOperand()).toString()
56+
or
57+
op instanceof RelationalOperation and
58+
tag = "Greater" and
59+
value = op.(RelationalOperation).getGreaterOperand().toString()
60+
or
61+
op instanceof RelationalOperation and
62+
tag = "Lesser" and
63+
value = op.(RelationalOperation).getLesserOperand().toString()
3664
)
3765
)
3866
}

rust/ql/test/library-tests/operations/test.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ fn test_operations(
1111
x = y; // $ Operation Op== Operands=2 AssignmentOperation BinaryExpr
1212

1313
// comparison operations
14-
x == y; // $ Operation Op=== Operands=2 BinaryExpr
15-
x != y; // $ Operation Op=!= Operands=2 BinaryExpr
16-
x < y; // $ Operation Op=< Operands=2 BinaryExpr
17-
x <= y; // $ Operation Op=<= Operands=2 BinaryExpr
18-
x > y; // $ Operation Op=> Operands=2 BinaryExpr
19-
x >= y; // $ Operation Op=>= Operands=2 BinaryExpr
14+
x == y; // $ Operation Op=== Operands=2 BinaryExpr ComparisonOperation EqualityOperation EqualsOperation
15+
x != y; // $ Operation Op=!= Operands=2 BinaryExpr ComparisonOperation EqualityOperation NotEqualsOperation
16+
x < y; // $ Operation Op=< Operands=2 BinaryExpr ComparisonOperation RelationalOperation LessThanOperation Greater=y Lesser=x
17+
x <= y; // $ Operation Op=<= Operands=2 BinaryExpr ComparisonOperation RelationalOperation LessOrEqualsOperation Greater=y Lesser=x
18+
x > y; // $ Operation Op=> Operands=2 BinaryExpr ComparisonOperation RelationalOperation GreaterThanOperation Greater=x Lesser=y
19+
x >= y; // $ Operation Op=>= Operands=2 BinaryExpr ComparisonOperation RelationalOperation GreaterOrEqualsOperation Greater=x Lesser=y
2020

2121
// arithmetic operations
2222
x + y; // $ Operation Op=+ Operands=2 BinaryExpr

0 commit comments

Comments
 (0)