Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a1bedf2

Browse files
committed
C#: Use expression flow state to determine non-null guards
1 parent 2eb2922 commit a1bedf2

6 files changed

Lines changed: 259 additions & 0 deletions

File tree

csharp/ql/src/semmle/code/csharp/controlflow/Guards.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,8 @@ module Internal {
846846
or
847847
e instanceof ArrayCreation
848848
or
849+
e.hasNotNullFlowState()
850+
or
849851
e.hasValue() and
850852
exists(Expr stripped | stripped = e.stripCasts() |
851853
not stripped instanceof NullLiteral and

csharp/ql/test/library-tests/controlflow/guards/AbstractValue.expected

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,77 +91,310 @@ abstractValue
9191
| non-empty | Collections.cs:89:26:89:32 | { ..., ... } |
9292
| non-empty | Collections.cs:90:22:90:28 | { ..., ... } |
9393
| non-null | Assert.cs:9:31:9:32 | "" |
94+
| non-null | Assert.cs:10:9:10:13 | access to type Debug |
95+
| non-null | Assert.cs:11:9:11:15 | access to type Console |
96+
| non-null | Assert.cs:11:27:11:27 | access to local variable s |
9497
| non-null | Assert.cs:16:31:16:32 | "" |
98+
| non-null | Assert.cs:17:9:17:14 | access to type Assert |
99+
| non-null | Assert.cs:18:9:18:15 | access to type Console |
95100
| non-null | Assert.cs:23:31:23:32 | "" |
101+
| non-null | Assert.cs:24:9:24:14 | access to type Assert |
102+
| non-null | Assert.cs:25:9:25:15 | access to type Console |
96103
| non-null | Assert.cs:30:31:30:32 | "" |
104+
| non-null | Assert.cs:31:9:31:14 | access to type Assert |
105+
| non-null | Assert.cs:32:9:32:15 | access to type Console |
97106
| non-null | Assert.cs:37:31:37:32 | "" |
107+
| non-null | Assert.cs:38:9:38:14 | access to type Assert |
108+
| non-null | Assert.cs:39:9:39:15 | access to type Console |
98109
| non-null | Assert.cs:44:31:44:32 | "" |
110+
| non-null | Assert.cs:45:9:45:14 | access to type Assert |
111+
| non-null | Assert.cs:46:9:46:15 | access to type Console |
99112
| non-null | Assert.cs:51:31:51:32 | "" |
113+
| non-null | Assert.cs:52:9:52:14 | access to type Assert |
114+
| non-null | Assert.cs:53:9:53:15 | access to type Console |
100115
| non-null | Assert.cs:58:31:58:32 | "" |
116+
| non-null | Assert.cs:59:9:59:14 | access to type Assert |
117+
| non-null | Assert.cs:60:9:60:15 | access to type Console |
101118
| non-null | Assert.cs:65:31:65:32 | "" |
119+
| non-null | Assert.cs:66:9:66:14 | access to type Assert |
120+
| non-null | Assert.cs:67:9:67:15 | access to type Console |
102121
| non-null | Assert.cs:72:31:72:32 | "" |
122+
| non-null | Assert.cs:73:9:73:14 | access to type Assert |
123+
| non-null | Assert.cs:74:9:74:15 | access to type Console |
103124
| non-null | Assert.cs:79:31:79:32 | "" |
125+
| non-null | Assert.cs:80:9:80:14 | access to type Assert |
126+
| non-null | Assert.cs:81:9:81:15 | access to type Console |
127+
| non-null | Collections.cs:12:17:12:20 | access to parameter args |
128+
| non-null | Collections.cs:13:13:13:16 | access to parameter args |
129+
| non-null | Collections.cs:14:13:14:16 | access to parameter args |
130+
| non-null | Collections.cs:15:13:15:16 | access to parameter args |
131+
| non-null | Collections.cs:16:13:16:16 | access to parameter args |
132+
| non-null | Collections.cs:17:13:17:16 | access to parameter args |
133+
| non-null | Collections.cs:18:13:18:16 | access to parameter args |
134+
| non-null | Collections.cs:23:17:23:20 | access to parameter args |
135+
| non-null | Collections.cs:24:13:24:16 | access to parameter args |
136+
| non-null | Collections.cs:25:13:25:16 | access to parameter args |
137+
| non-null | Collections.cs:26:13:26:16 | access to parameter args |
138+
| non-null | Collections.cs:27:13:27:16 | access to parameter args |
139+
| non-null | Collections.cs:28:13:28:16 | access to parameter args |
140+
| non-null | Collections.cs:29:13:29:16 | access to parameter args |
141+
| non-null | Collections.cs:34:17:34:20 | access to parameter args |
142+
| non-null | Collections.cs:35:13:35:16 | access to parameter args |
143+
| non-null | Collections.cs:36:13:36:16 | access to parameter args |
144+
| non-null | Collections.cs:37:13:37:16 | access to parameter args |
145+
| non-null | Collections.cs:38:13:38:16 | access to parameter args |
146+
| non-null | Collections.cs:39:13:39:16 | access to parameter args |
147+
| non-null | Collections.cs:40:13:40:16 | access to parameter args |
148+
| non-null | Collections.cs:45:17:45:20 | access to parameter args |
149+
| non-null | Collections.cs:50:13:50:16 | access to parameter args |
150+
| non-null | Collections.cs:52:17:52:20 | access to parameter args |
151+
| non-null | Collections.cs:52:17:52:30 | call to method ToArray |
152+
| non-null | Collections.cs:53:9:53:12 | access to parameter args |
153+
| non-null | Collections.cs:54:9:54:9 | access to local variable x |
154+
| non-null | Collections.cs:54:9:54:26 | ... = ... |
155+
| non-null | Collections.cs:54:13:54:16 | access to parameter args |
156+
| non-null | Collections.cs:54:13:54:26 | call to method ToArray |
157+
| non-null | Collections.cs:55:9:55:9 | access to local variable x |
104158
| non-null | Collections.cs:55:9:55:41 | ... = ... |
105159
| non-null | Collections.cs:55:13:55:41 | array creation of type String[] |
106160
| non-null | Collections.cs:55:27:55:29 | "a" |
107161
| non-null | Collections.cs:55:32:55:34 | "b" |
108162
| non-null | Collections.cs:55:37:55:39 | "c" |
163+
| non-null | Collections.cs:56:9:56:9 | access to local variable x |
109164
| non-null | Collections.cs:56:9:56:13 | ... = ... |
110165
| non-null | Collections.cs:56:13:56:13 | access to local variable x |
166+
| non-null | Collections.cs:57:9:57:9 | access to local variable x |
111167
| non-null | Collections.cs:57:9:57:25 | ... = ... |
112168
| non-null | Collections.cs:57:13:57:25 | array creation of type String[] |
169+
| non-null | Collections.cs:58:9:58:9 | access to local variable x |
113170
| non-null | Collections.cs:58:9:58:13 | ... = ... |
114171
| non-null | Collections.cs:58:13:58:13 | access to local variable x |
115172
| non-null | Collections.cs:63:17:63:45 | array creation of type String[] |
173+
| non-null | Collections.cs:63:17:63:54 | call to method ToList |
116174
| non-null | Collections.cs:63:31:63:33 | "a" |
117175
| non-null | Collections.cs:63:36:63:38 | "b" |
118176
| non-null | Collections.cs:63:41:63:43 | "c" |
177+
| non-null | Collections.cs:64:9:64:9 | access to local variable x |
178+
| non-null | Collections.cs:65:13:65:13 | access to local variable x |
179+
| non-null | Collections.cs:67:13:67:13 | access to local variable x |
119180
| non-null | Collections.cs:67:19:67:21 | "a" |
181+
| non-null | Collections.cs:68:13:68:13 | access to local variable x |
120182
| non-null | Collections.cs:68:19:68:21 | "b" |
183+
| non-null | Collections.cs:74:35:74:35 | access to parameter s |
121184
| non-null | Collections.cs:74:40:74:41 | "" |
185+
| non-null | Collections.cs:75:17:75:20 | access to parameter args |
186+
| non-null | Collections.cs:75:26:75:32 | access to local function IsEmpty |
187+
| non-null | Collections.cs:75:26:75:32 | delegate creation of type Func<String,Boolean> |
122188
| non-null | Collections.cs:75:26:75:32 | this access |
189+
| non-null | Collections.cs:76:13:76:16 | access to parameter args |
190+
| non-null | Collections.cs:76:24:76:30 | access to local function IsEmpty |
191+
| non-null | Collections.cs:76:24:76:30 | delegate creation of type Func<String,Boolean> |
123192
| non-null | Collections.cs:76:24:76:30 | this access |
193+
| non-null | Collections.cs:77:13:77:16 | access to parameter args |
194+
| non-null | Collections.cs:77:24:77:30 | access to local function IsEmpty |
195+
| non-null | Collections.cs:77:24:77:30 | delegate creation of type Func<String,Boolean> |
124196
| non-null | Collections.cs:77:24:77:30 | this access |
197+
| non-null | Collections.cs:78:13:78:16 | access to parameter args |
198+
| non-null | Collections.cs:78:24:78:30 | access to local function IsEmpty |
199+
| non-null | Collections.cs:78:24:78:30 | delegate creation of type Func<String,Boolean> |
125200
| non-null | Collections.cs:78:24:78:30 | this access |
201+
| non-null | Collections.cs:79:13:79:16 | access to parameter args |
202+
| non-null | Collections.cs:79:24:79:30 | access to local function IsEmpty |
203+
| non-null | Collections.cs:79:24:79:30 | delegate creation of type Func<String,Boolean> |
126204
| non-null | Collections.cs:79:24:79:30 | this access |
205+
| non-null | Collections.cs:80:13:80:16 | access to parameter args |
206+
| non-null | Collections.cs:80:24:80:30 | access to local function IsEmpty |
207+
| non-null | Collections.cs:80:24:80:30 | delegate creation of type Func<String,Boolean> |
127208
| non-null | Collections.cs:80:24:80:30 | this access |
209+
| non-null | Collections.cs:81:13:81:16 | access to parameter args |
210+
| non-null | Collections.cs:81:24:81:30 | access to local function IsEmpty |
211+
| non-null | Collections.cs:81:24:81:30 | delegate creation of type Func<String,Boolean> |
128212
| non-null | Collections.cs:81:24:81:30 | this access |
213+
| non-null | Collections.cs:82:13:82:16 | access to parameter args |
214+
| non-null | Collections.cs:82:24:82:30 | access to local function IsEmpty |
215+
| non-null | Collections.cs:82:24:82:30 | delegate creation of type Func<String,Boolean> |
129216
| non-null | Collections.cs:82:24:82:30 | this access |
130217
| non-null | Collections.cs:87:17:87:31 | array creation of type String[] |
131218
| non-null | Collections.cs:88:22:88:23 | array creation of type String[] |
219+
| non-null | Collections.cs:89:9:89:9 | access to local variable x |
132220
| non-null | Collections.cs:89:9:89:32 | ... = ... |
133221
| non-null | Collections.cs:89:13:89:32 | array creation of type String[] |
134222
| non-null | Collections.cs:89:28:89:30 | "a" |
135223
| non-null | Collections.cs:90:22:90:28 | array creation of type String[] |
136224
| non-null | Collections.cs:90:24:90:26 | "a" |
225+
| non-null | Guards.cs:12:13:12:13 | access to parameter s |
226+
| non-null | Guards.cs:14:13:14:19 | access to type Console |
227+
| non-null | Guards.cs:14:31:14:31 | access to parameter s |
228+
| non-null | Guards.cs:18:13:18:19 | access to type Console |
137229
| non-null | Guards.cs:18:31:18:46 | "<empty string>" |
230+
| non-null | Guards.cs:26:13:26:19 | access to type Console |
231+
| non-null | Guards.cs:26:31:26:31 | access to parameter s |
232+
| non-null | Guards.cs:32:14:32:19 | access to type String |
233+
| non-null | Guards.cs:33:13:33:19 | access to type Console |
138234
| non-null | Guards.cs:33:31:33:35 | ... + ... |
235+
| non-null | Guards.cs:36:14:36:20 | access to type Console |
236+
| non-null | Guards.cs:36:32:36:32 | access to parameter x |
139237
| non-null | Guards.cs:36:32:36:36 | ... + ... |
238+
| non-null | Guards.cs:36:36:36:36 | access to parameter y |
239+
| non-null | Guards.cs:39:13:39:19 | access to type Console |
240+
| non-null | Guards.cs:39:31:39:31 | access to parameter x |
140241
| non-null | Guards.cs:39:31:39:35 | ... + ... |
242+
| non-null | Guards.cs:39:35:39:35 | access to parameter y |
243+
| non-null | Guards.cs:42:14:42:20 | access to type Console |
244+
| non-null | Guards.cs:42:32:42:32 | access to parameter x |
141245
| non-null | Guards.cs:42:32:42:36 | ... + ... |
246+
| non-null | Guards.cs:42:36:42:36 | access to parameter y |
142247
| non-null | Guards.cs:44:13:44:17 | this access |
248+
| non-null | Guards.cs:45:13:45:19 | access to type Console |
143249
| non-null | Guards.cs:45:31:45:42 | object creation of type Guards |
144250
| non-null | Guards.cs:47:13:47:17 | this access |
251+
| non-null | Guards.cs:48:13:48:19 | access to type Console |
145252
| non-null | Guards.cs:48:31:48:34 | this access |
253+
| non-null | Guards.cs:48:31:48:40 | access to field Field |
254+
| non-null | Guards.cs:53:13:53:13 | access to parameter g |
255+
| non-null | Guards.cs:55:9:55:15 | access to type Console |
256+
| non-null | Guards.cs:55:27:55:27 | access to parameter g |
257+
| non-null | Guards.cs:55:27:55:33 | access to field Field |
258+
| non-null | Guards.cs:60:13:60:13 | access to parameter g |
146259
| non-null | Guards.cs:61:19:61:33 | object creation of type Exception |
260+
| non-null | Guards.cs:62:9:62:15 | access to type Console |
261+
| non-null | Guards.cs:62:27:62:27 | access to parameter g |
262+
| non-null | Guards.cs:62:27:62:36 | access to property Property |
263+
| non-null | Guards.cs:62:27:62:45 | access to property Property |
264+
| non-null | Guards.cs:62:27:62:51 | access to field Field |
265+
| non-null | Guards.cs:63:9:63:15 | access to type Console |
266+
| non-null | Guards.cs:63:27:63:27 | access to parameter g |
267+
| non-null | Guards.cs:63:27:63:36 | access to property Property |
268+
| non-null | Guards.cs:70:13:70:19 | access to type Console |
269+
| non-null | Guards.cs:70:31:70:31 | access to parameter s |
270+
| non-null | Guards.cs:71:13:71:13 | access to parameter s |
271+
| non-null | Guards.cs:72:13:72:19 | access to type Console |
272+
| non-null | Guards.cs:78:15:78:21 | access to property Length |
147273
| non-null | Guards.cs:78:26:78:26 | (...) ... |
274+
| non-null | Guards.cs:79:13:79:19 | access to type Console |
275+
| non-null | Guards.cs:79:31:79:31 | access to parameter s |
276+
| non-null | Guards.cs:80:15:80:21 | access to property Length |
148277
| non-null | Guards.cs:80:25:80:25 | (...) ... |
278+
| non-null | Guards.cs:81:13:81:19 | access to type Console |
279+
| non-null | Guards.cs:81:31:81:31 | access to parameter s |
280+
| non-null | Guards.cs:82:15:82:21 | access to property Length |
149281
| non-null | Guards.cs:82:26:82:26 | (...) ... |
282+
| non-null | Guards.cs:83:13:83:19 | access to type Console |
283+
| non-null | Guards.cs:83:31:83:31 | access to parameter s |
284+
| non-null | Guards.cs:84:15:84:21 | access to property Length |
150285
| non-null | Guards.cs:84:25:84:26 | (...) ... |
286+
| non-null | Guards.cs:85:13:85:19 | access to type Console |
287+
| non-null | Guards.cs:85:31:85:31 | access to parameter s |
288+
| non-null | Guards.cs:86:15:86:21 | access to property Length |
151289
| non-null | Guards.cs:86:26:86:27 | (...) ... |
290+
| non-null | Guards.cs:87:13:87:19 | access to type Console |
291+
| non-null | Guards.cs:87:31:87:31 | access to parameter s |
292+
| non-null | Guards.cs:88:15:88:21 | access to property Length |
293+
| non-null | Guards.cs:89:13:89:19 | access to type Console |
294+
| non-null | Guards.cs:89:31:89:31 | access to parameter s |
295+
| non-null | Guards.cs:91:13:91:19 | access to type Console |
296+
| non-null | Guards.cs:92:15:92:21 | access to property Length |
152297
| non-null | Guards.cs:92:25:92:25 | (...) ... |
153298
| non-null | Guards.cs:92:30:92:30 | (...) ... |
299+
| non-null | Guards.cs:93:13:93:19 | access to type Console |
300+
| non-null | Guards.cs:95:13:95:19 | access to type Console |
154301
| non-null | Guards.cs:96:18:96:19 | "" |
302+
| non-null | Guards.cs:97:13:97:19 | access to type Console |
303+
| non-null | Guards.cs:97:31:97:31 | access to parameter s |
304+
| non-null | Guards.cs:99:13:99:19 | access to type Console |
305+
| non-null | Guards.cs:104:13:104:13 | access to parameter g |
155306
| non-null | Guards.cs:105:19:105:33 | object creation of type Exception |
307+
| non-null | Guards.cs:106:9:106:9 | access to parameter g |
308+
| non-null | Guards.cs:106:9:106:18 | access to property Property |
309+
| non-null | Guards.cs:107:9:107:15 | access to type Console |
310+
| non-null | Guards.cs:107:27:107:27 | access to parameter g |
311+
| non-null | Guards.cs:108:9:108:15 | access to type Console |
312+
| non-null | Guards.cs:108:27:108:27 | access to parameter g |
313+
| non-null | Guards.cs:108:27:108:36 | access to property Property |
314+
| non-null | Guards.cs:113:21:113:21 | access to parameter g |
315+
| non-null | Guards.cs:114:14:114:14 | access to parameter g |
316+
| non-null | Guards.cs:114:14:114:23 | access to property Property |
317+
| non-null | Guards.cs:114:14:114:32 | access to property Property |
318+
| non-null | Guards.cs:115:9:115:55 | ... = ... |
319+
| non-null | Guards.cs:115:17:115:17 | access to parameter g |
320+
| non-null | Guards.cs:115:17:115:26 | access to property Property |
321+
| non-null | Guards.cs:115:17:115:35 | access to property Property |
322+
| non-null | Guards.cs:115:17:115:55 | ... ?? ... |
323+
| non-null | Guards.cs:115:46:115:55 | throw ... |
324+
| non-null | Guards.cs:116:9:116:15 | access to type Console |
325+
| non-null | Guards.cs:116:27:116:27 | access to parameter g |
326+
| non-null | Guards.cs:116:27:116:36 | access to property Property |
327+
| non-null | Guards.cs:116:27:116:45 | access to property Property |
328+
| non-null | Guards.cs:116:27:116:51 | access to field Field |
329+
| non-null | Guards.cs:117:9:117:9 | access to parameter g |
330+
| non-null | Guards.cs:117:9:117:18 | access to property Property |
331+
| non-null | Guards.cs:118:9:118:15 | access to type Console |
332+
| non-null | Guards.cs:118:27:118:27 | access to parameter g |
333+
| non-null | Guards.cs:119:9:119:15 | access to type Console |
334+
| non-null | Guards.cs:119:27:119:27 | access to parameter g |
335+
| non-null | Guards.cs:119:27:119:36 | access to property Property |
336+
| non-null | Guards.cs:125:18:125:19 | access to parameter s1 |
337+
| non-null | Guards.cs:125:21:125:31 | call to method Equals |
338+
| non-null | Guards.cs:125:29:125:30 | access to parameter s1 |
339+
| non-null | Guards.cs:132:16:132:16 | access to parameter s |
340+
| non-null | Guards.cs:138:20:138:20 | access to parameter s |
341+
| non-null | Guards.cs:145:20:145:20 | access to local variable s |
342+
| non-null | Guards.cs:154:24:154:24 | access to parameter o |
343+
| non-null | Guards.cs:156:24:156:24 | access to local variable a |
344+
| non-null | Guards.cs:158:24:158:24 | access to parameter o |
345+
| non-null | Guards.cs:162:24:162:24 | access to parameter o |
346+
| non-null | Guards.cs:168:14:168:19 | access to type String |
347+
| non-null | Guards.cs:169:13:169:19 | access to type Console |
348+
| non-null | Guards.cs:169:31:169:31 | access to parameter x |
156349
| non-null | Guards.cs:183:38:183:49 | this access |
157350
| non-null | Guards.cs:189:14:189:25 | this access |
351+
| non-null | Guards.cs:190:13:190:19 | access to type Console |
158352
| non-null | Guards.cs:191:14:191:25 | this access |
353+
| non-null | Guards.cs:192:13:192:19 | access to type Console |
159354
| non-null | Guards.cs:193:14:193:25 | this access |
355+
| non-null | Guards.cs:194:13:194:19 | access to type Console |
160356
| non-null | Guards.cs:195:13:195:27 | this access |
357+
| non-null | Guards.cs:196:13:196:19 | access to type Console |
161358
| non-null | Guards.cs:197:14:197:29 | this access |
359+
| non-null | Guards.cs:198:13:198:19 | access to type Console |
360+
| non-null | Guards.cs:205:13:205:13 | access to parameter o |
361+
| non-null | Guards.cs:206:33:206:36 | access to parameter args |
362+
| non-null | Guards.cs:208:17:208:17 | access to parameter o |
363+
| non-null | Guards.cs:268:16:268:25 | call to method GetType |
162364
| non-null | Guards.cs:268:30:268:41 | call to method GetType |
365+
| non-null | Guards.cs:269:13:269:14 | access to parameter o1 |
366+
| non-null | Guards.cs:270:16:270:25 | call to method GetType |
367+
| non-null | Guards.cs:270:30:270:31 | access to parameter o2 |
368+
| non-null | Guards.cs:270:33:270:42 | call to method GetType |
369+
| non-null | Guards.cs:279:17:279:17 | access to parameter o |
370+
| non-null | Guards.cs:281:17:281:17 | access to local variable a |
371+
| non-null | Guards.cs:283:17:283:17 | access to parameter o |
372+
| non-null | Guards.cs:287:17:287:17 | access to parameter o |
373+
| non-null | Splitting.cs:13:17:13:17 | access to parameter o |
374+
| non-null | Splitting.cs:23:24:23:24 | access to parameter o |
163375
| non-null | Splitting.cs:33:24:33:25 | "" |
376+
| non-null | Splitting.cs:44:17:44:17 | access to parameter o |
377+
| non-null | Splitting.cs:46:17:46:17 | access to parameter o |
378+
| non-null | Splitting.cs:55:13:55:13 | access to parameter o |
379+
| non-null | Splitting.cs:66:20:66:20 | access to parameter o |
380+
| non-null | Splitting.cs:78:24:78:24 | access to parameter o |
381+
| non-null | Splitting.cs:87:13:87:17 | access to type Debug |
382+
| non-null | Splitting.cs:90:13:90:13 | access to parameter o |
383+
| non-null | Splitting.cs:91:9:91:9 | access to parameter o |
384+
| non-null | Splitting.cs:97:13:97:17 | access to type Debug |
385+
| non-null | Splitting.cs:105:9:105:13 | access to type Debug |
386+
| non-null | Splitting.cs:107:13:107:13 | access to parameter o |
387+
| non-null | Splitting.cs:109:13:109:13 | access to parameter o |
388+
| non-null | Splitting.cs:116:9:116:13 | access to type Debug |
389+
| non-null | Splitting.cs:117:9:117:9 | access to parameter o |
390+
| non-null | Splitting.cs:119:13:119:13 | access to parameter o |
391+
| non-null | Splitting.cs:120:16:120:16 | access to parameter o |
392+
| non-null | Splitting.cs:132:17:132:17 | access to local variable o |
393+
| non-null | Splitting.cs:132:17:132:29 | ... = ... |
394+
| non-null | Splitting.cs:132:21:132:29 | call to method M11 |
164395
| non-null | Splitting.cs:132:21:132:29 | this access |
396+
| non-null | Splitting.cs:132:28:132:28 | access to local variable o |
397+
| non-null | Splitting.cs:133:17:133:17 | access to local variable o |
165398
| null | Assert.cs:9:24:9:27 | null |
166399
| null | Assert.cs:10:27:10:30 | null |
167400
| null | Assert.cs:16:24:16:27 | null |

0 commit comments

Comments
 (0)