|
1 | | -/** Provides classes and predicates related to handling APIs from external libraries. */ |
| 1 | +// Use `semmle.code.csharp.telemetry.ExternalApi` instead. |
| 2 | +deprecated module; |
2 | 3 |
|
3 | | -private import csharp |
4 | | -private import semmle.code.csharp.dispatch.Dispatch |
5 | | -private import semmle.code.csharp.dataflow.FlowSummary |
6 | | -private import semmle.code.csharp.dataflow.internal.DataFlowPrivate |
7 | | -private import semmle.code.csharp.dataflow.internal.DataFlowDispatch as DataFlowDispatch |
8 | | -private import semmle.code.csharp.dataflow.internal.ExternalFlow |
9 | | -private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl |
10 | | -private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate |
11 | | -private import semmle.code.csharp.security.dataflow.flowsources.ApiSources as ApiSources |
12 | | -private import semmle.code.csharp.security.dataflow.flowsinks.ApiSinks as ApiSinks |
13 | | -private import TestLibrary |
14 | | - |
15 | | -/** Holds if the given callable is not worth supporting. */ |
16 | | -private predicate isUninteresting(Callable c) { |
17 | | - c.getDeclaringType() instanceof TestLibrary |
18 | | - or |
19 | | - c.(Constructor).isParameterless() |
20 | | - or |
21 | | - // The data flow library uses read/store steps for properties, so we don't need to model them, |
22 | | - // if both a getter and a setter exist. |
23 | | - c.(Accessor).getDeclaration().(Property).isReadWrite() |
24 | | -} |
25 | | - |
26 | | -/** |
27 | | - * An external API from either the C# Standard Library or a 3rd party library. |
28 | | - */ |
29 | | -class ExternalApi extends Callable { |
30 | | - ExternalApi() { |
31 | | - this.isUnboundDeclaration() and |
32 | | - this.fromLibrary() and |
33 | | - this.(Modifiable).isEffectivelyPublic() and |
34 | | - not isUninteresting(this) |
35 | | - } |
36 | | - |
37 | | - /** |
38 | | - * Gets the unbound type, name and parameter types of this API. |
39 | | - */ |
40 | | - bindingset[this] |
41 | | - private string getSignature() { |
42 | | - result = |
43 | | - nestedName(this.getDeclaringType().getUnboundDeclaration()) + "." + this.getName() + "(" + |
44 | | - parameterQualifiedTypeNamesToString(this) + ")" |
45 | | - } |
46 | | - |
47 | | - /** |
48 | | - * Gets the namespace of this API. |
49 | | - */ |
50 | | - bindingset[this] |
51 | | - string getNamespace() { this.getDeclaringType().hasFullyQualifiedName(result, _) } |
52 | | - |
53 | | - /** |
54 | | - * Gets the namespace and signature of this API. |
55 | | - */ |
56 | | - bindingset[this] |
57 | | - string getApiName() { result = this.getNamespace() + "#" + this.getSignature() } |
58 | | - |
59 | | - /** Gets a node that is an input to a call to this API. */ |
60 | | - private ArgumentNode getAnInput() { |
61 | | - result |
62 | | - .getCall() |
63 | | - .(DataFlowDispatch::NonDelegateDataFlowCall) |
64 | | - .getATarget(_) |
65 | | - .getUnboundDeclaration() = this |
66 | | - } |
67 | | - |
68 | | - /** Gets a node that is an output from a call to this API. */ |
69 | | - private DataFlow::Node getAnOutput() { |
70 | | - exists(Call c, DataFlowDispatch::NonDelegateDataFlowCall dc | |
71 | | - dc.getDispatchCall().getCall() = c and |
72 | | - c.getTarget().getUnboundDeclaration() = this |
73 | | - | |
74 | | - result = DataFlowDispatch::getAnOutNode(dc, _) |
75 | | - ) |
76 | | - } |
77 | | - |
78 | | - /** Holds if this API has a supported summary. */ |
79 | | - pragma[nomagic] |
80 | | - predicate hasSummary() { |
81 | | - this instanceof SummarizedCallable |
82 | | - or |
83 | | - defaultAdditionalTaintStep(this.getAnInput(), _, _) |
84 | | - } |
85 | | - |
86 | | - /** Holds if this API is a known source. */ |
87 | | - pragma[nomagic] |
88 | | - predicate isSource() { this.getAnOutput() instanceof ApiSources::SourceNode } |
89 | | - |
90 | | - /** Holds if this API is a known sink. */ |
91 | | - pragma[nomagic] |
92 | | - predicate isSink() { this.getAnInput() instanceof ApiSinks::SinkNode } |
93 | | - |
94 | | - /** Holds if this API is a known neutral. */ |
95 | | - pragma[nomagic] |
96 | | - predicate isNeutral() { this instanceof FlowSummaryImpl::Public::NeutralCallable } |
97 | | - |
98 | | - /** |
99 | | - * Holds if this API is supported by existing CodeQL libraries, that is, it is either a |
100 | | - * recognized source, sink or neutral or it has a flow summary. |
101 | | - */ |
102 | | - predicate isSupported() { |
103 | | - this.hasSummary() or this.isSource() or this.isSink() or this.isNeutral() |
104 | | - } |
105 | | -} |
106 | | - |
107 | | -/** |
108 | | - * Gets the nested name of the type `t`. |
109 | | - * |
110 | | - * If the type is not a nested type, the result is the same as \`getName()\`. |
111 | | - * Otherwise the name of the nested type is prefixed with a \`+\` and appended to |
112 | | - * the name of the enclosing type, which might be a nested type as well. |
113 | | - */ |
114 | | -private string nestedName(Type t) { |
115 | | - not exists(t.getDeclaringType().getUnboundDeclaration()) and |
116 | | - result = t.getName() |
117 | | - or |
118 | | - nestedName(t.getDeclaringType().getUnboundDeclaration()) + "+" + t.getName() = result |
119 | | -} |
120 | | - |
121 | | -/** |
122 | | - * Gets the limit for the number of results produced by a telemetry query. |
123 | | - */ |
124 | | -int resultLimit() { result = 100 } |
125 | | - |
126 | | -/** |
127 | | - * Holds if it is relevant to count usages of `api`. |
128 | | - */ |
129 | | -signature predicate relevantApi(ExternalApi api); |
130 | | - |
131 | | -/** |
132 | | - * Given a predicate to count relevant API usages, this module provides a predicate |
133 | | - * for restricting the number or returned results based on a certain limit. |
134 | | - */ |
135 | | -module Results<relevantApi/1 getRelevantUsages> { |
136 | | - private int getUsages(string apiName) { |
137 | | - result = |
138 | | - strictcount(Call c, ExternalApi api | |
139 | | - c.getTarget().getUnboundDeclaration() = api and |
140 | | - apiName = api.getApiName() and |
141 | | - getRelevantUsages(api) and |
142 | | - c.fromSource() |
143 | | - ) |
144 | | - } |
145 | | - |
146 | | - private int getOrder(string apiName) { |
147 | | - apiName = |
148 | | - rank[result](string name, int usages | |
149 | | - usages = getUsages(name) |
150 | | - | |
151 | | - name order by usages desc, name |
152 | | - ) |
153 | | - } |
154 | | - |
155 | | - /** |
156 | | - * Holds if there exists an API with `apiName` that is being used `usages` times |
157 | | - * and if it is in the top results (guarded by resultLimit). |
158 | | - */ |
159 | | - predicate restrict(string apiName, int usages) { |
160 | | - usages = getUsages(apiName) and |
161 | | - getOrder(apiName) <= resultLimit() |
162 | | - } |
163 | | -} |
| 4 | +import semmle.code.csharp.telemetry.ExternalApi |
0 commit comments