mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
C#: Include dictionary indexers and more methods in cs/gethashcode-is-not-defined.
This commit is contained in:
@@ -159,6 +159,15 @@ class SystemCollectionsGenericIDictionaryInterface extends SystemCollectionsGene
|
||||
}
|
||||
}
|
||||
|
||||
/** The ``System.Collections.Generic.IReadOnlyDictionary`2`` interface. */
|
||||
class SystemCollectionsGenericIReadOnlyDictionaryInterface extends SystemCollectionsGenericUnboundGenericInterface
|
||||
{
|
||||
SystemCollectionsGenericIReadOnlyDictionaryInterface() {
|
||||
this.hasName("IReadOnlyDictionary`2") and
|
||||
this.getNumberOfTypeParameters() = 2
|
||||
}
|
||||
}
|
||||
|
||||
/** The ``System.Collections.Generic.IReadOnlyCollection`1`` interface. */
|
||||
class SystemCollectionsGenericIReadOnlyCollectionTInterface extends SystemCollectionsGenericUnboundGenericInterface
|
||||
{
|
||||
@@ -176,3 +185,11 @@ class SystemCollectionsGenericIReadOnlyListTInterface extends SystemCollectionsG
|
||||
this.getNumberOfTypeParameters() = 1
|
||||
}
|
||||
}
|
||||
|
||||
/** The ``System.Collections.Generic.HashSet`1`` class. */
|
||||
class SystemCollectionsGenericHashSetClass extends SystemCollectionsGenericUnboundGenericClass {
|
||||
SystemCollectionsGenericHashSetClass() {
|
||||
this.hasName("HashSet`1") and
|
||||
this.getNumberOfTypeParameters() = 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,24 +11,44 @@
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.frameworks.System
|
||||
import semmle.code.csharp.frameworks.system.Collections
|
||||
import semmle.code.csharp.frameworks.system.collections.Generic
|
||||
|
||||
predicate dictionary(ConstructedType constructed) {
|
||||
exists(UnboundGenericType dict |
|
||||
dict.hasFullyQualifiedName("System.Collections.Generic", "Dictionary`2") and
|
||||
constructed = dict.getAConstructedGeneric()
|
||||
/**
|
||||
* Holds if `t` is a dictionary type.
|
||||
*/
|
||||
predicate dictionary(ValueOrRefType t) {
|
||||
exists(Type base | base = t.getABaseType*().getUnboundDeclaration() |
|
||||
base instanceof SystemCollectionsGenericIDictionaryInterface or
|
||||
base instanceof SystemCollectionsGenericIReadOnlyDictionaryInterface or
|
||||
base instanceof SystemCollectionsIDictionaryInterface
|
||||
)
|
||||
}
|
||||
|
||||
predicate hashtable(Class c) { c.hasFullyQualifiedName("System.Collections", "Hashtable") }
|
||||
/**
|
||||
* Holds if `c` is a hashset type.
|
||||
*/
|
||||
predicate hashSet(ValueOrRefType t) {
|
||||
t.getABaseType*().getUnboundDeclaration() instanceof SystemCollectionsGenericHashSetClass
|
||||
}
|
||||
|
||||
predicate hashstructure(Type t) { hashtable(t) or dictionary(t) }
|
||||
predicate hashStructure(Type t) { dictionary(t) or hashSet(t) }
|
||||
|
||||
predicate hashAdd(Expr e) {
|
||||
/**
|
||||
* Holds if the expression `e` relies on `GetHashCode()` implementation.
|
||||
* That is, if the call assumes that `e1.Equals(e2)` implies `e1.GetHashCode() == e2.GetHashCode()`.
|
||||
*/
|
||||
predicate usesHashing(Expr e) {
|
||||
exists(MethodCall mc, string name |
|
||||
(name = "Add" or name = "ContainsKey") and
|
||||
name = ["Add", "Contains", "ContainsKey", "Remove", "TryAdd", "TryGetValue"] and
|
||||
mc.getArgument(0) = e and
|
||||
mc.getTarget().hasName(name) and
|
||||
hashstructure(mc.getTarget().getDeclaringType())
|
||||
hashStructure(mc.getTarget().getDeclaringType())
|
||||
)
|
||||
or
|
||||
exists(IndexerCall ic |
|
||||
ic.getArgument(0) = e and
|
||||
dictionary(ic.getTarget().getDeclaringType())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -46,7 +66,7 @@ predicate hashCall(Expr e) {
|
||||
|
||||
from Expr e, Type t
|
||||
where
|
||||
(hashAdd(e) or hashCall(e)) and
|
||||
(usesHashing(e) or hashCall(e)) and
|
||||
e.getType() = t and
|
||||
eqWithoutHash(t)
|
||||
select e,
|
||||
|
||||
Reference in New Issue
Block a user