Coverage Report

Created: 2026-10-28 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cryptsetup/lib/luks2/luks2_segment.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * LUKS - Linux Unified Key Setup v2, internal segment handling
4
 *
5
 * Copyright (C) 2018-2026 Red Hat, Inc. All rights reserved.
6
 * Copyright (C) 2018-2026 Ondrej Kozina
7
 */
8
9
#include "luks2_internal.h"
10
11
/* use only on already validated 'segments' object */
12
uint64_t json_segments_get_minimal_offset(json_object *jobj_segments, unsigned blockwise)
13
6.44k
{
14
6.44k
  uint64_t tmp, min = blockwise ? UINT64_MAX >> SECTOR_SHIFT : UINT64_MAX;
15
16
6.44k
  if (!jobj_segments)
17
0
    return 0;
18
19
6.56k
  json_object_object_foreach(jobj_segments, key, val) {
20
6.56k
    UNUSED(key);
21
22
6.56k
    if (json_segment_is_backup(val))
23
43
      continue;
24
25
6.51k
    tmp = json_segment_get_offset(val, blockwise);
26
27
6.51k
    if (!tmp)
28
3.29k
      return tmp;
29
30
3.22k
    if (tmp < min)
31
3.16k
      min = tmp;
32
3.22k
  }
33
34
3.14k
  return min;
35
6.44k
}
36
37
uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise)
38
13.1k
{
39
13.1k
  json_object *jobj;
40
41
13.1k
  if (!jobj_segment ||
42
13.1k
      !json_object_object_get_ex(jobj_segment, "offset", &jobj))
43
0
    return 0;
44
45
13.1k
  return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj);
46
13.1k
}
47
48
const char *json_segment_type(json_object *jobj_segment)
49
8
{
50
8
  json_object *jobj;
51
52
8
  if (!jobj_segment ||
53
8
      !json_object_object_get_ex(jobj_segment, "type", &jobj))
54
0
    return NULL;
55
56
8
  return json_object_get_string(jobj);
57
8
}
58
59
uint64_t json_segment_get_iv_offset(json_object *jobj_segment)
60
0
{
61
0
  json_object *jobj;
62
63
0
  if (!jobj_segment ||
64
0
      !json_object_object_get_ex(jobj_segment, "iv_tweak", &jobj))
65
0
    return 0;
66
67
0
  return crypt_jobj_get_uint64(jobj);
68
0
}
69
70
uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise)
71
6.67k
{
72
6.67k
  json_object *jobj;
73
74
6.67k
  if (!jobj_segment ||
75
6.67k
      !json_object_object_get_ex(jobj_segment, "size", &jobj))
76
0
    return 0;
77
78
6.67k
  return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj);
79
6.67k
}
80
81
static uint64_t json_segment_get_opal_size(json_object *jobj_segment, unsigned blockwise)
82
0
{
83
0
  json_object *jobj;
84
85
0
  if (!jobj_segment ||
86
0
      !json_object_object_get_ex(jobj_segment, "opal_segment_size", &jobj))
87
0
    return 0;
88
89
0
  return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj);
90
0
}
91
92
static bool json_segment_set_size(json_object *jobj_segment, const uint64_t *size_bytes)
93
0
{
94
0
  json_object *jobj;
95
96
0
  if (!jobj_segment)
97
0
    return false;
98
99
0
  jobj = size_bytes ? crypt_jobj_new_uint64(*size_bytes) : json_object_new_string("dynamic");
100
0
  if (!jobj)
101
0
    return false;
102
103
0
  json_object_object_add(jobj_segment, "size", jobj);
104
105
0
  return true;
106
0
}
107
108
const char *json_segment_get_cipher(json_object *jobj_segment)
109
0
{
110
0
  json_object *jobj;
111
112
  /* FIXME: Pseudo "null" cipher should be handled elsewhere */
113
0
  if (!jobj_segment ||
114
0
      !json_object_object_get_ex(jobj_segment, "encryption", &jobj))
115
0
    return "null";
116
117
0
  return json_object_get_string(jobj);
118
0
}
119
120
uint32_t json_segment_get_sector_size(json_object *jobj_segment)
121
2.21k
{
122
2.21k
  json_object *jobj;
123
2.21k
  int i;
124
125
2.21k
  if (!jobj_segment ||
126
2.21k
            !json_object_object_get_ex(jobj_segment, "sector_size", &jobj))
127
1.93k
    return SECTOR_SIZE;
128
129
281
  i = json_object_get_int(jobj);
130
281
  return i < 0 ? SECTOR_SIZE : i;
131
2.21k
}
132
133
int json_segment_get_opal_segment_id(json_object *jobj_segment, uint32_t *ret_opal_segment_id)
134
0
{
135
0
  json_object *jobj_segment_id;
136
137
0
  assert(ret_opal_segment_id);
138
139
0
  if (!json_object_object_get_ex(jobj_segment, "opal_segment_number", &jobj_segment_id))
140
0
    return -EINVAL;
141
142
0
  *ret_opal_segment_id = json_object_get_int(jobj_segment_id);
143
144
0
  return 0;
145
0
}
146
147
int json_segment_get_opal_key_size(json_object *jobj_segment, size_t *ret_key_size)
148
0
{
149
0
  json_object *jobj_key_size;
150
151
0
  assert(ret_key_size);
152
153
0
  if (!jobj_segment)
154
0
    return -EINVAL;
155
156
0
  if (!json_object_object_get_ex(jobj_segment, "opal_key_size", &jobj_key_size))
157
0
    return -EINVAL;
158
159
0
  *ret_key_size = json_object_get_int(jobj_key_size);
160
161
0
  return 0;
162
0
}
163
164
static json_object *json_segment_get_flags(json_object *jobj_segment)
165
15.6k
{
166
15.6k
  json_object *jobj;
167
168
15.6k
  if (!jobj_segment || !(json_object_object_get_ex(jobj_segment, "flags", &jobj)))
169
1.80k
    return NULL;
170
13.8k
  return jobj;
171
15.6k
}
172
173
bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len)
174
15.6k
{
175
15.6k
  int r, i;
176
15.6k
  json_object *jobj, *jobj_flags = json_segment_get_flags(jobj_segment);
177
178
15.6k
  if (!jobj_flags)
179
1.80k
    return false;
180
181
38.5k
  for (i = 0; i < (int)json_object_array_length(jobj_flags); i++) {
182
24.8k
    jobj = json_object_array_get_idx(jobj_flags, i);
183
24.8k
    if (len)
184
24.4k
      r = strncmp(json_object_get_string(jobj), flag_str, len);
185
418
    else
186
418
      r = strcmp(json_object_get_string(jobj), flag_str);
187
24.8k
    if (!r)
188
176
      return true;
189
24.8k
  }
190
191
13.6k
  return false;
192
13.8k
}
193
194
bool json_segment_is_backup(json_object *jobj_segment)
195
15.6k
{
196
15.6k
  return json_segment_contains_flag(jobj_segment, "backup-", 7);
197
15.6k
}
198
199
json_object *json_segments_get_segment(json_object *jobj_segments, int segment)
200
8.98k
{
201
8.98k
  json_object *jobj;
202
8.98k
  char segment_name[16];
203
204
8.98k
  if (snprintf(segment_name, sizeof(segment_name), "%u", segment) < 1)
205
0
    return NULL;
206
207
8.98k
  if (!json_object_object_get_ex(jobj_segments, segment_name, &jobj))
208
14
    return NULL;
209
210
8.97k
  return jobj;
211
8.98k
}
212
213
unsigned json_segments_count(json_object *jobj_segments)
214
2.21k
{
215
2.21k
  unsigned count = 0;
216
217
2.21k
  if (!jobj_segments)
218
0
    return 0;
219
220
2.25k
  json_object_object_foreach(jobj_segments, slot, val) {
221
2.25k
    UNUSED(slot);
222
2.25k
    if (!json_segment_is_backup(val))
223
2.23k
      count++;
224
2.25k
  }
225
226
2.21k
  return count;
227
2.21k
}
228
229
void json_segment_remove_flag(json_object *jobj_segment, const char *flag)
230
0
{
231
0
  json_object *jobj_flags, *jobj_flags_new;
232
233
0
  if (!jobj_segment)
234
0
    return;
235
236
0
  jobj_flags = json_segment_get_flags(jobj_segment);
237
0
  if (!jobj_flags)
238
0
    return;
239
240
0
  jobj_flags_new = LUKS2_array_remove(jobj_flags, flag);
241
0
  if (!jobj_flags_new)
242
0
    return;
243
244
0
  if (json_object_array_length(jobj_flags_new) <= 0) {
245
0
    json_object_put(jobj_flags_new);
246
0
    json_object_object_del(jobj_segment, "flags");
247
0
  } else
248
0
    json_object_object_add(jobj_segment, "flags", jobj_flags_new);
249
0
}
250
251
static json_object *_segment_create_generic(const char *type, uint64_t offset, const uint64_t *length)
252
0
{
253
0
  json_object *jobj = json_object_new_object();
254
0
  if (!jobj)
255
0
    return NULL;
256
257
0
  json_object_object_add(jobj, "type",    json_object_new_string(type));
258
0
  json_object_object_add(jobj, "offset",    crypt_jobj_new_uint64(offset));
259
0
  json_object_object_add(jobj, "size",    length ? crypt_jobj_new_uint64(*length) : json_object_new_string("dynamic"));
260
261
0
  return jobj;
262
0
}
263
264
json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption)
265
0
{
266
0
  json_object *jobj = _segment_create_generic("linear", offset, length);
267
0
  if (reencryption)
268
0
    LUKS2_segment_set_flag(jobj, "in-reencryption");
269
0
  return jobj;
270
0
}
271
272
static bool json_add_crypt_fields(json_object *jobj_segment, uint64_t iv_offset,
273
          const char *cipher, const char *integrity, uint32_t integrity_key_size,
274
          uint32_t sector_size, unsigned reencryption)
275
0
{
276
0
  json_object *jobj_integrity;
277
278
0
  assert(cipher);
279
280
0
  json_object_object_add(jobj_segment, "iv_tweak",    crypt_jobj_new_uint64(iv_offset));
281
0
  json_object_object_add(jobj_segment, "encryption",  json_object_new_string(cipher));
282
0
  json_object_object_add(jobj_segment, "sector_size", json_object_new_int(sector_size));
283
284
0
  if (integrity) {
285
0
    jobj_integrity = json_object_new_object();
286
0
    if (!jobj_integrity)
287
0
      return false;
288
289
0
    json_object_object_add(jobj_integrity, "type", json_object_new_string(integrity));
290
0
    json_object_object_add(jobj_integrity, "journal_encryption", json_object_new_string("none"));
291
0
    json_object_object_add(jobj_integrity, "journal_integrity", json_object_new_string("none"));
292
0
    if (integrity_key_size)
293
0
      json_object_object_add(jobj_integrity, "key_size", json_object_new_int(integrity_key_size));
294
0
    json_object_object_add(jobj_segment,   "integrity", jobj_integrity);
295
0
  }
296
297
0
  if (reencryption)
298
0
    LUKS2_segment_set_flag(jobj_segment, "in-reencryption");
299
300
0
  return true;
301
0
}
302
303
json_object *json_segment_create_crypt(uint64_t offset,
304
          uint64_t iv_offset, const uint64_t *length,
305
          const char *cipher, const char *integrity, uint32_t integrity_key_size,
306
          uint32_t sector_size, unsigned reencryption)
307
0
{
308
0
  json_object *jobj = _segment_create_generic("crypt", offset, length);
309
310
0
  if (!jobj)
311
0
    return NULL;
312
313
0
  if (json_add_crypt_fields(jobj, iv_offset, cipher, integrity, integrity_key_size, sector_size, reencryption))
314
0
    return jobj;
315
316
0
  json_object_put(jobj);
317
0
  return NULL;
318
0
}
319
320
static void json_add_opal_fields(json_object *jobj_segment, const uint64_t *length,
321
         uint32_t segment_number, uint32_t key_size)
322
0
{
323
0
  assert(jobj_segment);
324
0
  assert(length);
325
326
0
  json_object_object_add(jobj_segment, "opal_segment_number", json_object_new_int(segment_number));
327
0
  json_object_object_add(jobj_segment, "opal_key_size", json_object_new_int(key_size));
328
0
  json_object_object_add(jobj_segment, "opal_segment_size", crypt_jobj_new_uint64(*length));
329
0
}
330
331
json_object *json_segment_create_opal(uint64_t offset, const uint64_t *length,
332
              uint32_t segment_number, uint32_t key_size)
333
0
{
334
0
  json_object *jobj = _segment_create_generic("hw-opal", offset, length);
335
0
  if (!jobj)
336
0
    return NULL;
337
338
0
  json_add_opal_fields(jobj, length, segment_number, key_size);
339
340
0
  return jobj;
341
0
}
342
343
json_object *json_segment_create_opal_crypt(uint64_t offset, const uint64_t *length,
344
              uint32_t segment_number, uint32_t key_size,
345
              uint64_t iv_offset, const char *cipher,
346
              const char *integrity, uint32_t sector_size,
347
              unsigned reencryption)
348
0
{
349
0
  json_object *jobj = _segment_create_generic("hw-opal-crypt", offset, length);
350
0
  if (!jobj)
351
0
    return NULL;
352
353
0
  json_add_opal_fields(jobj, length, segment_number, key_size);
354
355
0
  if (json_add_crypt_fields(jobj, iv_offset, cipher, integrity, 0, sector_size, reencryption))
356
0
    return jobj;
357
358
0
  json_object_put(jobj);
359
0
  return NULL;
360
0
}
361
362
uint64_t LUKS2_segment_offset(struct luks2_hdr *hdr, int segment, unsigned blockwise)
363
0
{
364
0
  return json_segment_get_offset(LUKS2_get_segment_jobj(hdr, segment), blockwise);
365
0
}
366
367
int json_segments_segment_in_reencrypt(json_object *jobj_segments)
368
0
{
369
0
  json_object *jobj_flags;
370
0
  int s;
371
372
0
  json_object_object_foreach(jobj_segments, slot, val) {
373
0
    if (!json_object_object_get_ex(val, "flags", &jobj_flags) ||
374
0
        !LUKS2_array_jobj(jobj_flags, "in-reencryption"))
375
0
      continue;
376
377
0
    return crypt_str_to_int(slot, &s) < 0 ? -EINVAL : s;
378
0
  }
379
380
0
  return -1;
381
0
}
382
383
uint64_t LUKS2_segment_size(struct luks2_hdr *hdr, int segment, unsigned blockwise)
384
0
{
385
0
  return json_segment_get_size(LUKS2_get_segment_jobj(hdr, segment), blockwise);
386
0
}
387
388
uint64_t LUKS2_opal_segment_size(struct luks2_hdr *hdr, int segment, unsigned blockwise)
389
0
{
390
0
  return json_segment_get_opal_size(LUKS2_get_segment_jobj(hdr, segment), blockwise);
391
0
}
392
393
bool LUKS2_segment_set_size(struct luks2_hdr *hdr, int segment, const uint64_t *segment_size_bytes)
394
0
{
395
0
  return json_segment_set_size(LUKS2_get_segment_jobj(hdr, segment), segment_size_bytes);
396
0
}
397
398
int LUKS2_segment_is_type(struct luks2_hdr *hdr, int segment, const char *type)
399
0
{
400
0
  return !strcmp(json_segment_type(LUKS2_get_segment_jobj(hdr, segment)) ?: "", type);
401
0
}
402
403
static bool json_segment_is_hw_opal_only(json_object *jobj_segment)
404
0
{
405
0
  const char *type = json_segment_type(jobj_segment);
406
407
0
  if (!type)
408
0
    return false;
409
410
0
  return !strcmp(type, "hw-opal");
411
0
}
412
413
static bool json_segment_is_hw_opal_crypt(json_object *jobj_segment)
414
0
{
415
0
  const char *type = json_segment_type(jobj_segment);
416
417
0
  if (!type)
418
0
    return false;
419
420
0
  return !strcmp(type, "hw-opal-crypt");
421
0
}
422
423
static bool json_segment_is_hw_opal(json_object *jobj_segment)
424
0
{
425
0
  return json_segment_is_hw_opal_crypt(jobj_segment) ||
426
0
         json_segment_is_hw_opal_only(jobj_segment);
427
0
}
428
429
bool LUKS2_segment_is_hw_opal_only(struct luks2_hdr *hdr, int segment)
430
0
{
431
0
  return json_segment_is_hw_opal_only(LUKS2_get_segment_jobj(hdr, segment));
432
0
}
433
434
bool LUKS2_segment_is_hw_opal_crypt(struct luks2_hdr *hdr, int segment)
435
0
{
436
0
  return json_segment_is_hw_opal_crypt(LUKS2_get_segment_jobj(hdr, segment));
437
0
}
438
439
bool LUKS2_segment_is_hw_opal(struct luks2_hdr *hdr, int segment)
440
0
{
441
0
  return json_segment_is_hw_opal(LUKS2_get_segment_jobj(hdr, segment));
442
0
}
443
444
int LUKS2_get_opal_segment_number(struct luks2_hdr *hdr, int segment, uint32_t *ret_opal_segment_number)
445
0
{
446
0
  json_object *jobj_segment = LUKS2_get_segment_jobj(hdr, segment);
447
448
0
  assert(ret_opal_segment_number);
449
450
0
  if (!json_segment_is_hw_opal(jobj_segment))
451
0
    return -ENOENT;
452
453
0
  return json_segment_get_opal_segment_id(jobj_segment, ret_opal_segment_number);
454
0
}
455
456
int LUKS2_get_opal_key_size(struct luks2_hdr *hdr, int segment)
457
0
{
458
0
  size_t key_size = 0;
459
0
  json_object *jobj_segment = LUKS2_get_segment_jobj(hdr, segment);
460
461
0
  if (json_segment_get_opal_key_size(jobj_segment, &key_size) < 0)
462
0
    return 0;
463
464
0
  return key_size;
465
0
}
466
467
int LUKS2_last_segment_by_type(struct luks2_hdr *hdr, const char *type)
468
0
{
469
0
  json_object *jobj_segments;
470
0
  int last_found = -1, s;
471
472
0
  if (!type)
473
0
    return -1;
474
475
0
  if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments))
476
0
    return -1;
477
478
0
  json_object_object_foreach(jobj_segments, slot, val) {
479
0
    if (json_segment_is_backup(val))
480
0
      continue;
481
0
    if (strcmp(type, json_segment_type(val) ?: ""))
482
0
      continue;
483
484
0
    if (crypt_str_to_int(slot, &s) == 0 && s > last_found)
485
0
      last_found = s;
486
0
  }
487
488
0
  return last_found;
489
0
}
490
491
int LUKS2_segment_by_type(struct luks2_hdr *hdr, const char *type)
492
0
{
493
0
  json_object *jobj_segments;
494
0
  int first_found = -1, s;
495
496
0
  if (!type)
497
0
    return -EINVAL;
498
499
0
  if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments))
500
0
    return -EINVAL;
501
502
0
  json_object_object_foreach(jobj_segments, slot, val) {
503
0
    if (json_segment_is_backup(val))
504
0
      continue;
505
0
    if (strcmp(type, json_segment_type(val) ?: ""))
506
0
      continue;
507
508
0
    if (crypt_str_to_int(slot, &s) == 0 && (first_found < 0 || s < first_found))
509
0
      first_found = s;
510
0
  }
511
512
0
  return first_found;
513
0
}
514
515
int LUKS2_segment_first_unused_id(struct luks2_hdr *hdr)
516
0
{
517
0
  json_object *jobj_segments;
518
519
0
  if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments))
520
0
    return -EINVAL;
521
522
0
  return json_object_object_length(jobj_segments);
523
0
}
524
525
int LUKS2_segment_set_flag(json_object *jobj_segment, const char *flag)
526
0
{
527
0
  json_object *jobj_flags;
528
529
0
  if (!jobj_segment || !flag)
530
0
    return -EINVAL;
531
532
0
  if (!json_object_object_get_ex(jobj_segment, "flags", &jobj_flags)) {
533
0
    jobj_flags = json_object_new_array();
534
0
    if (!jobj_flags)
535
0
      return -ENOMEM;
536
0
    json_object_object_add(jobj_segment, "flags", jobj_flags);
537
0
  }
538
539
0
  if (LUKS2_array_jobj(jobj_flags, flag))
540
0
    return 0;
541
542
0
  json_object_array_add(jobj_flags, json_object_new_string(flag));
543
544
0
  return 0;
545
0
}
546
547
int LUKS2_segments_set(struct crypt_device *cd, struct luks2_hdr *hdr,
548
           json_object *jobj_segments, int commit)
549
0
{
550
0
  json_object_object_add(hdr->jobj, "segments", jobj_segments);
551
552
0
  return commit ? LUKS2_hdr_write(cd, hdr) : 0;
553
0
}
554
555
int LUKS2_get_segment_id_by_flag(struct luks2_hdr *hdr, const char *flag)
556
2.21k
{
557
2.21k
  json_object *jobj_flags, *jobj_segments = LUKS2_get_segments_jobj(hdr);
558
2.21k
  int s;
559
560
2.21k
  if (!flag || !jobj_segments)
561
0
    return -ENOENT;
562
563
2.25k
  json_object_object_foreach(jobj_segments, key, value) {
564
2.25k
    if (!json_object_object_get_ex(value, "flags", &jobj_flags))
565
320
      continue;
566
1.93k
    if (LUKS2_array_jobj(jobj_flags, flag))
567
1
      return crypt_str_to_int(key, &s) < 0 ? -EINVAL : s;
568
1.93k
  }
569
570
2.21k
  return -ENOENT;
571
2.21k
}
572
573
json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag)
574
0
{
575
0
  json_object *jobj_flags, *jobj_segments = LUKS2_get_segments_jobj(hdr);
576
577
0
  if (!flag || !jobj_segments)
578
0
    return NULL;
579
580
0
  json_object_object_foreach(jobj_segments, key, value) {
581
0
    UNUSED(key);
582
0
    if (!json_object_object_get_ex(value, "flags", &jobj_flags))
583
0
      continue;
584
0
    if (LUKS2_array_jobj(jobj_flags, flag))
585
0
      return value;
586
0
  }
587
588
0
  return NULL;
589
0
}
590
591
/* compares key characteristics of both segments */
592
bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2)
593
4
{
594
4
  const char *type = json_segment_type(jobj_segment_1);
595
4
  const char *type2 = json_segment_type(jobj_segment_2);
596
597
4
  if (!type || !type2)
598
0
    return false;
599
600
4
  if (strcmp(type, type2))
601
4
    return false;
602
603
0
  if (!strcmp(type, "crypt"))
604
0
    return (json_segment_get_sector_size(jobj_segment_1) == json_segment_get_sector_size(jobj_segment_2) &&
605
0
      !strcmp(json_segment_get_cipher(jobj_segment_1),
606
0
              json_segment_get_cipher(jobj_segment_2)));
607
608
0
  return true;
609
0
}
610
611
bool LUKS2_segments_dynamic_size(struct luks2_hdr *hdr)
612
0
{
613
0
  json_object *jobj_segments, *jobj_size;
614
615
0
  assert(hdr);
616
617
0
  jobj_segments = LUKS2_get_segments_jobj(hdr);
618
0
  if (!jobj_segments)
619
0
    return false;
620
621
0
  json_object_object_foreach(jobj_segments, key, val) {
622
0
    UNUSED(key);
623
624
0
    if (json_segment_is_backup(val))
625
0
      continue;
626
627
0
    if (json_object_object_get_ex(val, "size", &jobj_size) &&
628
0
        !strcmp(json_object_get_string(jobj_size), "dynamic"))
629
0
      return true;
630
0
  }
631
632
0
  return false;
633
0
}