Bug Summary

File:src/usr.bin/openssl/certhash.c
Warning:line 621, column 15
Access to field 'filename' results in a dereference of a null pointer (loaded from field 'reference')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name certhash.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/openssl/obj -resource-dir /usr/local/lib/clang/13.0.0 -D LIBRESSL_INTERNAL -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/openssl/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/openssl/certhash.c
1/* $OpenBSD: certhash.c,v 1.19 2021/10/23 08:13:48 tb Exp $ */
2/*
3 * Copyright (c) 2014, 2015 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/types.h>
19#include <sys/stat.h>
20
21#include <errno(*__errno()).h>
22#include <dirent.h>
23#include <fcntl.h>
24#include <limits.h>
25#include <stdio.h>
26#include <string.h>
27#include <unistd.h>
28
29#include <openssl/bio.h>
30#include <openssl/evp.h>
31#include <openssl/pem.h>
32#include <openssl/x509.h>
33
34#include "apps.h"
35
36static struct {
37 int dryrun;
38 int verbose;
39} certhash_config;
40
41static const struct option certhash_options[] = {
42 {
43 .name = "n",
44 .desc = "Perform a dry-run - do not make any changes",
45 .type = OPTION_FLAG,
46 .opt.flag = &certhash_config.dryrun,
47 },
48 {
49 .name = "v",
50 .desc = "Verbose",
51 .type = OPTION_FLAG,
52 .opt.flag = &certhash_config.verbose,
53 },
54 { NULL((void*)0) },
55};
56
57struct hashinfo {
58 char *filename;
59 char *target;
60 unsigned long hash;
61 unsigned int index;
62 unsigned char fingerprint[EVP_MAX_MD_SIZE64];
63 int is_crl;
64 int is_dup;
65 int exists;
66 int changed;
67 struct hashinfo *reference;
68 struct hashinfo *next;
69};
70
71static struct hashinfo *
72hashinfo(const char *filename, unsigned long hash, unsigned char *fingerprint)
73{
74 struct hashinfo *hi;
75
76 if ((hi = calloc(1, sizeof(*hi))) == NULL((void*)0))
77 return (NULL((void*)0));
78 if (filename != NULL((void*)0)) {
79 if ((hi->filename = strdup(filename)) == NULL((void*)0)) {
80 free(hi);
81 return (NULL((void*)0));
82 }
83 }
84 hi->hash = hash;
85 if (fingerprint != NULL((void*)0))
86 memcpy(hi->fingerprint, fingerprint, sizeof(hi->fingerprint));
87
88 return (hi);
89}
90
91static void
92hashinfo_free(struct hashinfo *hi)
93{
94 if (hi == NULL((void*)0))
95 return;
96
97 free(hi->filename);
98 free(hi->target);
99 free(hi);
100}
101
102#ifdef DEBUG
103static void
104hashinfo_print(struct hashinfo *hi)
105{
106 int i;
107
108 printf("hashinfo %s %08lx %u %i\n", hi->filename, hi->hash,
109 hi->index, hi->is_crl);
110 for (i = 0; i < (int)EVP_MAX_MD_SIZE64; i++) {
111 printf("%02X%c", hi->fingerprint[i],
112 (i + 1 == (int)EVP_MAX_MD_SIZE64) ? '\n' : ':');
113 }
114}
115#endif
116
117static int
118hashinfo_compare(const void *a, const void *b)
119{
120 struct hashinfo *hia = *(struct hashinfo **)a;
121 struct hashinfo *hib = *(struct hashinfo **)b;
122 int rv;
123
124 rv = hia->hash < hib->hash ? -1 : hia->hash > hib->hash;
125 if (rv != 0)
126 return (rv);
127 rv = memcmp(hia->fingerprint, hib->fingerprint,
128 sizeof(hia->fingerprint));
129 if (rv != 0)
130 return (rv);
131 return strcmp(hia->filename, hib->filename);
132}
133
134static struct hashinfo *
135hashinfo_chain(struct hashinfo *head, struct hashinfo *entry)
136{
137 struct hashinfo *hi = head;
138
139 if (hi == NULL((void*)0))
140 return (entry);
141 while (hi->next != NULL((void*)0))
142 hi = hi->next;
143 hi->next = entry;
144
145 return (head);
146}
147
148static void
149hashinfo_chain_free(struct hashinfo *hi)
150{
151 struct hashinfo *next;
152
153 while (hi != NULL((void*)0)) {
154 next = hi->next;
155 hashinfo_free(hi);
156 hi = next;
157 }
158}
159
160static size_t
161hashinfo_chain_length(struct hashinfo *hi)
162{
163 int len = 0;
164
165 while (hi != NULL((void*)0)) {
166 len++;
167 hi = hi->next;
168 }
169 return (len);
170}
171
172static int
173hashinfo_chain_sort(struct hashinfo **head)
174{
175 struct hashinfo **list, *entry;
176 size_t len;
177 int i;
178
179 if (*head == NULL((void*)0))
180 return (0);
181
182 len = hashinfo_chain_length(*head);
183 if ((list = reallocarray(NULL((void*)0), len, sizeof(struct hashinfo *))) == NULL((void*)0))
184 return (-1);
185
186 for (entry = *head, i = 0; entry != NULL((void*)0); entry = entry->next, i++)
187 list[i] = entry;
188 qsort(list, len, sizeof(struct hashinfo *), hashinfo_compare);
189
190 *head = entry = list[0];
191 for (i = 1; i < len; i++) {
192 entry->next = list[i];
193 entry = list[i];
194 }
195 entry->next = NULL((void*)0);
196
197 free(list);
198 return (0);
199}
200
201static char *
202hashinfo_linkname(struct hashinfo *hi)
203{
204 char *filename;
205
206 if (asprintf(&filename, "%08lx.%s%u", hi->hash,
207 (hi->is_crl ? "r" : ""), hi->index) == -1)
208 return (NULL((void*)0));
209
210 return (filename);
211}
212
213static int
214filename_is_hash(const char *filename)
215{
216 const char *p = filename;
217
218 while ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f'))
219 p++;
220 if (*p++ != '.')
221 return (0);
222 if (*p == 'r') /* CRL format. */
223 p++;
224 while (*p >= '0' && *p <= '9')
225 p++;
226 if (*p != '\0')
227 return (0);
228
229 return (1);
230}
231
232static int
233filename_is_pem(const char *filename)
234{
235 const char *q, *p = filename;
236
237 if ((q = strchr(p, '\0')) == NULL((void*)0))
238 return (0);
239 if ((q - p) < 4)
240 return (0);
241 if (strncmp((q - 4), ".pem", 4) != 0)
242 return (0);
243
244 return (1);
245}
246
247static struct hashinfo *
248hashinfo_from_linkname(const char *linkname, const char *target)
249{
250 struct hashinfo *hi = NULL((void*)0);
251 const char *errstr;
252 char *l, *p, *ep;
253 long long val;
254
255 if ((l = strdup(linkname)) == NULL((void*)0))
256 goto err;
257 if ((p = strchr(l, '.')) == NULL((void*)0))
258 goto err;
259 *p++ = '\0';
260
261 if ((hi = hashinfo(linkname, 0, NULL((void*)0))) == NULL((void*)0))
262 goto err;
263 if ((hi->target = strdup(target)) == NULL((void*)0))
264 goto err;
265
266 errno(*__errno()) = 0;
267 val = strtoll(l, &ep, 16);
268 if (l[0] == '\0' || *ep != '\0')
269 goto err;
270 if (errno(*__errno()) == ERANGE34 && (val == LLONG_MAX9223372036854775807LL || val == LLONG_MIN(-9223372036854775807LL -1LL)))
271 goto err;
272 if (val < 0 || val > ULONG_MAX(9223372036854775807L *2UL+1UL))
273 goto err;
274 hi->hash = (unsigned long)val;
275
276 if (*p == 'r') {
277 hi->is_crl = 1;
278 p++;
279 }
280
281 val = strtonum(p, 0, 0xffffffff, &errstr);
282 if (errstr != NULL((void*)0))
283 goto err;
284
285 hi->index = (unsigned int)val;
286
287 goto done;
288
289 err:
290 hashinfo_free(hi);
291 hi = NULL((void*)0);
292
293 done:
294 free(l);
295
296 return (hi);
297}
298
299static struct hashinfo *
300certhash_cert(BIO *bio, const char *filename)
301{
302 unsigned char fingerprint[EVP_MAX_MD_SIZE64];
303 struct hashinfo *hi = NULL((void*)0);
304 const EVP_MD *digest;
305 X509 *cert = NULL((void*)0);
306 unsigned long hash;
307 unsigned int len;
308
309 if ((cert = PEM_read_bio_X509(bio, NULL((void*)0), NULL((void*)0), NULL((void*)0))) == NULL((void*)0))
310 goto err;
311
312 hash = X509_subject_name_hash(cert);
313
314 digest = EVP_sha256();
315 if (X509_digest(cert, digest, fingerprint, &len) != 1) {
316 fprintf(stderr(&__sF[2]), "out of memory\n");
317 goto err;
318 }
319
320 hi = hashinfo(filename, hash, fingerprint);
321
322 err:
323 X509_free(cert);
324
325 return (hi);
326}
327
328static struct hashinfo *
329certhash_crl(BIO *bio, const char *filename)
330{
331 unsigned char fingerprint[EVP_MAX_MD_SIZE64];
332 struct hashinfo *hi = NULL((void*)0);
333 const EVP_MD *digest;
334 X509_CRL *crl = NULL((void*)0);
335 unsigned long hash;
336 unsigned int len;
337
338 if ((crl = PEM_read_bio_X509_CRL(bio, NULL((void*)0), NULL((void*)0), NULL((void*)0))) == NULL((void*)0))
339 return (NULL((void*)0));
340
341 hash = X509_NAME_hash(X509_CRL_get_issuer(crl));
342
343 digest = EVP_sha256();
344 if (X509_CRL_digest(crl, digest, fingerprint, &len) != 1) {
345 fprintf(stderr(&__sF[2]), "out of memory\n");
346 goto err;
347 }
348
349 hi = hashinfo(filename, hash, fingerprint);
350
351 err:
352 X509_CRL_free(crl);
353
354 return (hi);
355}
356
357static int
358certhash_addlink(struct hashinfo **links, struct hashinfo *hi)
359{
360 struct hashinfo *link = NULL((void*)0);
361
362 if ((link = hashinfo(NULL((void*)0), hi->hash, hi->fingerprint)) == NULL((void*)0))
363 goto err;
364
365 if ((link->filename = hashinfo_linkname(hi)) == NULL((void*)0))
366 goto err;
367
368 link->reference = hi;
369 link->changed = 1;
370 *links = hashinfo_chain(*links, link);
371 hi->reference = link;
372
373 return (0);
374
375 err:
376 hashinfo_free(link);
377 return (-1);
378}
379
380static void
381certhash_findlink(struct hashinfo *links, struct hashinfo *hi)
382{
383 struct hashinfo *link;
384
385 for (link = links; link != NULL((void*)0); link = link->next) {
386 if (link->is_crl == hi->is_crl &&
387 link->hash == hi->hash &&
388 link->index == hi->index &&
389 link->reference == NULL((void*)0)) {
390 link->reference = hi;
391 if (link->target == NULL((void*)0) ||
392 strcmp(link->target, hi->filename) != 0)
393 link->changed = 1;
394 hi->reference = link;
395 break;
396 }
397 }
398}
399
400static void
401certhash_index(struct hashinfo *head, const char *name)
402{
403 struct hashinfo *last, *entry;
404 int index = 0;
405
406 last = NULL((void*)0);
407 for (entry = head; entry != NULL((void*)0); entry = entry->next) {
408 if (last != NULL((void*)0)) {
409 if (entry->hash == last->hash) {
410 if (memcmp(entry->fingerprint,
411 last->fingerprint,
412 sizeof(entry->fingerprint)) == 0) {
413 fprintf(stderr(&__sF[2]), "WARNING: duplicate %s "
414 "in %s (using %s), ignoring...\n",
415 name, entry->filename,
416 last->filename);
417 entry->is_dup = 1;
418 continue;
419 }
420 index++;
421 } else {
422 index = 0;
423 }
424 }
425 entry->index = index;
426 last = entry;
427 }
428}
429
430static int
431certhash_merge(struct hashinfo **links, struct hashinfo **certs,
432 struct hashinfo **crls)
433{
434 struct hashinfo *cert, *crl;
435
436 /* Pass 1 - sort and index entries. */
437 if (hashinfo_chain_sort(certs) == -1)
438 return (-1);
439 if (hashinfo_chain_sort(crls) == -1)
440 return (-1);
441 certhash_index(*certs, "certificate");
442 certhash_index(*crls, "CRL");
443
444 /* Pass 2 - map to existing links. */
445 for (cert = *certs; cert != NULL((void*)0); cert = cert->next) {
446 if (cert->is_dup == 1)
447 continue;
448 certhash_findlink(*links, cert);
449 }
450 for (crl = *crls; crl != NULL((void*)0); crl = crl->next) {
451 if (crl->is_dup == 1)
452 continue;
453 certhash_findlink(*links, crl);
454 }
455
456 /* Pass 3 - determine missing links. */
457 for (cert = *certs; cert != NULL((void*)0); cert = cert->next) {
458 if (cert->is_dup == 1 || cert->reference != NULL((void*)0))
459 continue;
460 if (certhash_addlink(links, cert) == -1)
461 return (-1);
462 }
463 for (crl = *crls; crl != NULL((void*)0); crl = crl->next) {
464 if (crl->is_dup == 1 || crl->reference != NULL((void*)0))
465 continue;
466 if (certhash_addlink(links, crl) == -1)
467 return (-1);
468 }
469
470 return (0);
471}
472
473static int
474certhash_link(struct dirent *dep, struct hashinfo **links)
475{
476 struct hashinfo *hi = NULL((void*)0);
477 char target[PATH_MAX1024];
478 struct stat sb;
479 int n;
480
481 if (lstat(dep->d_name, &sb) == -1) {
482 fprintf(stderr(&__sF[2]), "failed to stat %s\n", dep->d_name);
483 return (-1);
484 }
485 if (!S_ISLNK(sb.st_mode)((sb.st_mode & 0170000) == 0120000))
486 return (0);
487
488 n = readlink(dep->d_name, target, sizeof(target) - 1);
489 if (n == -1) {
490 fprintf(stderr(&__sF[2]), "failed to readlink %s\n", dep->d_name);
491 return (-1);
492 }
493 if (n >= sizeof(target) - 1) {
494 fprintf(stderr(&__sF[2]), "symbolic link is too long %s\n", dep->d_name);
495 return (-1);
496 }
497 target[n] = '\0';
498
499 hi = hashinfo_from_linkname(dep->d_name, target);
500 if (hi == NULL((void*)0)) {
501 fprintf(stderr(&__sF[2]), "failed to get hash info %s\n", dep->d_name);
502 return (-1);
503 }
504 hi->exists = 1;
505 *links = hashinfo_chain(*links, hi);
506
507 return (0);
508}
509
510static int
511certhash_file(struct dirent *dep, struct hashinfo **certs,
512 struct hashinfo **crls)
513{
514 struct hashinfo *hi = NULL((void*)0);
515 int has_cert, has_crl;
516 int ret = -1;
517 BIO *bio = NULL((void*)0);
518 FILE *f;
519
520 has_cert = has_crl = 0;
521
522 if ((f = fopen(dep->d_name, "r")) == NULL((void*)0)) {
523 fprintf(stderr(&__sF[2]), "failed to fopen %s\n", dep->d_name);
524 goto err;
525 }
526 if ((bio = BIO_new_fp(f, BIO_CLOSE0x01)) == NULL((void*)0)) {
527 fprintf(stderr(&__sF[2]), "failed to create bio\n");
528 fclose(f);
529 goto err;
530 }
531
532 if ((hi = certhash_cert(bio, dep->d_name)) != NULL((void*)0)) {
533 has_cert = 1;
534 *certs = hashinfo_chain(*certs, hi);
535 }
536
537 if (BIO_reset(bio)(int)BIO_ctrl(bio,1,0,((void*)0)) != 0) {
538 fprintf(stderr(&__sF[2]), "BIO_reset failed\n");
539 goto err;
540 }
541
542 if ((hi = certhash_crl(bio, dep->d_name)) != NULL((void*)0)) {
543 has_crl = hi->is_crl = 1;
544 *crls = hashinfo_chain(*crls, hi);
545 }
546
547 if (!has_cert && !has_crl)
548 fprintf(stderr(&__sF[2]), "PEM file %s does not contain a certificate "
549 "or CRL, ignoring...\n", dep->d_name);
550
551 ret = 0;
552
553 err:
554 BIO_free(bio);
555
556 return (ret);
557}
558
559static int
560certhash_directory(const char *path)
561{
562 struct hashinfo *links = NULL((void*)0), *certs = NULL((void*)0), *crls = NULL((void*)0), *link;
563 int ret = 0;
564 struct dirent *dep;
565 DIR *dip = NULL((void*)0);
566
567 if ((dip = opendir(".")) == NULL((void*)0)) {
24
Assuming the condition is false
25
Taking false branch
568 fprintf(stderr(&__sF[2]), "failed to open directory %s\n", path);
569 goto err;
570 }
571
572 if (certhash_config.verbose
25.1
Field 'verbose' is 0
)
26
Taking false branch
573 fprintf(stdout(&__sF[1]), "scanning directory %s\n", path);
574
575 /* Create lists of existing hash links, certs and CRLs. */
576 while ((dep = readdir(dip)) != NULL((void*)0)) {
27
Assuming the condition is false
28
Loop condition is false. Execution continues on line 587
577 if (filename_is_hash(dep->d_name)) {
578 if (certhash_link(dep, &links) == -1)
579 goto err;
580 }
581 if (filename_is_pem(dep->d_name)) {
582 if (certhash_file(dep, &certs, &crls) == -1)
583 goto err;
584 }
585 }
586
587 if (certhash_merge(&links, &certs, &crls) == -1) {
29
Assuming the condition is false
30
Taking false branch
588 fprintf(stderr(&__sF[2]), "certhash merge failed\n");
589 goto err;
590 }
591
592 /* Remove spurious links. */
593 for (link = links; link != NULL((void*)0); link = link->next) {
31
Assuming 'link' is not equal to NULL
32
Loop condition is true. Entering loop body
41
Assuming 'link' is equal to NULL
42
Loop condition is false. Execution continues on line 611
594 if (link->exists == 0 ||
33
Assuming field 'exists' is not equal to 0
595 (link->reference != NULL((void*)0) && link->changed == 0))
34
Assuming field 'reference' is equal to NULL
596 continue;
597 if (certhash_config.verbose)
35
Assuming field 'verbose' is 0
36
Taking false branch
598 fprintf(stdout(&__sF[1]), "%s link %s -> %s\n",
599 (certhash_config.dryrun ? "would remove" :
600 "removing"), link->filename, link->target);
601 if (certhash_config.dryrun)
37
Assuming field 'dryrun' is 0
38
Taking false branch
602 continue;
603 if (unlink(link->filename) == -1) {
39
Assuming the condition is false
40
Taking false branch
604 fprintf(stderr(&__sF[2]), "failed to remove link %s\n",
605 link->filename);
606 goto err;
607 }
608 }
609
610 /* Create missing links. */
611 for (link = links; link
42.1
'link' is not equal to NULL
!= NULL((void*)0); link = link->next) {
43
Loop condition is true. Entering loop body
612 if (link->exists == 1 && link->changed == 0)
44
Assuming field 'exists' is not equal to 1
613 continue;
614 if (certhash_config.verbose
44.1
Field 'verbose' is 0
)
45
Taking false branch
615 fprintf(stdout(&__sF[1]), "%s link %s -> %s\n",
616 (certhash_config.dryrun ? "would create" :
617 "creating"), link->filename,
618 link->reference->filename);
619 if (certhash_config.dryrun
45.1
Field 'dryrun' is 0
)
46
Taking false branch
620 continue;
621 if (symlink(link->reference->filename, link->filename) == -1) {
47
Access to field 'filename' results in a dereference of a null pointer (loaded from field 'reference')
622 fprintf(stderr(&__sF[2]), "failed to create link %s -> %s\n",
623 link->filename, link->reference->filename);
624 goto err;
625 }
626 }
627
628 goto done;
629
630 err:
631 ret = 1;
632
633 done:
634 hashinfo_chain_free(certs);
635 hashinfo_chain_free(crls);
636 hashinfo_chain_free(links);
637
638 if (dip != NULL((void*)0))
639 closedir(dip);
640 return (ret);
641}
642
643static void
644certhash_usage(void)
645{
646 fprintf(stderr(&__sF[2]), "usage: certhash [-nv] dir ...\n");
647 options_usage(certhash_options);
648}
649
650int
651certhash_main(int argc, char **argv)
652{
653 int argsused;
654 int i, cwdfd, ret = 0;
655
656 if (single_execution) {
1
Assuming 'single_execution' is 0
2
Taking false branch
657 if (pledge("stdio cpath wpath rpath", NULL((void*)0)) == -1) {
658 perror("pledge");
659 exit(1);
660 }
661 }
662
663 memset(&certhash_config, 0, sizeof(certhash_config));
664
665 if (options_parse(argc, argv, certhash_options, NULL((void*)0), &argsused) != 0) {
3
Assuming the condition is false
4
Taking false branch
666 certhash_usage();
667 return (1);
668 }
669
670 if ((cwdfd = open(".", O_RDONLY0x0000)) == -1) {
5
Assuming the condition is false
6
Taking false branch
671 perror("failed to open current directory");
672 return (1);
673 }
674
675 for (i = argsused; i < argc; i++) {
7
Assuming 'i' is < 'argc'
8
Loop condition is true. Entering loop body
13
Assuming 'i' is < 'argc'
14
Loop condition is true. Entering loop body
19
Assuming 'i' is < 'argc'
20
Loop condition is true. Entering loop body
676 if (chdir(argv[i]) == -1) {
9
Assuming the condition is false
10
Taking false branch
15
Assuming the condition is false
16
Taking false branch
21
Assuming the condition is false
22
Taking false branch
677 fprintf(stderr(&__sF[2]),
678 "failed to change to directory %s: %s\n",
679 argv[i], strerror(errno(*__errno())));
680 ret = 1;
681 continue;
682 }
683 ret |= certhash_directory(argv[i]);
23
Calling 'certhash_directory'
684 if (fchdir(cwdfd) == -1) {
11
Assuming the condition is false
12
Taking false branch
17
Assuming the condition is false
18
Taking false branch
685 perror("failed to restore current directory");
686 ret = 1;
687 break; /* can't continue safely */
688 }
689 }
690 close(cwdfd);
691
692 return (ret);
693}