From 93f8cea8845783adbac926b459989ba93107537d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 9 Apr 2025 15:44:54 +0100 Subject: [PATCH 01/10] Rust: Add + clean up some QLDoc. --- .../rust/elements/AssignmentOperation.qll | 18 ++++++++++++------ .../codeql/rust/elements/LogicalOperation.qll | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/AssignmentOperation.qll b/rust/ql/lib/codeql/rust/elements/AssignmentOperation.qll index 368e5738c191..a3ca1722b577 100644 --- a/rust/ql/lib/codeql/rust/elements/AssignmentOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/AssignmentOperation.qll @@ -1,16 +1,23 @@ -/** Provides classes for assignment operations. */ +/** + * Provides classes for assignment operations. + */ private import rust private import codeql.rust.elements.internal.BinaryExprImpl -/** An assignment operation. */ +/** + * An assignment operation, for example: + * ```rust + * x = y; + * x += y; + * ``` + */ abstract private class AssignmentOperationImpl extends Impl::BinaryExpr { } final class AssignmentOperation = AssignmentOperationImpl; /** - * An assignment expression, for example - * + * An assignment expression, for example: * ```rust * x = y; * ``` @@ -22,8 +29,7 @@ final class AssignmentExpr extends AssignmentOperationImpl { } /** - * A compound assignment expression, for example - * + * A compound assignment expression, for example: * ```rust * x += y; * ``` diff --git a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll index fdbfb5d4613a..ab9aa6ef0fd4 100644 --- a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll @@ -2,30 +2,48 @@ private import codeql.rust.elements.Expr private import codeql.rust.elements.BinaryExpr private import codeql.rust.elements.PrefixExpr +/** + * A logical operation, such as `&&`, `||` or `!`. + */ abstract private class LogicalOperationImpl extends Expr { abstract Expr getAnOperand(); } final class LogicalOperation = LogicalOperationImpl; +/** + * A binary logical operation, such as `&&` or `||`. + */ abstract private class BinaryLogicalOperationImpl extends BinaryExpr, LogicalOperationImpl { override Expr getAnOperand() { result = [this.getLhs(), this.getRhs()] } } final class BinaryLogicalOperation = BinaryLogicalOperationImpl; +/** + * The logical and operation, `&&`. + */ final class LogicalAndExpr extends BinaryLogicalOperationImpl, BinaryExpr { LogicalAndExpr() { this.getOperatorName() = "&&" } } +/** + * The logical or operation, `||`. + */ final class LogicalOrExpr extends BinaryLogicalOperationImpl { LogicalOrExpr() { this.getOperatorName() = "||" } } +/** + * A unary logical operation, such as `!`. + */ abstract private class UnaryLogicalOperationImpl extends PrefixExpr, LogicalOperationImpl { } final class UnaryLogicalOperation = UnaryLogicalOperationImpl; +/** + * A logical not operation, `!`. + */ final class LogicalNotExpr extends UnaryLogicalOperationImpl { LogicalNotExpr() { this.getOperatorName() = "!" } From f64e86fe2e661d88b892c483e7d8fe7015d39c9b Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 9 Apr 2025 20:55:34 +0100 Subject: [PATCH 02/10] Rust: Add a library test for Operations. --- .../operations/Operations.expected | 0 .../library-tests/operations/Operations.ql | 30 ++++++++++ rust/ql/test/library-tests/operations/test.rs | 57 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 rust/ql/test/library-tests/operations/Operations.expected create mode 100644 rust/ql/test/library-tests/operations/Operations.ql create mode 100644 rust/ql/test/library-tests/operations/test.rs diff --git a/rust/ql/test/library-tests/operations/Operations.expected b/rust/ql/test/library-tests/operations/Operations.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/rust/ql/test/library-tests/operations/Operations.ql b/rust/ql/test/library-tests/operations/Operations.ql new file mode 100644 index 000000000000..7605aa9e7196 --- /dev/null +++ b/rust/ql/test/library-tests/operations/Operations.ql @@ -0,0 +1,30 @@ +import rust +import utils.test.InlineExpectationsTest + +string describe(Expr op) { + op instanceof PrefixExpr and result = "PrefixExpr" + or + op instanceof BinaryExpr and result = "BinaryExpr" + or + op instanceof AssignmentOperation and result = "AssignmentOperation" + or + op instanceof LogicalOperation and result = "LogicalOperation" + or + op instanceof RefExpr and result = "RefExpr" +} + +module OperationsTest implements TestSig { + string getARelevantTag() { result = describe(_) } + + predicate hasActualResult(Location location, string element, string tag, string value) { + exists(Expr op | + location = op.getLocation() and + location.getFile().getBaseName() != "" and + element = op.toString() and + tag = describe(op) and + value = "" + ) + } +} + +import MakeTest diff --git a/rust/ql/test/library-tests/operations/test.rs b/rust/ql/test/library-tests/operations/test.rs new file mode 100644 index 000000000000..84152bd70723 --- /dev/null +++ b/rust/ql/test/library-tests/operations/test.rs @@ -0,0 +1,57 @@ + +// --- tests --- + +fn test_operations( + y: i32, a: bool, b: bool, + ptr: &i32, res: Result) -> Result<(), ()> +{ + let mut x: i32; + + // simple assignment + x = y; // $ AssignmentOperation BinaryExpr + + // comparison operations + x == y; // $ BinaryExpr + x != y; // $ BinaryExpr + x < y; // $ BinaryExpr + x <= y; // $ BinaryExpr + x > y; // $ BinaryExpr + x >= y; // $ BinaryExpr + + // arithmetic operations + x + y; // $ BinaryExpr + x - y; // $ BinaryExpr + x * y; // $ BinaryExpr + x / y; // $ BinaryExpr + x % y; // $ BinaryExpr + x += y; // $ AssignmentOperation BinaryExpr + x -= y; // $ AssignmentOperation BinaryExpr + x *= y; // $ AssignmentOperation BinaryExpr + x /= y; // $ AssignmentOperation BinaryExpr + x %= y; // $ AssignmentOperation BinaryExpr + -x; // $ PrefixExpr + + // logical operations + a && b; // $ BinaryExpr LogicalOperation + a || b; // $ BinaryExpr LogicalOperation + !a; // $ PrefixExpr LogicalOperation + + // bitwise operations + x & y; // $ BinaryExpr + x | y; // $ BinaryExpr + x ^ y; // $ BinaryExpr + x << y; // $ BinaryExpr + x >> y; // $ BinaryExpr + x &= y; // $ AssignmentOperation BinaryExpr + x |= y; // $ AssignmentOperation BinaryExpr + x ^= y; // $ AssignmentOperation BinaryExpr + x <<= y; // $ AssignmentOperation BinaryExpr + x >>= y; // $ AssignmentOperation BinaryExpr + + // miscellaneous expressions that might be operations + *ptr; // $ PrefixExpr + &x; // $ RefExpr + res?; + + return Ok(()); +} From 060d5152c470bbe09de81c4186cc542398193b13 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 9 Apr 2025 16:02:54 +0100 Subject: [PATCH 03/10] Rust: Add an Operation class above LogicalOperation, AssignmentOperation etc. --- .../codeql/rust/elements/LogicalOperation.qll | 3 +- .../ql/lib/codeql/rust/elements/Operation.qll | 19 ++++++ .../rust/elements/internal/BinaryExprImpl.qll | 3 +- .../rust/elements/internal/PrefixExprImpl.qll | 3 +- rust/ql/lib/rust.qll | 1 + .../library-tests/operations/Operations.ql | 2 + rust/ql/test/library-tests/operations/test.rs | 64 +++++++++---------- 7 files changed, 60 insertions(+), 35 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/elements/Operation.qll diff --git a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll index ab9aa6ef0fd4..7638bea15fdb 100644 --- a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll @@ -1,11 +1,12 @@ private import codeql.rust.elements.Expr private import codeql.rust.elements.BinaryExpr private import codeql.rust.elements.PrefixExpr +private import codeql.rust.elements.Operation /** * A logical operation, such as `&&`, `||` or `!`. */ -abstract private class LogicalOperationImpl extends Expr { +abstract private class LogicalOperationImpl extends Operation { abstract Expr getAnOperand(); } diff --git a/rust/ql/lib/codeql/rust/elements/Operation.qll b/rust/ql/lib/codeql/rust/elements/Operation.qll new file mode 100644 index 000000000000..a1915f837fdd --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/Operation.qll @@ -0,0 +1,19 @@ +/** + * Provides classes for operations. + */ + +private import rust +private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl + +/** + * INTERNAL: This module contains the customizable definition of `Operation` and should not + * be referenced directly. + */ +module OperationImpl { + /** + * An operation, for example `&&`, `+=`, `!` or `*`. + */ + abstract class Operation extends ExprImpl::Expr { } +} + +final class Operation = OperationImpl::Operation; diff --git a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll index 6aac95fcacee..bb7106cf6e98 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll @@ -5,6 +5,7 @@ */ private import codeql.rust.elements.internal.generated.BinaryExpr +private import codeql.rust.elements.Operation::OperationImpl as OperationImpl /** * INTERNAL: This module contains the customizable definition of `BinaryExpr` and should not @@ -22,7 +23,7 @@ module Impl { * x += y; * ``` */ - class BinaryExpr extends Generated::BinaryExpr { + class BinaryExpr extends Generated::BinaryExpr, OperationImpl::Operation { override string toStringImpl() { result = "... " + this.getOperatorName() + " ..." } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll index bf77c7b88ea4..2008be60660c 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll @@ -5,6 +5,7 @@ */ private import codeql.rust.elements.internal.generated.PrefixExpr +private import codeql.rust.elements.Operation::OperationImpl as OperationImpl /** * INTERNAL: This module contains the customizable definition of `PrefixExpr` and should not @@ -20,7 +21,7 @@ module Impl { * let z = *ptr; * ``` */ - class PrefixExpr extends Generated::PrefixExpr { + class PrefixExpr extends Generated::PrefixExpr, OperationImpl::Operation { override string toStringImpl() { result = this.getOperatorName() + " ..." } } } diff --git a/rust/ql/lib/rust.qll b/rust/ql/lib/rust.qll index ff97a37b5d1f..f09f49b30bb6 100644 --- a/rust/ql/lib/rust.qll +++ b/rust/ql/lib/rust.qll @@ -3,6 +3,7 @@ import codeql.rust.elements import codeql.Locations import codeql.files.FileSystem +import codeql.rust.elements.Operation import codeql.rust.elements.AssignmentOperation 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 7605aa9e7196..1609d4b5d22f 100644 --- a/rust/ql/test/library-tests/operations/Operations.ql +++ b/rust/ql/test/library-tests/operations/Operations.ql @@ -2,6 +2,8 @@ import rust import utils.test.InlineExpectationsTest string describe(Expr op) { + op instanceof Operation and result = "Operation" + or op instanceof PrefixExpr and result = "PrefixExpr" or op instanceof BinaryExpr and result = "BinaryExpr" diff --git a/rust/ql/test/library-tests/operations/test.rs b/rust/ql/test/library-tests/operations/test.rs index 84152bd70723..7ec3d8a3eef1 100644 --- a/rust/ql/test/library-tests/operations/test.rs +++ b/rust/ql/test/library-tests/operations/test.rs @@ -8,48 +8,48 @@ fn test_operations( let mut x: i32; // simple assignment - x = y; // $ AssignmentOperation BinaryExpr + x = y; // $ Operation AssignmentOperation BinaryExpr // comparison operations - x == y; // $ BinaryExpr - x != y; // $ BinaryExpr - x < y; // $ BinaryExpr - x <= y; // $ BinaryExpr - x > y; // $ BinaryExpr - x >= y; // $ BinaryExpr + x == y; // $ Operation BinaryExpr + x != y; // $ Operation BinaryExpr + x < y; // $ Operation BinaryExpr + x <= y; // $ Operation BinaryExpr + x > y; // $ Operation BinaryExpr + x >= y; // $ Operation BinaryExpr // arithmetic operations - x + y; // $ BinaryExpr - x - y; // $ BinaryExpr - x * y; // $ BinaryExpr - x / y; // $ BinaryExpr - x % y; // $ BinaryExpr - x += y; // $ AssignmentOperation BinaryExpr - x -= y; // $ AssignmentOperation BinaryExpr - x *= y; // $ AssignmentOperation BinaryExpr - x /= y; // $ AssignmentOperation BinaryExpr - x %= y; // $ AssignmentOperation BinaryExpr - -x; // $ PrefixExpr + x + y; // $ Operation BinaryExpr + x - y; // $ Operation BinaryExpr + x * y; // $ Operation BinaryExpr + x / y; // $ Operation BinaryExpr + x % y; // $ Operation BinaryExpr + x += y; // $ Operation AssignmentOperation BinaryExpr + x -= y; // $ Operation AssignmentOperation BinaryExpr + x *= y; // $ Operation AssignmentOperation BinaryExpr + x /= y; // $ Operation AssignmentOperation BinaryExpr + x %= y; // $ Operation AssignmentOperation BinaryExpr + -x; // $ Operation PrefixExpr // logical operations - a && b; // $ BinaryExpr LogicalOperation - a || b; // $ BinaryExpr LogicalOperation - !a; // $ PrefixExpr LogicalOperation + a && b; // $ Operation BinaryExpr LogicalOperation + a || b; // $ Operation BinaryExpr LogicalOperation + !a; // $ Operation PrefixExpr LogicalOperation // bitwise operations - x & y; // $ BinaryExpr - x | y; // $ BinaryExpr - x ^ y; // $ BinaryExpr - x << y; // $ BinaryExpr - x >> y; // $ BinaryExpr - x &= y; // $ AssignmentOperation BinaryExpr - x |= y; // $ AssignmentOperation BinaryExpr - x ^= y; // $ AssignmentOperation BinaryExpr - x <<= y; // $ AssignmentOperation BinaryExpr - x >>= y; // $ AssignmentOperation BinaryExpr + x & y; // $ Operation BinaryExpr + x | y; // $ Operation BinaryExpr + x ^ y; // $ Operation BinaryExpr + x << y; // $ Operation BinaryExpr + x >> y; // $ Operation BinaryExpr + x &= y; // $ Operation AssignmentOperation BinaryExpr + x |= y; // $ Operation AssignmentOperation BinaryExpr + x ^= y; // $ Operation AssignmentOperation BinaryExpr + x <<= y; // $ Operation AssignmentOperation BinaryExpr + x >>= y; // $ Operation AssignmentOperation BinaryExpr // miscellaneous expressions that might be operations - *ptr; // $ PrefixExpr + *ptr; // $ Operation PrefixExpr &x; // $ RefExpr res?; From be2017621fce954873af3fd47c8eba1a5531bc94 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 May 2025 12:36:31 +0100 Subject: [PATCH 04/10] Rust: Unify getAnOperand() methods into Operation. --- .../codeql/rust/elements/LogicalOperation.qll | 4 -- .../ql/lib/codeql/rust/elements/Operation.qll | 9 ++- .../rust/elements/internal/BinaryExprImpl.qll | 2 + .../rust/elements/internal/PrefixExprImpl.qll | 2 + .../library-tests/operations/Operations.ql | 12 +++- rust/ql/test/library-tests/operations/test.rs | 64 +++++++++---------- 6 files changed, 52 insertions(+), 41 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll index 7638bea15fdb..40a3c4a4e261 100644 --- a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll @@ -7,7 +7,6 @@ private import codeql.rust.elements.Operation * A logical operation, such as `&&`, `||` or `!`. */ abstract private class LogicalOperationImpl extends Operation { - abstract Expr getAnOperand(); } final class LogicalOperation = LogicalOperationImpl; @@ -16,7 +15,6 @@ final class LogicalOperation = LogicalOperationImpl; * A binary logical operation, such as `&&` or `||`. */ abstract private class BinaryLogicalOperationImpl extends BinaryExpr, LogicalOperationImpl { - override Expr getAnOperand() { result = [this.getLhs(), this.getRhs()] } } final class BinaryLogicalOperation = BinaryLogicalOperationImpl; @@ -47,6 +45,4 @@ final class UnaryLogicalOperation = UnaryLogicalOperationImpl; */ final class LogicalNotExpr extends UnaryLogicalOperationImpl { LogicalNotExpr() { this.getOperatorName() = "!" } - - override Expr getAnOperand() { result = this.getExpr() } } diff --git a/rust/ql/lib/codeql/rust/elements/Operation.qll b/rust/ql/lib/codeql/rust/elements/Operation.qll index a1915f837fdd..6564e9127435 100644 --- a/rust/ql/lib/codeql/rust/elements/Operation.qll +++ b/rust/ql/lib/codeql/rust/elements/Operation.qll @@ -10,10 +10,15 @@ private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl * be referenced directly. */ module OperationImpl { + /** + * An operation, for example `&&`, `+=`, `!` or `*`. + */ + abstract class Operation extends ExprImpl::Expr { /** - * An operation, for example `&&`, `+=`, `!` or `*`. + * Gets an operand of this operation. */ - abstract class Operation extends ExprImpl::Expr { } + abstract Expr getAnOperand(); + } } final class Operation = OperationImpl::Operation; diff --git a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll index bb7106cf6e98..7793fc5808cb 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll @@ -25,5 +25,7 @@ module Impl { */ class BinaryExpr extends Generated::BinaryExpr, OperationImpl::Operation { override string toStringImpl() { result = "... " + this.getOperatorName() + " ..." } + + override Expr getAnOperand() { result = [this.getLhs(), this.getRhs()] } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll index 2008be60660c..782f0addf640 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll @@ -23,5 +23,7 @@ module Impl { */ class PrefixExpr extends Generated::PrefixExpr, OperationImpl::Operation { override string toStringImpl() { result = this.getOperatorName() + " ..." } + + override Expr getAnOperand() { result = this.getExpr() } } } diff --git a/rust/ql/test/library-tests/operations/Operations.ql b/rust/ql/test/library-tests/operations/Operations.ql index 1609d4b5d22f..5829b5b360f4 100644 --- a/rust/ql/test/library-tests/operations/Operations.ql +++ b/rust/ql/test/library-tests/operations/Operations.ql @@ -16,15 +16,21 @@ string describe(Expr op) { } module OperationsTest implements TestSig { - string getARelevantTag() { result = describe(_) } + string getARelevantTag() { result = describe(_) or result = "Operands" } predicate hasActualResult(Location location, string element, string tag, string value) { exists(Expr op | location = op.getLocation() and location.getFile().getBaseName() != "" and element = op.toString() and - tag = describe(op) and - value = "" + ( + tag = describe(op) and + value = "" + or + op instanceof Operation and + tag = "Operands" and + value = count(op.(Operation).getAnOperand()).toString() + ) ) } } diff --git a/rust/ql/test/library-tests/operations/test.rs b/rust/ql/test/library-tests/operations/test.rs index 7ec3d8a3eef1..1e8da17c2e4e 100644 --- a/rust/ql/test/library-tests/operations/test.rs +++ b/rust/ql/test/library-tests/operations/test.rs @@ -8,48 +8,48 @@ fn test_operations( let mut x: i32; // simple assignment - x = y; // $ Operation AssignmentOperation BinaryExpr + x = y; // $ Operation Operands=2 AssignmentOperation BinaryExpr // comparison operations - x == y; // $ Operation BinaryExpr - x != y; // $ Operation BinaryExpr - x < y; // $ Operation BinaryExpr - x <= y; // $ Operation BinaryExpr - x > y; // $ Operation BinaryExpr - x >= y; // $ Operation BinaryExpr + x == y; // $ Operation Operands=2 BinaryExpr + x != y; // $ Operation Operands=2 BinaryExpr + x < y; // $ Operation Operands=2 BinaryExpr + x <= y; // $ Operation Operands=2 BinaryExpr + x > y; // $ Operation Operands=2 BinaryExpr + x >= y; // $ Operation Operands=2 BinaryExpr // arithmetic operations - x + y; // $ Operation BinaryExpr - x - y; // $ Operation BinaryExpr - x * y; // $ Operation BinaryExpr - x / y; // $ Operation BinaryExpr - x % y; // $ Operation BinaryExpr - x += y; // $ Operation AssignmentOperation BinaryExpr - x -= y; // $ Operation AssignmentOperation BinaryExpr - x *= y; // $ Operation AssignmentOperation BinaryExpr - x /= y; // $ Operation AssignmentOperation BinaryExpr - x %= y; // $ Operation AssignmentOperation BinaryExpr - -x; // $ Operation PrefixExpr + x + y; // $ Operation Operands=2 BinaryExpr + x - y; // $ Operation Operands=2 BinaryExpr + x * y; // $ Operation Operands=2 BinaryExpr + x / y; // $ Operation Operands=2 BinaryExpr + x % y; // $ Operation Operands=2 BinaryExpr + x += y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x -= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x *= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x /= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x %= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + -x; // $ Operation Operands=1 PrefixExpr // logical operations - a && b; // $ Operation BinaryExpr LogicalOperation - a || b; // $ Operation BinaryExpr LogicalOperation - !a; // $ Operation PrefixExpr LogicalOperation + a && b; // $ Operation Operands=2 BinaryExpr LogicalOperation + a || b; // $ Operation Operands=2 BinaryExpr LogicalOperation + !a; // $ Operation Operands=1 PrefixExpr LogicalOperation // bitwise operations - x & y; // $ Operation BinaryExpr - x | y; // $ Operation BinaryExpr - x ^ y; // $ Operation BinaryExpr - x << y; // $ Operation BinaryExpr - x >> y; // $ Operation BinaryExpr - x &= y; // $ Operation AssignmentOperation BinaryExpr - x |= y; // $ Operation AssignmentOperation BinaryExpr - x ^= y; // $ Operation AssignmentOperation BinaryExpr - x <<= y; // $ Operation AssignmentOperation BinaryExpr - x >>= y; // $ Operation AssignmentOperation BinaryExpr + x & y; // $ Operation Operands=2 BinaryExpr + x | y; // $ Operation Operands=2 BinaryExpr + x ^ y; // $ Operation Operands=2 BinaryExpr + x << y; // $ Operation Operands=2 BinaryExpr + x >> y; // $ Operation Operands=2 BinaryExpr + x &= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x |= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x ^= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x <<= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x >>= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr // miscellaneous expressions that might be operations - *ptr; // $ Operation PrefixExpr + *ptr; // $ Operation Operands=1 PrefixExpr &x; // $ RefExpr res?; From dc1b4fcf7aa2c603e9412e9a1ea98b444c53574f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 May 2025 12:50:47 +0100 Subject: [PATCH 05/10] Rust: Unify getOperatorName() methods into Operation. --- .../ql/lib/codeql/rust/elements/Operation.qll | 5 ++ .../rust/elements/internal/BinaryExprImpl.qll | 2 + .../rust/elements/internal/PrefixExprImpl.qll | 2 + .../library-tests/operations/Operations.ql | 5 +- rust/ql/test/library-tests/operations/test.rs | 64 +++++++++---------- 5 files changed, 45 insertions(+), 33 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/Operation.qll b/rust/ql/lib/codeql/rust/elements/Operation.qll index 6564e9127435..26486686cb20 100644 --- a/rust/ql/lib/codeql/rust/elements/Operation.qll +++ b/rust/ql/lib/codeql/rust/elements/Operation.qll @@ -14,6 +14,11 @@ module OperationImpl { * An operation, for example `&&`, `+=`, `!` or `*`. */ abstract class Operation extends ExprImpl::Expr { + /** + * Gets the operator name of this operation, if it exists. + */ + abstract string getOperatorName(); + /** * Gets an operand of this operation. */ diff --git a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll index 7793fc5808cb..42ac0521db3c 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll @@ -26,6 +26,8 @@ module Impl { class BinaryExpr extends Generated::BinaryExpr, OperationImpl::Operation { override string toStringImpl() { result = "... " + this.getOperatorName() + " ..." } + override string getOperatorName() { result = Generated::BinaryExpr.super.getOperatorName() } + override Expr getAnOperand() { result = [this.getLhs(), this.getRhs()] } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll index 782f0addf640..56cc43babd0c 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll @@ -24,6 +24,8 @@ module Impl { class PrefixExpr extends Generated::PrefixExpr, OperationImpl::Operation { override string toStringImpl() { result = this.getOperatorName() + " ..." } + override string getOperatorName() { result = Generated::PrefixExpr.super.getOperatorName() } + override Expr getAnOperand() { result = this.getExpr() } } } diff --git a/rust/ql/test/library-tests/operations/Operations.ql b/rust/ql/test/library-tests/operations/Operations.ql index 5829b5b360f4..cbb81bdcb025 100644 --- a/rust/ql/test/library-tests/operations/Operations.ql +++ b/rust/ql/test/library-tests/operations/Operations.ql @@ -16,7 +16,7 @@ string describe(Expr op) { } module OperationsTest implements TestSig { - string getARelevantTag() { result = describe(_) or result = "Operands" } + string getARelevantTag() { result = describe(_) or result = ["Op", "Operands"] } predicate hasActualResult(Location location, string element, string tag, string value) { exists(Expr op | @@ -27,6 +27,9 @@ module OperationsTest implements TestSig { tag = describe(op) and value = "" or + tag = "Op" and + value = op.(Operation).getOperatorName() + or op instanceof Operation and tag = "Operands" and value = count(op.(Operation).getAnOperand()).toString() diff --git a/rust/ql/test/library-tests/operations/test.rs b/rust/ql/test/library-tests/operations/test.rs index 1e8da17c2e4e..f82a9501fef4 100644 --- a/rust/ql/test/library-tests/operations/test.rs +++ b/rust/ql/test/library-tests/operations/test.rs @@ -8,48 +8,48 @@ fn test_operations( let mut x: i32; // simple assignment - x = y; // $ Operation Operands=2 AssignmentOperation BinaryExpr + x = y; // $ Operation Op== Operands=2 AssignmentOperation BinaryExpr // comparison operations - x == y; // $ Operation Operands=2 BinaryExpr - x != y; // $ Operation Operands=2 BinaryExpr - x < y; // $ Operation Operands=2 BinaryExpr - x <= y; // $ Operation Operands=2 BinaryExpr - x > y; // $ Operation Operands=2 BinaryExpr - x >= y; // $ Operation 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 // arithmetic operations - x + y; // $ Operation Operands=2 BinaryExpr - x - y; // $ Operation Operands=2 BinaryExpr - x * y; // $ Operation Operands=2 BinaryExpr - x / y; // $ Operation Operands=2 BinaryExpr - x % y; // $ Operation Operands=2 BinaryExpr - x += y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x -= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x *= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x /= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x %= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - -x; // $ Operation Operands=1 PrefixExpr + 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 AssignmentOperation BinaryExpr + x -= y; // $ Operation Op=-= Operands=2 AssignmentOperation BinaryExpr + x *= y; // $ Operation Op=*= Operands=2 AssignmentOperation BinaryExpr + x /= y; // $ Operation Op=/= Operands=2 AssignmentOperation BinaryExpr + x %= y; // $ Operation Op=%= Operands=2 AssignmentOperation BinaryExpr + -x; // $ Operation Op=- Operands=1 PrefixExpr // logical operations - a && b; // $ Operation Operands=2 BinaryExpr LogicalOperation - a || b; // $ Operation Operands=2 BinaryExpr LogicalOperation - !a; // $ Operation Operands=1 PrefixExpr LogicalOperation + a && b; // $ Operation Op=&& Operands=2 BinaryExpr LogicalOperation + a || b; // $ Operation Op=|| Operands=2 BinaryExpr LogicalOperation + !a; // $ Operation Op=! Operands=1 PrefixExpr LogicalOperation // bitwise operations - x & y; // $ Operation Operands=2 BinaryExpr - x | y; // $ Operation Operands=2 BinaryExpr - x ^ y; // $ Operation Operands=2 BinaryExpr - x << y; // $ Operation Operands=2 BinaryExpr - x >> y; // $ Operation Operands=2 BinaryExpr - x &= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x |= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x ^= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x <<= y; // $ Operation Operands=2 AssignmentOperation BinaryExpr - x >>= y; // $ Operation Operands=2 AssignmentOperation 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 AssignmentOperation BinaryExpr + x |= y; // $ Operation Op=|= Operands=2 AssignmentOperation BinaryExpr + x ^= y; // $ Operation Op=^= Operands=2 AssignmentOperation BinaryExpr + x <<= y; // $ Operation Op=<<= Operands=2 AssignmentOperation BinaryExpr + x >>= y; // $ Operation Op=>>= Operands=2 AssignmentOperation BinaryExpr // miscellaneous expressions that might be operations - *ptr; // $ Operation Operands=1 PrefixExpr + *ptr; // $ Operation Op=* Operands=1 PrefixExpr &x; // $ RefExpr res?; From 09dc7fc5c4a012cecebc090135c6ede65c89bd4d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 2 May 2025 16:58:43 +0100 Subject: [PATCH 06/10] Rust: Autoformat. --- rust/ql/lib/codeql/rust/elements/LogicalOperation.qll | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll index 40a3c4a4e261..72cc4ffdf57e 100644 --- a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll @@ -6,16 +6,14 @@ private import codeql.rust.elements.Operation /** * A logical operation, such as `&&`, `||` or `!`. */ -abstract private class LogicalOperationImpl extends Operation { -} +abstract private class LogicalOperationImpl extends Operation { } final class LogicalOperation = LogicalOperationImpl; /** * A binary logical operation, such as `&&` or `||`. */ -abstract private class BinaryLogicalOperationImpl extends BinaryExpr, LogicalOperationImpl { -} +abstract private class BinaryLogicalOperationImpl extends BinaryExpr, LogicalOperationImpl { } final class BinaryLogicalOperation = BinaryLogicalOperationImpl; From 48b95f3a4e2288bbd8bb07b241a80b715ed35463 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 9 May 2025 17:01:26 +0100 Subject: [PATCH 07/10] Rust: Move OperationImpl to internal/OperationImpl.qll. --- .../ql/lib/codeql/rust/elements/Operation.qll | 23 +-------------- .../rust/elements/internal/OperationImpl.qll | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 22 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll diff --git a/rust/ql/lib/codeql/rust/elements/Operation.qll b/rust/ql/lib/codeql/rust/elements/Operation.qll index 26486686cb20..b3615bddb33e 100644 --- a/rust/ql/lib/codeql/rust/elements/Operation.qll +++ b/rust/ql/lib/codeql/rust/elements/Operation.qll @@ -2,28 +2,7 @@ * Provides classes for operations. */ -private import rust +import internal.OperationImpl private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl -/** - * INTERNAL: This module contains the customizable definition of `Operation` and should not - * be referenced directly. - */ -module OperationImpl { - /** - * An operation, for example `&&`, `+=`, `!` or `*`. - */ - abstract class Operation extends ExprImpl::Expr { - /** - * Gets the operator name of this operation, if it exists. - */ - abstract string getOperatorName(); - - /** - * Gets an operand of this operation. - */ - abstract Expr getAnOperand(); - } -} - final class Operation = OperationImpl::Operation; diff --git a/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll new file mode 100644 index 000000000000..7b2d1a9d62e2 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll @@ -0,0 +1,29 @@ +/** + * Provides classes for operations. + * + * INTERNAL: Do not use. + */ + +private import rust +private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl + +/** + * INTERNAL: This module contains the customizable definition of `Operation` and should not + * be referenced directly. + */ +module OperationImpl { + /** + * An operation, for example `&&`, `+=`, `!` or `*`. + */ + abstract class Operation extends ExprImpl::Expr { + /** + * Gets the operator name of this operation, if it exists. + */ + abstract string getOperatorName(); + + /** + * Gets an operand of this operation. + */ + abstract Expr getAnOperand(); + } +} From 9160036e416a82158d88e5ae10bbd04077965efd Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 16:45:41 +0100 Subject: [PATCH 08/10] Rust: Rename OperationImpl -> Impl. --- rust/ql/lib/codeql/rust/elements/Operation.qll | 2 +- rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/Operation.qll b/rust/ql/lib/codeql/rust/elements/Operation.qll index b3615bddb33e..dad24e980eda 100644 --- a/rust/ql/lib/codeql/rust/elements/Operation.qll +++ b/rust/ql/lib/codeql/rust/elements/Operation.qll @@ -2,7 +2,7 @@ * Provides classes for operations. */ -import internal.OperationImpl +import internal.OperationImpl::Impl as OperationImpl private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl final class Operation = OperationImpl::Operation; diff --git a/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll index 7b2d1a9d62e2..deffd72086d6 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll @@ -11,7 +11,7 @@ private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl * INTERNAL: This module contains the customizable definition of `Operation` and should not * be referenced directly. */ -module OperationImpl { +module Impl { /** * An operation, for example `&&`, `+=`, `!` or `*`. */ From a2944cdb61c6af07b7ccd57745c6211648b08d10 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 12 May 2025 16:48:06 +0100 Subject: [PATCH 09/10] Rust: Make usage of Impl more consistent with other Impl modules. --- rust/ql/lib/codeql/rust/elements/Operation.qll | 4 ++-- rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll | 2 +- rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/Operation.qll b/rust/ql/lib/codeql/rust/elements/Operation.qll index dad24e980eda..035e4ce81f2b 100644 --- a/rust/ql/lib/codeql/rust/elements/Operation.qll +++ b/rust/ql/lib/codeql/rust/elements/Operation.qll @@ -2,7 +2,7 @@ * Provides classes for operations. */ -import internal.OperationImpl::Impl as OperationImpl +private import internal.OperationImpl private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl -final class Operation = OperationImpl::Operation; +final class Operation = Impl::Operation; diff --git a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll index 42ac0521db3c..966d64936377 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/BinaryExprImpl.qll @@ -5,7 +5,7 @@ */ private import codeql.rust.elements.internal.generated.BinaryExpr -private import codeql.rust.elements.Operation::OperationImpl as OperationImpl +private import codeql.rust.elements.internal.OperationImpl::Impl as OperationImpl /** * INTERNAL: This module contains the customizable definition of `BinaryExpr` and should not diff --git a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll index 56cc43babd0c..75e2969fabc5 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PrefixExprImpl.qll @@ -5,7 +5,7 @@ */ private import codeql.rust.elements.internal.generated.PrefixExpr -private import codeql.rust.elements.Operation::OperationImpl as OperationImpl +private import codeql.rust.elements.internal.OperationImpl::Impl as OperationImpl /** * INTERNAL: This module contains the customizable definition of `PrefixExpr` and should not From b3dc7a21b38f3fc408492329c652e7b502feeb98 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 13 May 2025 09:06:25 +0100 Subject: [PATCH 10/10] Apply suggestions from code review Co-authored-by: Simon Friis Vindum --- rust/ql/lib/codeql/rust/elements/LogicalOperation.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll index 72cc4ffdf57e..eaf1ff06b7d5 100644 --- a/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll +++ b/rust/ql/lib/codeql/rust/elements/LogicalOperation.qll @@ -18,14 +18,14 @@ abstract private class BinaryLogicalOperationImpl extends BinaryExpr, LogicalOpe final class BinaryLogicalOperation = BinaryLogicalOperationImpl; /** - * The logical and operation, `&&`. + * The logical "and" operation, `&&`. */ final class LogicalAndExpr extends BinaryLogicalOperationImpl, BinaryExpr { LogicalAndExpr() { this.getOperatorName() = "&&" } } /** - * The logical or operation, `||`. + * The logical "or" operation, `||`. */ final class LogicalOrExpr extends BinaryLogicalOperationImpl { LogicalOrExpr() { this.getOperatorName() = "||" } @@ -39,7 +39,7 @@ abstract private class UnaryLogicalOperationImpl extends PrefixExpr, LogicalOper final class UnaryLogicalOperation = UnaryLogicalOperationImpl; /** - * A logical not operation, `!`. + * A logical "not" operation, `!`. */ final class LogicalNotExpr extends UnaryLogicalOperationImpl { LogicalNotExpr() { this.getOperatorName() = "!" }