Skip to content

Commit 25881d6

Browse files
authored
Merge pull request #8626 from michaelnebel/csharp/equalsgethashcodeoverrides
C#: Exclude Equals and GetHashCode overrides from model generation.
2 parents 50dc382 + 81904cc commit 25881d6

File tree

4 files changed

+65
-1
lines changed

4 files changed

+65
-1
lines changed

csharp/ql/src/utils/model-generator/internal/CaptureModelsSpecific.qll

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ private import csharp as CS
66
private import semmle.code.csharp.commons.Util as Util
77
private import semmle.code.csharp.commons.Collections as Collections
88
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
9+
private import semmle.code.csharp.frameworks.System as System
910
import semmle.code.csharp.dataflow.ExternalFlow as ExternalFlow
1011
import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
1112
import semmle.code.csharp.dataflow.internal.DataFlowPrivate as DataFlowPrivate
@@ -16,14 +17,34 @@ module TaintTracking = CS::TaintTracking;
1617

1718
class Type = CS::Type;
1819

20+
/**
21+
* Holds if `api` is an override or an interface implementation that
22+
* is irrelevant to the data flow analysis.
23+
*/
24+
private predicate isIrrelevantOverrideOrImplementation(CS::Callable api) {
25+
exists(CS::Callable exclude, CS::Method m |
26+
(
27+
api = m.getAnOverrider*().getUnboundDeclaration()
28+
or
29+
api = m.getAnUltimateImplementor().getUnboundDeclaration()
30+
) and
31+
exclude = m.getUnboundDeclaration()
32+
|
33+
exists(System::SystemObjectClass c | exclude = [c.getGetHashCodeMethod(), c.getEqualsMethod()])
34+
or
35+
exists(System::SystemIEquatableTInterface i | exclude = i.getEqualsMethod())
36+
)
37+
}
38+
1939
/**
2040
* Holds if it is relevant to generate models for `api`.
2141
*/
2242
private predicate isRelevantForModels(CS::Callable api) {
2343
[api.(CS::Modifiable), api.(CS::Accessor).getDeclaration()].isEffectivelyPublic() and
44+
api.getDeclaringType().getNamespace().getQualifiedName() != "" and
2445
not api instanceof CS::ConversionOperator and
2546
not api instanceof Util::MainMethod and
26-
api.getDeclaringType().getNamespace().getQualifiedName() != ""
47+
not isIrrelevantOverrideOrImplementation(api)
2748
}
2849

2950
/**

csharp/ql/test/utils/model-generator/CaptureSummaryModels.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
| Summaries;DerivedClass1Flow;false;ReturnParam1;(System.Int32,System.Int32);Argument[1];ReturnValue;taint |
1919
| Summaries;DerivedClass2Flow;false;ReturnParam0;(System.Int32,System.Int32);Argument[0];ReturnValue;taint |
2020
| Summaries;DerivedClass2Flow;false;ReturnParam;(System.Int32);Argument[0];ReturnValue;taint |
21+
| Summaries;EqualsGetHashCodeNoFlow;false;Equals;(System.Int32);Argument[0];ReturnValue;taint |
2122
| Summaries;GenericFlow<>;false;AddFieldToGenericList;(System.Collections.Generic.List<T>);Argument[Qualifier];Argument[0].Element;taint |
2223
| Summaries;GenericFlow<>;false;AddToGenericList<>;(System.Collections.Generic.List<S>,S);Argument[1];Argument[0].Element;taint |
2324
| Summaries;GenericFlow<>;false;ReturnFieldInGenericList;();Argument[Qualifier];ReturnValue;taint |

csharp/ql/test/utils/model-generator/NoSummaries.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,22 @@ public int ReturnParam(int input)
4242
}
4343
}
4444
}
45+
}
46+
47+
public class EquatableBound : IEquatable<int>
48+
{
49+
public readonly bool tainted;
50+
public bool Equals(int other)
51+
{
52+
return tainted;
53+
}
54+
}
55+
56+
public class EquatableUnBound<T> : IEquatable<T>
57+
{
58+
public readonly bool tainted;
59+
public bool Equals(T? other)
60+
{
61+
return tainted;
62+
}
4563
}

csharp/ql/test/utils/model-generator/Summaries.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,4 +206,28 @@ public static explicit operator OperatorFlow(byte b)
206206
return new OperatorFlow(b);
207207
}
208208

209+
}
210+
211+
public class EqualsGetHashCodeNoFlow
212+
{
213+
public readonly bool boolTainted;
214+
public readonly int intTainted;
215+
216+
// No flow summary as this is an override of the Equals method.
217+
public override bool Equals(object obj)
218+
{
219+
return boolTainted;
220+
}
221+
222+
// Flow summary as this is not an override of the object Equals method.
223+
public int Equals(int i)
224+
{
225+
return i;
226+
}
227+
228+
// No flow summary as this is an override of the GetHashCode method.
229+
public override int GetHashCode()
230+
{
231+
return intTainted;
232+
}
209233
}

0 commit comments

Comments
 (0)