-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathDataMembers.qll
71 lines (64 loc) · 2.29 KB
/
DataMembers.qll
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* Provides classes for talking about "data members" of a class.
*
* In C#, fields are only one kind of data member -- indexers and properties
* give rise to very similar concepts that we may want to treat uniformly.
*/
import csharp
/**
* Library helper class unifying the various members which may hold data,
* namely fields, properties and indexer results.
*/
class DataMember extends Member {
DataMember() {
this instanceof Field or
this instanceof Property or
this instanceof Indexer
}
/**
* Gets the type of the data member. For a field, this is the type of the field.
* For a property or indexer, it is the type returned by the `get` accessor.
*/
Type getType() {
result = this.(Field).getType() or
result = this.(Property).getType() or
result = this.(Indexer).getType()
}
}
/**
* A data member which is also a collection.
*/
class CollectionMember extends DataMember {
CollectionMember() { this.getType().(ValueOrRefType).getABaseType*().hasName("ICollection") }
/**
* Gets an expression corresponding to a read or write of this collection member.
*/
Expr getAReadOrWrite() { result = this.getARead() or result = this.getAWrite() }
/**
* Gets an expression corresponding to a read access of this collection member.
*/
Expr getARead() {
// A read of a field or property can be a method call...
result = any(MethodCall call | call.getQualifier() = this.getAnAccess())
or
// ... or an indexer access that isn't in an assignment position
result = any(IndexerRead ir | ir.getQualifier() = this.getAnAccess())
}
/**
* Gets an expression corresponding to a write access to this collection member.
* Typically this will change the contents of the collection.
*/
Expr getAWrite() {
// A write of a field or property can be a method call to certain methods...
exists(MethodCall call | call = result |
call.getQualifier() = this.getAnAccess() and
call.getTarget()
.getName()
.regexpMatch("Add.*|Append|Clear.*|Delete|" +
"(Try)?Dequeue|Enqueue|Insert.*|(Try)?Pop|Push|(Try?)Remove.*|Replace.*|SafeDelete|Set.*|")
)
or
// ... or an indexer access that is in an assignment position
result = any(IndexerWrite iw | iw.getQualifier() = this.getAnAccess())
}
}