From fdbc72a673a8e9f2ac6041290142526d929a8c98 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Feb 2026 10:34:49 +0000 Subject: [PATCH] Remove ObjectType parameter checks from System.qll methods Removes instanceof ObjectType checks from method signatures in System.qll to support nullable reference types (object?). This fixes false positives when Equals(object?) is used instead of Equals(object), as they are the same underlying type with different nullability annotations. Fixes: - SystemIComparableInterface.getCompareToMethod() - SystemObjectClass.getEqualsMethod() - SystemObjectClass.getStaticEqualsMethod() - SystemObjectClass.getReferenceEqualsMethod() Co-authored-by: hvitved <3667920+hvitved@users.noreply.github.com> --- .../semmle/code/csharp/frameworks/System.qll | 6 --- .../NullableTest.cs | 46 +++++++++++++++++++ 2 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 csharp/ql/test/query-tests/API Abuse/ClassDoesNotImplementEquals/NullableTest.cs diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/System.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/System.qll index 2681b9437b6..3872ad13dcb 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/System.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/System.qll @@ -144,7 +144,6 @@ class SystemIComparableInterface extends SystemInterface { result.getDeclaringType() = this and result.hasName("CompareTo") and result.getNumberOfParameters() = 1 and - result.getParameter(0).getType() instanceof ObjectType and result.getReturnType() instanceof IntType } } @@ -263,7 +262,6 @@ class SystemObjectClass extends SystemClass instanceof ObjectType { result.getDeclaringType() = this and result.hasName("Equals") and result.getNumberOfParameters() = 1 and - result.getParameter(0).getType() instanceof ObjectType and result.getReturnType() instanceof BoolType } @@ -273,8 +271,6 @@ class SystemObjectClass extends SystemClass instanceof ObjectType { result.getDeclaringType() = this and result.hasName("Equals") and result.getNumberOfParameters() = 2 and - result.getParameter(0).getType() instanceof ObjectType and - result.getParameter(1).getType() instanceof ObjectType and result.getReturnType() instanceof BoolType } @@ -284,8 +280,6 @@ class SystemObjectClass extends SystemClass instanceof ObjectType { result.getDeclaringType() = this and result.hasName("ReferenceEquals") and result.getNumberOfParameters() = 2 and - result.getParameter(0).getType() instanceof ObjectType and - result.getParameter(1).getType() instanceof ObjectType and result.getReturnType() instanceof BoolType } diff --git a/csharp/ql/test/query-tests/API Abuse/ClassDoesNotImplementEquals/NullableTest.cs b/csharp/ql/test/query-tests/API Abuse/ClassDoesNotImplementEquals/NullableTest.cs new file mode 100644 index 00000000000..81c96940a90 --- /dev/null +++ b/csharp/ql/test/query-tests/API Abuse/ClassDoesNotImplementEquals/NullableTest.cs @@ -0,0 +1,46 @@ +using System; + +#nullable enable + +namespace Test +{ + class TestClass1 : IEquatable + { + private int field1; + + public bool Equals(TestClass1? param1) + { + return param1 != null && field1 == param1.field1; + } + + public override bool Equals(object? param2) + { + return param2 is TestClass1 tc && Equals(tc); + } + + public override int GetHashCode() + { + return field1; + } + } + + class TestClass2 + { + private string field2; + + public TestClass2(string s) + { + field2 = s; + } + + public override bool Equals(object? param3) + { + return param3 is TestClass2 tc && field2 == tc.field2; + } + + public override int GetHashCode() + { + return field2?.GetHashCode() ?? 0; + } + } +}