11
11
12
12
import csharp
13
13
import semmle.code.csharp.frameworks.System
14
+ import semmle.code.csharp.frameworks.system.Collections
15
+ import semmle.code.csharp.frameworks.system.collections.Generic
14
16
15
- predicate dictionary ( ConstructedType constructed ) {
16
- exists ( UnboundGenericType dict |
17
- dict .hasFullyQualifiedName ( "System.Collections.Generic" , "Dictionary`2" ) and
18
- constructed = dict .getAConstructedGeneric ( )
17
+ /**
18
+ * Holds if `t` is a dictionary type.
19
+ */
20
+ predicate dictionary ( ValueOrRefType t ) {
21
+ exists ( Type base | base = t .getABaseType * ( ) .getUnboundDeclaration ( ) |
22
+ base instanceof SystemCollectionsGenericIDictionaryInterface or
23
+ base instanceof SystemCollectionsGenericIReadOnlyDictionaryInterface or
24
+ base instanceof SystemCollectionsIDictionaryInterface
19
25
)
20
26
}
21
27
22
- predicate hashtable ( Class c ) { c .hasFullyQualifiedName ( "System.Collections" , "Hashtable" ) }
28
+ /**
29
+ * Holds if `c` is a hashset type.
30
+ */
31
+ predicate hashSet ( ValueOrRefType t ) {
32
+ t .getABaseType * ( ) .getUnboundDeclaration ( ) instanceof SystemCollectionsGenericHashSetClass
33
+ }
23
34
24
- predicate hashstructure ( Type t ) { hashtable ( t ) or dictionary ( t ) }
35
+ predicate hashStructure ( Type t ) { dictionary ( t ) or hashSet ( t ) }
25
36
26
- predicate hashAdd ( Expr e ) {
37
+ /**
38
+ * Holds if the expression `e` relies on `GetHashCode()` implementation.
39
+ * That is, if the call assumes that `e1.Equals(e2)` implies `e1.GetHashCode() == e2.GetHashCode()`.
40
+ */
41
+ predicate usesHashing ( Expr e ) {
27
42
exists ( MethodCall mc , string name |
28
- ( name = "Add" or name = "ContainsKey" ) and
43
+ name = [ "Add" , "Contains" , "ContainsKey" , "Remove" , "TryAdd" , "TryGetValue" ] and
29
44
mc .getArgument ( 0 ) = e and
30
45
mc .getTarget ( ) .hasName ( name ) and
31
- hashstructure ( mc .getTarget ( ) .getDeclaringType ( ) )
46
+ hashStructure ( mc .getTarget ( ) .getDeclaringType ( ) )
47
+ )
48
+ or
49
+ exists ( IndexerCall ic |
50
+ ic .getArgument ( 0 ) = e and
51
+ dictionary ( ic .getTarget ( ) .getDeclaringType ( ) )
32
52
)
33
53
}
34
54
@@ -46,7 +66,7 @@ predicate hashCall(Expr e) {
46
66
47
67
from Expr e , Type t
48
68
where
49
- ( hashAdd ( e ) or hashCall ( e ) ) and
69
+ ( usesHashing ( e ) or hashCall ( e ) ) and
50
70
e .getType ( ) = t and
51
71
eqWithoutHash ( t )
52
72
select e ,
0 commit comments