C#: Introduce Expr.getIntValue.

This commit is contained in:
Anders Schack-Mulligen
2026-04-13 14:52:38 +02:00
parent 6078df524b
commit d3e580fd0e
12 changed files with 38 additions and 40 deletions

View File

@@ -9,5 +9,5 @@
import csharp import csharp
from IntegerLiteral literal from IntegerLiteral literal
where literal.getValue().toInt() = 0 where literal.getIntValue() = 0
select literal select literal

View File

@@ -713,7 +713,7 @@ private class SignedIntegralConstantExpr extends Expr {
} }
private predicate convConstantIntExpr(SignedIntegralConstantExpr e, SimpleType toType) { private predicate convConstantIntExpr(SignedIntegralConstantExpr e, SimpleType toType) {
exists(int n | n = e.getValue().toInt() | exists(int n | n = e.getIntValue() |
toType = any(SByteType t | n in [t.minValue() .. t.maxValue()]) toType = any(SByteType t | n in [t.minValue() .. t.maxValue()])
or or
toType = any(ByteType t | n in [t.minValue() .. t.maxValue()]) toType = any(ByteType t | n in [t.minValue() .. t.maxValue()])
@@ -730,7 +730,7 @@ private predicate convConstantIntExpr(SignedIntegralConstantExpr e, SimpleType t
private predicate convConstantLongExpr(SignedIntegralConstantExpr e) { private predicate convConstantLongExpr(SignedIntegralConstantExpr e) {
e.getType() instanceof LongType and e.getType() instanceof LongType and
e.getValue().toInt() >= 0 e.getIntValue() >= 0
} }
/** 6.1.10: Implicit reference conversions involving type parameters. */ /** 6.1.10: Implicit reference conversions involving type parameters. */

View File

@@ -161,7 +161,7 @@ private newtype TComparisonTest =
compare.getComparisonKind().isCompare() and compare.getComparisonKind().isCompare() and
outerKind = outer.getComparisonKind() and outerKind = outer.getComparisonKind() and
outer.getAnArgument() = compare.getExpr() and outer.getAnArgument() = compare.getExpr() and
i = outer.getAnArgument().getValue().toInt() i = outer.getAnArgument().getIntValue()
| |
outerKind.isEquality() and outerKind.isEquality() and
( (

View File

@@ -32,13 +32,13 @@ private module ConstantComparisonOperation {
private int maxValue(Expr expr) { private int maxValue(Expr expr) {
if convertedType(expr) instanceof IntegralType and exists(expr.getValue()) if convertedType(expr) instanceof IntegralType and exists(expr.getValue())
then result = expr.getValue().toInt() then result = expr.getIntValue()
else result = convertedType(expr).maxValue() else result = convertedType(expr).maxValue()
} }
private int minValue(Expr expr) { private int minValue(Expr expr) {
if convertedType(expr) instanceof IntegralType and exists(expr.getValue()) if convertedType(expr) instanceof IntegralType and exists(expr.getValue())
then result = expr.getValue().toInt() then result = expr.getIntValue()
else result = convertedType(expr).minValue() else result = convertedType(expr).minValue()
} }

View File

@@ -60,25 +60,16 @@ private module GuardsInput implements
override boolean asBooleanValue() { boolConst(this, result) } override boolean asBooleanValue() { boolConst(this, result) }
} }
private predicate intConst(Expr e, int i) {
e.getValue().toInt() = i and
(
e.getType() instanceof Enum
or
e.getType() instanceof IntegralType
)
}
private class IntegerConstant extends ConstantExpr { private class IntegerConstant extends ConstantExpr {
IntegerConstant() { intConst(this, _) } IntegerConstant() { exists(this.getIntValue()) }
override int asIntegerValue() { intConst(this, result) } override int asIntegerValue() { result = this.getIntValue() }
} }
private class EnumConst extends ConstantExpr { private class EnumConst extends ConstantExpr {
EnumConst() { this.getType() instanceof Enum and this.hasValue() } EnumConst() { this.getType() instanceof Enum and this.hasValue() }
override int asIntegerValue() { result = this.getValue().toInt() } override int asIntegerValue() { result = this.getIntValue() }
} }
private class StringConstant extends ConstantExpr instanceof StringLiteral { private class StringConstant extends ConstantExpr instanceof StringLiteral {
@@ -517,35 +508,35 @@ class EnumerableCollectionExpr extends Expr {
| |
// x.Length == 0 // x.Length == 0
ct.getComparisonKind().isEquality() and ct.getComparisonKind().isEquality() and
ct.getAnArgument().getValue().toInt() = 0 and ct.getAnArgument().getIntValue() = 0 and
branch = isEmpty branch = isEmpty
or or
// x.Length == k, k > 0 // x.Length == k, k > 0
ct.getComparisonKind().isEquality() and ct.getComparisonKind().isEquality() and
ct.getAnArgument().getValue().toInt() > 0 and ct.getAnArgument().getIntValue() > 0 and
branch = true and branch = true and
isEmpty = false isEmpty = false
or or
// x.Length != 0 // x.Length != 0
ct.getComparisonKind().isInequality() and ct.getComparisonKind().isInequality() and
ct.getAnArgument().getValue().toInt() = 0 and ct.getAnArgument().getIntValue() = 0 and
branch = isEmpty.booleanNot() branch = isEmpty.booleanNot()
or or
// x.Length != k, k != 0 // x.Length != k, k != 0
ct.getComparisonKind().isInequality() and ct.getComparisonKind().isInequality() and
ct.getAnArgument().getValue().toInt() != 0 and ct.getAnArgument().getIntValue() != 0 and
branch = false and branch = false and
isEmpty = false isEmpty = false
or or
// x.Length > k, k >= 0 // x.Length > k, k >= 0
ct.getComparisonKind().isLessThan() and ct.getComparisonKind().isLessThan() and
ct.getFirstArgument().getValue().toInt() >= 0 and ct.getFirstArgument().getIntValue() >= 0 and
branch = true and branch = true and
isEmpty = false isEmpty = false
or or
// x.Length >= k, k > 0 // x.Length >= k, k > 0
ct.getComparisonKind().isLessThanEquals() and ct.getComparisonKind().isLessThanEquals() and
ct.getFirstArgument().getValue().toInt() > 0 and ct.getFirstArgument().getIntValue() > 0 and
branch = true and branch = true and
isEmpty = false isEmpty = false
) )

View File

@@ -23,7 +23,7 @@ predicate systemArrayLengthAccess(PropertyAccess pa) {
* - a read of the `Length` of an array with `val` lengths. * - a read of the `Length` of an array with `val` lengths.
*/ */
private predicate constantIntegerExpr(ExprNode e, int val) { private predicate constantIntegerExpr(ExprNode e, int val) {
e.getValue().toInt() = val e.getExpr().getIntValue() = val
or or
exists(ExprNode src | exists(ExprNode src |
e = getAnExplicitDefinitionRead(src) and e = getAnExplicitDefinitionRead(src) and

View File

@@ -57,6 +57,13 @@ class Expr extends ControlFlowElement, @expr {
/** Gets the value of this expression, if any */ /** Gets the value of this expression, if any */
string getValue() { expr_value(this, result) } string getValue() { expr_value(this, result) }
/** Gets the integer value of this expression, if any. */
cached
int getIntValue() {
result = this.getValue().toInt() and
(this.getType() instanceof IntegralType or this.getType() instanceof Enum)
}
/** Holds if this expression has a value. */ /** Holds if this expression has a value. */
final predicate hasValue() { exists(this.getValue()) } final predicate hasValue() { exists(this.getValue()) }

View File

@@ -81,7 +81,7 @@ class SystemRuntimeCompilerServicesInlineArrayAttribute extends Attribute {
/** /**
* Gets the length of the inline array. * Gets the length of the inline array.
*/ */
int getLength() { result = this.getConstructorArgument(0).getValue().toInt() } int getLength() { result = this.getConstructorArgument(0).getIntValue() }
} }
/** An attribute of type `System.Runtime.CompilerServices.OverloadResolutionPriority`. */ /** An attribute of type `System.Runtime.CompilerServices.OverloadResolutionPriority`. */
@@ -94,5 +94,5 @@ class SystemRuntimeCompilerServicesOverloadResolutionPriorityAttribute extends A
/** /**
* Gets the priority number. * Gets the priority number.
*/ */
int getPriority() { result = this.getConstructorArgument(0).getValue().toInt() } int getPriority() { result = this.getConstructorArgument(0).getIntValue() }
} }

View File

@@ -13,7 +13,7 @@
import csharp import csharp
predicate isDefinitelyPositive(Expr e) { predicate isDefinitelyPositive(Expr e) {
e.getValue().toInt() >= 0 or e.getIntValue() >= 0 or
e.(PropertyAccess).getTarget().hasName("Length") or e.(PropertyAccess).getTarget().hasName("Length") or
e.(MethodCall).getTarget().hasUndecoratedName("Count") e.(MethodCall).getTarget().hasUndecoratedName("Count")
} }
@@ -23,12 +23,12 @@ where
t.getLeftOperand() = lhs and t.getLeftOperand() = lhs and
t.getRightOperand() = rhs and t.getRightOperand() = rhs and
not isDefinitelyPositive(lhs.getLeftOperand().stripCasts()) and not isDefinitelyPositive(lhs.getLeftOperand().stripCasts()) and
lhs.getRightOperand().(IntegerLiteral).getValue() = "2" and lhs.getRightOperand().(IntegerLiteral).getIntValue() = 2 and
( (
t instanceof EQExpr and rhs.getValue() = "1" and parity = "oddness" t instanceof EQExpr and rhs.getIntValue() = 1 and parity = "oddness"
or or
t instanceof NEExpr and rhs.getValue() = "1" and parity = "evenness" t instanceof NEExpr and rhs.getIntValue() = 1 and parity = "evenness"
or or
t instanceof GTExpr and rhs.getValue() = "0" and parity = "oddness" t instanceof GTExpr and rhs.getIntValue() = 0 and parity = "oddness"
) )
select t, "Possibly invalid test for " + parity + ". This will fail for negative numbers." select t, "Possibly invalid test for " + parity + ". This will fail for negative numbers."

View File

@@ -27,8 +27,8 @@ predicate isExactEraStartDateCreation(ObjectCreation cr) {
cr.getType().hasFullyQualifiedName("System", "DateTime") or cr.getType().hasFullyQualifiedName("System", "DateTime") or
cr.getType().hasFullyQualifiedName("System", "DateTimeOffset") cr.getType().hasFullyQualifiedName("System", "DateTimeOffset")
) and ) and
isEraStart(cr.getArgument(0).getValue().toInt(), cr.getArgument(1).getValue().toInt(), isEraStart(cr.getArgument(0).getIntValue(), cr.getArgument(1).getIntValue(),
cr.getArgument(2).getValue().toInt()) cr.getArgument(2).getIntValue())
} }
predicate isDateFromJapaneseCalendarToDateTime(MethodCall mc) { predicate isDateFromJapaneseCalendarToDateTime(MethodCall mc) {
@@ -44,7 +44,7 @@ predicate isDateFromJapaneseCalendarToDateTime(MethodCall mc) {
mc.getNumberOfArguments() = 7 // implicitly current era mc.getNumberOfArguments() = 7 // implicitly current era
or or
mc.getNumberOfArguments() = 8 and mc.getNumberOfArguments() = 8 and
mc.getArgument(7).getValue() = "0" mc.getArgument(7).getIntValue() = 0
) // explicitly current era ) // explicitly current era
} }

View File

@@ -40,8 +40,8 @@ predicate convertedToFloatOrDecimal(Expr e, Type t) {
/** Holds if `div` is an exact integer division. */ /** Holds if `div` is an exact integer division. */
predicate exactDivision(DivExpr div) { predicate exactDivision(DivExpr div) {
exists(int numerator, int denominator | exists(int numerator, int denominator |
numerator = div.getNumerator().stripCasts().getValue().toInt() and numerator = div.getNumerator().stripCasts().getIntValue() and
denominator = div.getDenominator().stripCasts().getValue().toInt() and denominator = div.getDenominator().stripCasts().getIntValue() and
numerator % denominator = 0 numerator % denominator = 0
) )
} }

View File

@@ -20,7 +20,7 @@ predicate incorrectUseOfRC2(Assignment e, string msg) {
.getDeclaringType() .getDeclaringType()
.hasFullyQualifiedName("System.Security.Cryptography", "RC2CryptoServiceProvider") .hasFullyQualifiedName("System.Security.Cryptography", "RC2CryptoServiceProvider")
) and ) and
e.getRightOperand().getValue().toInt() < 128 and e.getRightOperand().getIntValue() < 128 and
msg = "Key size should be at least 128 bits for RC2 encryption." msg = "Key size should be at least 128 bits for RC2 encryption."
} }
@@ -28,7 +28,7 @@ predicate incorrectUseOfDsa(ObjectCreation e, string msg) {
e.getTarget() e.getTarget()
.getDeclaringType() .getDeclaringType()
.hasFullyQualifiedName("System.Security.Cryptography", "DSACryptoServiceProvider") and .hasFullyQualifiedName("System.Security.Cryptography", "DSACryptoServiceProvider") and
exists(Expr i | e.getArgument(0) = i and i.getValue().toInt() < 2048) and exists(Expr i | e.getArgument(0) = i and i.getIntValue() < 2048) and
msg = "Key size should be at least 2048 bits for DSA encryption." msg = "Key size should be at least 2048 bits for DSA encryption."
} }
@@ -36,7 +36,7 @@ predicate incorrectUseOfRsa(ObjectCreation e, string msg) {
e.getTarget() e.getTarget()
.getDeclaringType() .getDeclaringType()
.hasFullyQualifiedName("System.Security.Cryptography", "RSACryptoServiceProvider") and .hasFullyQualifiedName("System.Security.Cryptography", "RSACryptoServiceProvider") and
exists(Expr i | e.getArgument(0) = i and i.getValue().toInt() < 2048) and exists(Expr i | e.getArgument(0) = i and i.getIntValue() < 2048) and
msg = "Key size should be at least 2048 bits for RSA encryption." msg = "Key size should be at least 2048 bits for RSA encryption."
} }