Merge pull request #19562 from geoffw0/operations3

Rust: Add more Operation subclasses
This commit is contained in:
Geoffrey White
2025-05-27 09:26:35 +01:00
committed by GitHub
10 changed files with 131 additions and 32 deletions

View File

@@ -0,0 +1,38 @@
/**
* Provides classes for arithmetic operations.
*/
private import codeql.rust.elements.BinaryExpr
private import codeql.rust.elements.PrefixExpr
private import codeql.rust.elements.Operation
private import codeql.rust.elements.AssignmentOperation
/**
* An arithmetic operation, such as `+`, `*=`, or `-`.
*/
abstract private class ArithmeticOperationImpl extends Operation { }
final class ArithmeticOperation = ArithmeticOperationImpl;
/**
* A binary arithmetic operation, such as `+` or `*`.
*/
final class BinaryArithmeticOperation extends BinaryExpr, ArithmeticOperationImpl {
BinaryArithmeticOperation() { this.getOperatorName() = ["+", "-", "*", "/", "%"] }
}
/**
* An arithmetic assignment operation, such as `+=` or `*=`.
*/
final class AssignArithmeticOperation extends BinaryExpr, ArithmeticOperationImpl,
AssignmentOperation
{
AssignArithmeticOperation() { this.getOperatorName() = ["+=", "-=", "*=", "/=", "%="] }
}
/**
* A prefix arithmetic operation, such as `-`.
*/
final class PrefixArithmeticOperation extends PrefixExpr, ArithmeticOperationImpl {
PrefixArithmeticOperation() { this.getOperatorName() = "-" }
}

View File

@@ -0,0 +1,28 @@
/**
* Provides classes for bitwise operations.
*/
private import codeql.rust.elements.BinaryExpr
private import codeql.rust.elements.Operation
private import codeql.rust.elements.AssignmentOperation
/**
* A bitwise operation, such as `&`, `<<`, or `|=`.
*/
abstract private class BitwiseOperationImpl extends Operation { }
final class BitwiseOperation = BitwiseOperationImpl;
/**
* A binary bitwise operation, such as `&` or `<<`.
*/
final class BinaryBitwiseOperation extends BinaryExpr, BitwiseOperationImpl {
BinaryBitwiseOperation() { this.getOperatorName() = ["&", "|", "^", "<<", ">>"] }
}
/**
* A bitwise assignment operation, such as `|=` or `<<=`.
*/
final class AssignBitwiseOperation extends BinaryExpr, BitwiseOperationImpl, AssignmentOperation {
AssignBitwiseOperation() { this.getOperatorName() = ["&=", "|=", "^=", "<<=", ">>="] }
}

View File

@@ -0,0 +1,13 @@
/**
* Provides classes for deref expressions (`*`).
*/
private import codeql.rust.elements.PrefixExpr
private import codeql.rust.elements.Operation
/**
* A dereference expression, the prefix operator `*`.
*/
final class DerefExpr extends PrefixExpr, Operation {
DerefExpr() { this.getOperatorName() = "*" }
}

View File

@@ -5,6 +5,7 @@
*/
private import codeql.rust.elements.internal.generated.RefExpr
private import codeql.rust.elements.internal.OperationImpl::Impl as OperationImpl
/**
* INTERNAL: This module contains the customizable definition of `RefExpr` and should not
@@ -21,11 +22,15 @@ module Impl {
* let raw_mut: &mut i32 = &raw mut foo;
* ```
*/
class RefExpr extends Generated::RefExpr {
class RefExpr extends Generated::RefExpr, OperationImpl::Operation {
override string toStringImpl() {
result = "&" + concat(int i | | this.getSpecPart(i), " " order by i)
}
override string getOperatorName() { result = "&" }
override Expr getAnOperand() { result = this.getExpr() }
private string getSpecPart(int index) {
index = 0 and this.isRaw() and result = "raw"
or

View File

@@ -610,7 +610,7 @@ module Impl {
exists(Expr mid |
assignmentExprDescendant(mid) and
getImmediateParent(e) = mid and
not mid.(PrefixExpr).getOperatorName() = "*" and
not mid instanceof DerefExpr and
not mid instanceof FieldExpr and
not mid instanceof IndexExpr
)

View File

@@ -259,8 +259,7 @@ private predicate typeEqualityLeft(AstNode n1, TypePath path1, AstNode n2, TypeP
typeEquality(n1, path1, n2, path2)
or
n2 =
any(PrefixExpr pe |
pe.getOperatorName() = "*" and
any(DerefExpr pe |
pe.getExpr() = n1 and
path1.isCons(TRefTypeParameter(), path2)
)
@@ -271,8 +270,7 @@ private predicate typeEqualityRight(AstNode n1, TypePath path1, AstNode n2, Type
typeEquality(n1, path1, n2, path2)
or
n2 =
any(PrefixExpr pe |
pe.getOperatorName() = "*" and
any(DerefExpr pe |
pe.getExpr() = n1 and
path1 = TypePath::cons(TRefTypeParameter(), path2)
)

View File

@@ -50,9 +50,7 @@ module AccessInvalidPointer {
* A pointer access using the unary `*` operator.
*/
private class DereferenceSink extends Sink {
DereferenceSink() {
exists(PrefixExpr p | p.getOperatorName() = "*" and p.getExpr() = this.asExpr().getExpr())
}
DereferenceSink() { any(DerefExpr p).getExpr() = this.asExpr().getExpr() }
}
/**

View File

@@ -4,8 +4,11 @@ import codeql.rust.elements
import codeql.Locations
import codeql.files.FileSystem
import codeql.rust.elements.Operation
import codeql.rust.elements.ArithmeticOperation
import codeql.rust.elements.AssignmentOperation
import codeql.rust.elements.BitwiseOperation
import codeql.rust.elements.ComparisonOperation
import codeql.rust.elements.DerefExpr
import codeql.rust.elements.LiteralExprExt
import codeql.rust.elements.LogicalOperation
import codeql.rust.elements.AsyncBlockExpr

View File

@@ -32,6 +32,22 @@ string describe(Expr op) {
op instanceof LessOrEqualsOperation and result = "LessOrEqualsOperation"
or
op instanceof GreaterOrEqualsOperation and result = "GreaterOrEqualsOperation"
or
op instanceof ArithmeticOperation and result = "ArithmeticOperation"
or
op instanceof BinaryArithmeticOperation and result = "BinaryArithmeticOperation"
or
op instanceof AssignArithmeticOperation and result = "AssignArithmeticOperation"
or
op instanceof PrefixArithmeticOperation and result = "PrefixArithmeticOperation"
or
op instanceof BitwiseOperation and result = "BitwiseOperation"
or
op instanceof BinaryBitwiseOperation and result = "BinaryBitwiseOperation"
or
op instanceof AssignBitwiseOperation and result = "AssignBitwiseOperation"
or
op instanceof DerefExpr and result = "DerefExpr"
}
module OperationsTest implements TestSig {

View File

@@ -19,17 +19,17 @@ fn test_operations(
x >= y; // $ Operation Op=>= Operands=2 BinaryExpr ComparisonOperation RelationalOperation GreaterOrEqualsOperation Greater=x Lesser=y
// arithmetic 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 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
x + y; // $ Operation Op=+ Operands=2 BinaryExpr ArithmeticOperation BinaryArithmeticOperation
x - y; // $ Operation Op=- Operands=2 BinaryExpr ArithmeticOperation BinaryArithmeticOperation
x * y; // $ Operation Op=* Operands=2 BinaryExpr ArithmeticOperation BinaryArithmeticOperation
x / y; // $ Operation Op=/ Operands=2 BinaryExpr ArithmeticOperation BinaryArithmeticOperation
x % y; // $ Operation Op=% Operands=2 BinaryExpr ArithmeticOperation BinaryArithmeticOperation
x += y; // $ Operation Op=+= Operands=2 AssignmentOperation BinaryExpr ArithmeticOperation AssignArithmeticOperation
x -= y; // $ Operation Op=-= Operands=2 AssignmentOperation BinaryExpr ArithmeticOperation AssignArithmeticOperation
x *= y; // $ Operation Op=*= Operands=2 AssignmentOperation BinaryExpr ArithmeticOperation AssignArithmeticOperation
x /= y; // $ Operation Op=/= Operands=2 AssignmentOperation BinaryExpr ArithmeticOperation AssignArithmeticOperation
x %= y; // $ Operation Op=%= Operands=2 AssignmentOperation BinaryExpr ArithmeticOperation AssignArithmeticOperation
-x; // $ Operation Op=- Operands=1 PrefixExpr ArithmeticOperation PrefixArithmeticOperation
// logical operations
a && b; // $ Operation Op=&& Operands=2 BinaryExpr LogicalOperation
@@ -37,20 +37,20 @@ fn test_operations(
!a; // $ Operation Op=! Operands=1 PrefixExpr LogicalOperation
// bitwise 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 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 & y; // $ Operation Op=& Operands=2 BinaryExpr BitwiseOperation BinaryBitwiseOperation
x | y; // $ Operation Op=| Operands=2 BinaryExpr BitwiseOperation BinaryBitwiseOperation
x ^ y; // $ Operation Op=^ Operands=2 BinaryExpr BitwiseOperation BinaryBitwiseOperation
x << y; // $ Operation Op=<< Operands=2 BinaryExpr BitwiseOperation BinaryBitwiseOperation
x >> y; // $ Operation Op=>> Operands=2 BinaryExpr BitwiseOperation BinaryBitwiseOperation
x &= y; // $ Operation Op=&= Operands=2 AssignmentOperation BinaryExpr BitwiseOperation AssignBitwiseOperation
x |= y; // $ Operation Op=|= Operands=2 AssignmentOperation BinaryExpr BitwiseOperation AssignBitwiseOperation
x ^= y; // $ Operation Op=^= Operands=2 AssignmentOperation BinaryExpr BitwiseOperation AssignBitwiseOperation
x <<= y; // $ Operation Op=<<= Operands=2 AssignmentOperation BinaryExpr BitwiseOperation AssignBitwiseOperation
x >>= y; // $ Operation Op=>>= Operands=2 AssignmentOperation BinaryExpr BitwiseOperation AssignBitwiseOperation
// miscellaneous expressions that might be operations
*ptr; // $ Operation Op=* Operands=1 PrefixExpr
&x; // $ RefExpr
*ptr; // $ Operation Op=* Operands=1 PrefixExpr DerefExpr
&x; // $ Operation Op=& Operands=1 RefExpr MISSING: PrefixExpr
res?;
return Ok(());