Bug Summary

File:got/../lib/fetch.c
Warning:line 708, column 11
Potential leak of memory pointed to by 'progress'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd6.9 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name fetch.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 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/local/lib/clang/11.1.0 -I /home/ben/Projects/got/got/../include -I /home/ben/Projects/got/got/../lib -D GOT_LIBEXECDIR=/home/ben/bin -D GOT_VERSION=0.53-current -internal-isystem /usr/local/lib/clang/11.1.0/include -internal-externc-isystem /usr/include -O0 -fdebug-compilation-dir /home/ben/Projects/got/got/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -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 -o /home/ben/Projects/got/scan/2021-05-28-230913-68537-1 -x c /home/ben/Projects/got/got/../lib/fetch.c
1/*
2 * Copyright (c) 2018, 2019 Ori Bernstein <ori@openbsd.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <sys/queue.h>
20#include <sys/uio.h>
21#include <sys/socket.h>
22#include <sys/wait.h>
23#include <sys/resource.h>
24#include <sys/socket.h>
25
26#include <endian.h>
27#include <errno(*__errno()).h>
28#include <err.h>
29#include <fcntl.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <stdint.h>
34#include <sha1.h>
35#include <unistd.h>
36#include <zlib.h>
37#include <ctype.h>
38#include <limits.h>
39#include <imsg.h>
40#include <time.h>
41#include <uuid.h>
42#include <netdb.h>
43#include <netinet/in.h>
44
45#include "got_error.h"
46#include "got_reference.h"
47#include "got_repository.h"
48#include "got_path.h"
49#include "got_cancel.h"
50#include "got_worktree.h"
51#include "got_object.h"
52#include "got_opentemp.h"
53#include "got_fetch.h"
54
55#include "got_lib_delta.h"
56#include "got_lib_inflate.h"
57#include "got_lib_object.h"
58#include "got_lib_object_parse.h"
59#include "got_lib_object_create.h"
60#include "got_lib_pack.h"
61#include "got_lib_sha1.h"
62#include "got_lib_privsep.h"
63#include "got_lib_object_cache.h"
64#include "got_lib_repository.h"
65
66#ifndef nitems
67#define nitems(_a)(sizeof((_a)) / sizeof((_a)[0])) (sizeof((_a)) / sizeof((_a)[0]))
68#endif
69
70#ifndef ssizeof
71#define ssizeof(_x)((ssize_t)(sizeof(_x))) ((ssize_t)(sizeof(_x)))
72#endif
73
74#ifndef MIN
75#define MIN(_a,_b)((_a) < (_b) ? (_a) : (_b)) ((_a) < (_b) ? (_a) : (_b))
76#endif
77
78static int
79hassuffix(char *base, char *suf)
80{
81 int nb, ns;
82
83 nb = strlen(base);
84 ns = strlen(suf);
85 if (ns <= nb && strcmp(base + (nb - ns), suf) == 0)
86 return 1;
87 return 0;
88}
89
90static const struct got_error *
91dial_ssh(pid_t *fetchpid, int *fetchfd, const char *host, const char *port,
92 const char *path, const char *direction, int verbosity)
93{
94 const struct got_error *error = NULL((void *)0);
95 int pid, pfd[2];
96 char cmd[64];
97 char *argv[11];
98 int i = 0, j;
99
100 *fetchpid = -1;
101 *fetchfd = -1;
102
103 argv[i++] = GOT_FETCH_PATH_SSH"/usr/bin/ssh";
104 if (port != NULL((void *)0)) {
105 argv[i++] = "-p";
106 argv[i++] = (char *)port;
107 }
108 if (verbosity == -1) {
109 argv[i++] = "-q";
110 } else {
111 /* ssh(1) allows up to 3 "-v" options. */
112 for (j = 0; j < MIN(3, verbosity)((3) < (verbosity) ? (3) : (verbosity)); j++)
113 argv[i++] = "-v";
114 }
115 argv[i++] = "--";
116 argv[i++] = (char *)host;
117 argv[i++] = (char *)cmd;
118 argv[i++] = (char *)path;
119 argv[i++] = NULL((void *)0);
120
121 if (pipe(pfd) == -1)
122 return got_error_from_errno("pipe");
123
124 pid = fork();
125 if (pid == -1) {
126 error = got_error_from_errno("fork");
127 close(pfd[0]);
128 close(pfd[1]);
129 return error;
130 } else if (pid == 0) {
131 int n;
132 if (close(pfd[1]) == -1)
133 err(1, "close");
134 if (dup2(pfd[0], 0) == -1)
135 err(1, "dup2");
136 if (dup2(pfd[0], 1) == -1)
137 err(1, "dup2");
138 n = snprintf(cmd, sizeof(cmd), "git-%s-pack", direction);
139 if (n < 0 || n >= ssizeof(cmd)((ssize_t)(sizeof(cmd))))
140 err(1, "snprintf");
141 if (execv(GOT_FETCH_PATH_SSH"/usr/bin/ssh", argv) == -1)
142 err(1, "execv");
143 abort(); /* not reached */
144 } else {
145 if (close(pfd[0]) == -1)
146 return got_error_from_errno("close");
147 *fetchpid = pid;
148 *fetchfd = pfd[1];
149 return NULL((void *)0);
150 }
151}
152
153static const struct got_error *
154dial_git(int *fetchfd, const char *host, const char *port, const char *path,
155 const char *direction)
156{
157 const struct got_error *err = NULL((void *)0);
158 struct addrinfo hints, *servinfo, *p;
159 char *cmd = NULL((void *)0), *pkt = NULL((void *)0);
160 int fd = -1, totlen, r, eaicode;
161
162 *fetchfd = -1;
163
164 if (port == NULL((void *)0))
165 port = GOT_DEFAULT_GIT_PORT_STR"9418";
166
167 memset(&hints, 0, sizeof hints);
168 hints.ai_family = AF_UNSPEC0;
169 hints.ai_socktype = SOCK_STREAM1;
170 eaicode = getaddrinfo(host, port, &hints, &servinfo);
171 if (eaicode) {
172 char msg[512];
173 snprintf(msg, sizeof(msg), "%s: %s", host,
174 gai_strerror(eaicode));
175 return got_error_msg(GOT_ERR_ADDRINFO121, msg);
176 }
177
178 for (p = servinfo; p != NULL((void *)0); p = p->ai_next) {
179 if ((fd = socket(p->ai_family, p->ai_socktype,
180 p->ai_protocol)) == -1)
181 continue;
182 if (connect(fd, p->ai_addr, p->ai_addrlen) == 0) {
183 err = NULL((void *)0);
184 break;
185 }
186 err = got_error_from_errno("connect");
187 close(fd);
188 }
189 if (p == NULL((void *)0))
190 goto done;
191
192 if (asprintf(&cmd, "git-%s-pack %s", direction, path) == -1) {
193 err = got_error_from_errno("asprintf");
194 goto done;
195 }
196 totlen = 4 + strlen(cmd) + 1 + strlen("host=") + strlen(host) + 1;
197 if (asprintf(&pkt, "%04x%s", totlen, cmd) == -1) {
198 err = got_error_from_errno("asprintf");
199 goto done;
200 }
201 r = write(fd, pkt, strlen(pkt) + 1);
202 if (r == -1) {
203 err = got_error_from_errno("write");
204 goto done;
205 }
206 if (asprintf(&pkt, "host=%s", host) == -1) {
207 err = got_error_from_errno("asprintf");
208 goto done;
209 }
210 r = write(fd, pkt, strlen(pkt) + 1);
211 if (r == -1) {
212 err = got_error_from_errno("write");
213 goto done;
214 }
215done:
216 free(cmd);
217 free(pkt);
218 if (err) {
219 if (fd != -1)
220 close(fd);
221 } else
222 *fetchfd = fd;
223 return err;
224}
225
226const struct got_error *
227got_fetch_connect(pid_t *fetchpid, int *fetchfd, const char *proto,
228 const char *host, const char *port, const char *server_path, int verbosity)
229{
230 const struct got_error *err = NULL((void *)0);
231
232 *fetchpid = -1;
233 *fetchfd = -1;
234
235 if (strcmp(proto, "ssh") == 0 || strcmp(proto, "git+ssh") == 0)
236 err = dial_ssh(fetchpid, fetchfd, host, port, server_path,
237 "upload", verbosity);
238 else if (strcmp(proto, "git") == 0)
239 err = dial_git(fetchfd, host, port, server_path, "upload");
240 else if (strcmp(proto, "http") == 0 || strcmp(proto, "git+http") == 0)
241 err = got_error_path(proto, GOT_ERR_NOT_IMPL18);
242 else
243 err = got_error_path(proto, GOT_ERR_BAD_PROTO120);
244 return err;
245}
246
247const struct got_error *
248got_fetch_parse_uri(char **proto, char **host, char **port,
249 char **server_path, char **repo_name, const char *uri)
250{
251 const struct got_error *err = NULL((void *)0);
252 char *s, *p, *q;
253 int n;
254
255 *proto = *host = *port = *server_path = *repo_name = NULL((void *)0);
256
257 p = strstr(uri, "://");
258 if (!p) {
259 /* Try parsing Git's "scp" style URL syntax. */
260 *proto = strdup("ssh");
261 if (proto == NULL((void *)0)) {
262 err = got_error_from_errno("strdup");
263 goto done;
264 }
265 s = (char *)uri;
266 q = strchr(s, ':');
267 if (q == NULL((void *)0)) {
268 err = got_error(GOT_ERR_PARSE_URI119);
269 goto done;
270 }
271 /* No slashes allowed before first colon. */
272 p = strchr(s, '/');
273 if (p && q > p) {
274 err = got_error(GOT_ERR_PARSE_URI119);
275 goto done;
276 }
277 *host = strndup(s, q - s);
278 if (*host == NULL((void *)0)) {
279 err = got_error_from_errno("strndup");
280 goto done;
281 }
282 p = q + 1;
283 } else {
284 *proto = strndup(uri, p - uri);
285 if (proto == NULL((void *)0)) {
286 err = got_error_from_errno("strndup");
287 goto done;
288 }
289 s = p + 3;
290
291 p = strstr(s, "/");
292 if (p == NULL((void *)0) || strlen(p) == 1) {
293 err = got_error(GOT_ERR_PARSE_URI119);
294 goto done;
295 }
296
297 q = memchr(s, ':', p - s);
298 if (q) {
299 *host = strndup(s, q - s);
300 if (*host == NULL((void *)0)) {
301 err = got_error_from_errno("strndup");
302 goto done;
303 }
304 *port = strndup(q + 1, p - (q + 1));
305 if (*port == NULL((void *)0)) {
306 err = got_error_from_errno("strndup");
307 goto done;
308 }
309 } else {
310 *host = strndup(s, p - s);
311 if (*host == NULL((void *)0)) {
312 err = got_error_from_errno("strndup");
313 goto done;
314 }
315 }
316 }
317
318 while (p[0] == '/' && p[1] == '/')
319 p++;
320 *server_path = strdup(p);
321 if (*server_path == NULL((void *)0)) {
322 err = got_error_from_errno("strdup");
323 goto done;
324 }
325 got_path_strip_trailing_slashes(*server_path);
326
327 p = strrchr(p, '/');
328 if (!p || strlen(p) <= 1) {
329 err = got_error(GOT_ERR_PARSE_URI119);
330 goto done;
331 }
332 p++;
333 n = strlen(p);
334 if (n == 0) {
335 err = got_error(GOT_ERR_PARSE_URI119);
336 goto done;
337 }
338 if (hassuffix(p, ".git"))
339 n -= 4;
340 *repo_name = strndup(p, (p + n) - p);
341 if (*repo_name == NULL((void *)0)) {
342 err = got_error_from_errno("strndup");
343 goto done;
344 }
345done:
346 if (err) {
347 free(*proto);
348 *proto = NULL((void *)0);
349 free(*host);
350 *host = NULL((void *)0);
351 free(*port);
352 *port = NULL((void *)0);
353 free(*server_path);
354 *server_path = NULL((void *)0);
355 free(*repo_name);
356 *repo_name = NULL((void *)0);
357 }
358 return err;
359}
360
361const struct got_error*
362got_fetch_pack(struct got_object_id **pack_hash, struct got_pathlist_head *refs,
363 struct got_pathlist_head *symrefs, const char *remote_name,
364 int mirror_references, int fetch_all_branches,
365 struct got_pathlist_head *wanted_branches,
366 struct got_pathlist_head *wanted_refs, int list_refs_only, int verbosity,
367 int fetchfd, struct got_repository *repo,
368 got_fetch_progress_cb progress_cb, void *progress_arg)
369{
370 size_t i;
371 int imsg_fetchfds[2], imsg_idxfds[2];
372 int packfd = -1, npackfd = -1, idxfd = -1, nidxfd = -1, nfetchfd = -1;
373 int tmpfds[3];
374 int fetchstatus, idxstatus, done = 0;
375 const struct got_error *err;
376 struct imsgbuf fetchibuf, idxibuf;
377 pid_t fetchpid, idxpid;
378 char *tmppackpath = NULL((void *)0), *tmpidxpath = NULL((void *)0);
379 char *packpath = NULL((void *)0), *idxpath = NULL((void *)0), *id_str = NULL((void *)0);
380 const char *repo_path = NULL((void *)0);
381 struct got_pathlist_head have_refs;
382 struct got_pathlist_entry *pe;
383 struct got_reflist_head my_refs;
384 struct got_reflist_entry *re;
385 off_t packfile_size = 0;
386 struct got_packfile_hdr pack_hdr;
387 uint32_t nobj = 0;
388 char *ref_prefix = NULL((void *)0);
389 size_t ref_prefixlen = 0;
390 char *path;
391 char *progress = NULL((void *)0);
392
393 *pack_hash = NULL((void *)0);
394
395 /*
396 * Prevent fetching of references that won't make any
397 * sense outside of the remote repository's context.
398 */
399 TAILQ_FOREACH(pe, wanted_refs, entry)for((pe) = ((wanted_refs)->tqh_first); (pe) != ((void *)0)
; (pe) = ((pe)->entry.tqe_next))
{
1
Assuming 'pe' is equal to null
2
Loop condition is false. Execution continues on line 408
400 const char *refname = pe->path;
401 if (strncmp(refname, "refs/got/", 9) == 0 ||
402 strncmp(refname, "got/", 4) == 0 ||
403 strncmp(refname, "refs/remotes/", 13) == 0 ||
404 strncmp(refname, "remotes/", 8) == 0)
405 return got_error_path(refname, GOT_ERR_FETCH_BAD_REF125);
406 }
407
408 if (!list_refs_only)
3
Assuming 'list_refs_only' is not equal to 0
4
Taking false branch
409 repo_path = got_repo_get_path_git_dir(repo);
410
411 for (i = 0; i < nitems(tmpfds)(sizeof((tmpfds)) / sizeof((tmpfds)[0])); i++)
5
Loop condition is true. Entering loop body
6
Loop condition is true. Entering loop body
7
Loop condition is true. Entering loop body
8
Loop condition is false. Execution continues on line 414
412 tmpfds[i] = -1;
413
414 TAILQ_INIT(&have_refs)do { (&have_refs)->tqh_first = ((void *)0); (&have_refs
)->tqh_last = &(&have_refs)->tqh_first; } while
(0)
;
9
Loop condition is false. Exiting loop
415 TAILQ_INIT(&my_refs)do { (&my_refs)->tqh_first = ((void *)0); (&my_refs
)->tqh_last = &(&my_refs)->tqh_first; } while (
0)
;
10
Loop condition is false. Exiting loop
416
417 if (!mirror_references) {
11
Assuming 'mirror_references' is not equal to 0
12
Taking false branch
418 if (asprintf(&ref_prefix, "refs/remotes/%s/",
419 remote_name) == -1)
420 return got_error_from_errno("asprintf");
421 ref_prefixlen = strlen(ref_prefix);
422 }
423
424 if (!list_refs_only
12.1
'list_refs_only' is not equal to 0
) {
13
Taking false branch
425 err = got_ref_list(&my_refs, repo, NULL((void *)0),
426 got_ref_cmp_by_name, NULL((void *)0));
427 if (err)
428 goto done;
429 }
430
431 TAILQ_FOREACH(re, &my_refs, entry)for((re) = ((&my_refs)->tqh_first); (re) != ((void *)0
); (re) = ((re)->entry.tqe_next))
{
14
Loop condition is false. Execution continues on line 494
432 struct got_object_id *id;
433 const char *refname;
434
435 if (got_ref_is_symbolic(re->ref))
436 continue;
437
438 refname = got_ref_get_name(re->ref);
439
440 if (mirror_references) {
441 char *name;
442 err = got_ref_resolve(&id, repo, re->ref);
443 if (err)
444 goto done;
445 name = strdup(refname);
446 if (name == NULL((void *)0)) {
447 err = got_error_from_errno("strdup");
448 goto done;
449 }
450 err = got_pathlist_append(&have_refs, name, id);
451 if (err)
452 goto done;
453 continue;
454 }
455
456 if (strncmp("refs/tags/", refname, 10) == 0) {
457 char *tagname;
458
459 err = got_ref_resolve(&id, repo, re->ref);
460 if (err)
461 goto done;
462 tagname = strdup(refname);
463 if (tagname == NULL((void *)0)) {
464 err = got_error_from_errno("strdup");
465 goto done;
466 }
467 err = got_pathlist_append(&have_refs, tagname, id);
468 if (err) {
469 free(tagname);
470 goto done;
471 }
472 }
473
474 if (strncmp(ref_prefix, refname, ref_prefixlen) == 0) {
475 char *branchname;
476
477 err = got_ref_resolve(&id, repo, re->ref);
478 if (err)
479 goto done;
480
481 if (asprintf(&branchname, "refs/heads/%s",
482 refname + ref_prefixlen) == -1) {
483 err = got_error_from_errno("asprintf");
484 goto done;
485 }
486 err = got_pathlist_append(&have_refs, branchname, id);
487 if (err) {
488 free(branchname);
489 goto done;
490 }
491 }
492 }
493
494 if (list_refs_only
14.1
'list_refs_only' is not equal to 0
) {
15
Taking true branch
495 packfd = got_opentempfd();
496 if (packfd == -1) {
16
Assuming the condition is false
17
Taking false branch
497 err = got_error_from_errno("got_opentempfd");
498 goto done;
499 }
500 } else {
501 if (asprintf(&path, "%s/%s/fetching.pack",
502 repo_path, GOT_OBJECTS_PACK_DIR"objects/pack") == -1) {
503 err = got_error_from_errno("asprintf");
504 goto done;
505 }
506 err = got_opentemp_named_fd(&tmppackpath, &packfd, path);
507 free(path);
508 if (err)
509 goto done;
510 if (fchmod(packfd, GOT_DEFAULT_FILE_MODE(0100000 | 0000400|0000200 | 0000040 | 0000004)) != 0) {
511 err = got_error_from_errno2("fchmod", tmppackpath);
512 goto done;
513 }
514 }
515 if (list_refs_only
17.1
'list_refs_only' is not equal to 0
) {
18
Taking true branch
516 idxfd = got_opentempfd();
517 if (idxfd == -1) {
19
Assuming the condition is false
20
Taking false branch
518 err = got_error_from_errno("got_opentempfd");
519 goto done;
520 }
521 } else {
522 if (asprintf(&path, "%s/%s/fetching.idx",
523 repo_path, GOT_OBJECTS_PACK_DIR"objects/pack") == -1) {
524 err = got_error_from_errno("asprintf");
525 goto done;
526 }
527 err = got_opentemp_named_fd(&tmpidxpath, &idxfd, path);
528 free(path);
529 if (err)
530 goto done;
531 if (fchmod(idxfd, GOT_DEFAULT_FILE_MODE(0100000 | 0000400|0000200 | 0000040 | 0000004)) != 0) {
532 err = got_error_from_errno2("fchmod", tmpidxpath);
533 goto done;
534 }
535 }
536 nidxfd = dup(idxfd);
537 if (nidxfd == -1) {
21
Assuming the condition is false
22
Taking false branch
538 err = got_error_from_errno("dup");
539 goto done;
540 }
541
542 for (i = 0; i < nitems(tmpfds)(sizeof((tmpfds)) / sizeof((tmpfds)[0])); i++) {
23
Loop condition is true. Entering loop body
26
Loop condition is true. Entering loop body
29
Loop condition is true. Entering loop body
32
Loop condition is false. Execution continues on line 550
543 tmpfds[i] = got_opentempfd();
544 if (tmpfds[i] == -1) {
24
Assuming the condition is false
25
Taking false branch
27
Assuming the condition is false
28
Taking false branch
30
Assuming the condition is false
31
Taking false branch
545 err = got_error_from_errno("got_opentempfd");
546 goto done;
547 }
548 }
549
550 if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, imsg_fetchfds) == -1) {
33
Assuming the condition is false
34
Taking false branch
551 err = got_error_from_errno("socketpair");
552 goto done;
553 }
554
555 fetchpid = fork();
556 if (fetchpid == -1) {
35
Assuming the condition is false
36
Taking false branch
557 err = got_error_from_errno("fork");
558 goto done;
559 } else if (fetchpid == 0){
37
Assuming 'fetchpid' is not equal to 0
38
Taking false branch
560 got_privsep_exec_child(imsg_fetchfds,
561 GOT_PATH_PROG_FETCH_PACK"/home/ben/bin" "/" "got-fetch-pack", tmppackpath);
562 }
563
564 if (close(imsg_fetchfds[1]) == -1) {
39
Assuming the condition is false
40
Taking false branch
565 err = got_error_from_errno("close");
566 goto done;
567 }
568 imsg_init(&fetchibuf, imsg_fetchfds[0]);
569 nfetchfd = dup(fetchfd);
570 if (nfetchfd == -1) {
41
Assuming the condition is false
42
Taking false branch
571 err = got_error_from_errno("dup");
572 goto done;
573 }
574 err = got_privsep_send_fetch_req(&fetchibuf, nfetchfd, &have_refs,
575 fetch_all_branches, wanted_branches, wanted_refs,
576 list_refs_only, verbosity);
577 if (err != NULL((void *)0))
43
Assuming 'err' is equal to NULL
44
Taking false branch
578 goto done;
579 nfetchfd = -1;
580 npackfd = dup(packfd);
581 if (npackfd == -1) {
45
Assuming the condition is false
46
Taking false branch
582 err = got_error_from_errno("dup");
583 goto done;
584 }
585 err = got_privsep_send_fetch_outfd(&fetchibuf, npackfd);
586 if (err != NULL((void *)0))
47
Assuming 'err' is equal to NULL
48
Taking false branch
587 goto done;
588 npackfd = -1;
589
590 packfile_size = 0;
591 progress = calloc(GOT_FETCH_PKTMAX65536, 1);
49
Memory is allocated
592 if (progress == NULL((void *)0)) {
50
Assuming 'progress' is not equal to NULL
51
Taking false branch
593 err = got_error_from_errno("calloc");
594 goto done;
595 }
596
597 *pack_hash = calloc(1, sizeof(**pack_hash));
598 if (*pack_hash == NULL((void *)0)) {
52
Assuming the condition is false
53
Taking false branch
599 err = got_error_from_errno("calloc");
600 goto done;
601 }
602
603 while (!done
68.3
'done' is not equal to 0
) {
54
Loop condition is true. Entering loop body
65
Loop condition is true. Entering loop body
69
Loop condition is false. Execution continues on line 665
604 struct got_object_id *id = NULL((void *)0);
605 char *refname = NULL((void *)0);
606 char *server_progress = NULL((void *)0);
607 off_t packfile_size_cur = 0;
608
609 err = got_privsep_recv_fetch_progress(&done,
610 &id, &refname, symrefs, &server_progress,
611 &packfile_size_cur, (*pack_hash)->sha1, &fetchibuf);
612 if (err != NULL((void *)0))
55
Assuming 'err' is equal to NULL
56
Taking false branch
66
Assuming 'err' is equal to NULL
67
Taking false branch
613 goto done;
614 if (!done && refname && id) {
57
Assuming 'done' is 0
58
Assuming 'refname' is null
68
Assuming 'done' is not equal to 0
615 err = got_pathlist_insert(NULL((void *)0), refs, refname, id);
616 if (err)
617 goto done;
618 } else if (!done
58.1
'done' is 0
68.1
'done' is not equal to 0
&& server_progress) {
59
Assuming 'server_progress' is null
60
Taking false branch
619 char *p;
620 /*
621 * XXX git-daemon tends to send batched output with
622 * lines spanning separate packets. Buffer progress
623 * output until we see a CR or LF to avoid giving
624 * partial lines of progress output to the callback.
625 */
626 if (strlcat(progress, server_progress,
627 GOT_FETCH_PKTMAX65536) >= GOT_FETCH_PKTMAX65536) {
628 progress[0] = '\0'; /* discard */
629 continue;
630 }
631 while ((p = strchr(progress, '\r')) != NULL((void *)0) ||
632 (p = strchr(progress, '\n')) != NULL((void *)0)) {
633 char *s;
634 size_t n;
635 char c = *p;
636 *p = '\0';
637 if (asprintf(&s, "%s%s", progress,
638 c == '\n' ? "\n" : "") == -1) {
639 err = got_error_from_errno("asprintf");
640 goto done;
641 }
642 err = progress_cb(progress_arg, s,
643 packfile_size_cur, 0, 0, 0, 0);
644 free(s);
645 if (err)
646 break;
647 n = strlen(progress);
648 if (n < GOT_FETCH_PKTMAX65536 - 1) {
649 memmove(progress, &progress[n + 1],
650 GOT_FETCH_PKTMAX65536 - n - 1);
651 } else
652 progress[0] = '\0';
653 }
654 free(server_progress);
655 if (err)
656 goto done;
657 } else if (!done
60.1
'done' is 0
68.2
'done' is not equal to 0
&& packfile_size_cur != packfile_size) {
61
Assuming 'packfile_size_cur' is not equal to 'packfile_size'
62
Taking true branch
658 err = progress_cb(progress_arg, NULL((void *)0),
659 packfile_size_cur, 0, 0, 0, 0);
660 if (err)
63
Assuming 'err' is null
64
Taking false branch
661 break;
662 packfile_size = packfile_size_cur;
663 }
664 }
665 if (waitpid(fetchpid, &fetchstatus, 0) == -1) {
70
Assuming the condition is false
71
Taking false branch
666 err = got_error_from_errno("waitpid");
667 goto done;
668 }
669
670 if (lseek(packfd, 0, SEEK_SET0) == -1) {
72
Assuming the condition is false
73
Taking false branch
671 err = got_error_from_errno("lseek");
672 goto done;
673 }
674
675 /* If zero data was fetched without error we are already up-to-date. */
676 if (packfile_size
73.1
'packfile_size' is not equal to 0
== 0) {
74
Taking false branch
677 free(*pack_hash);
678 *pack_hash = NULL((void *)0);
679 goto done;
680 } else if (packfile_size < ssizeof(pack_hdr)((ssize_t)(sizeof(pack_hdr))) + SHA1_DIGEST_LENGTH20) {
75
Assuming the condition is false
76
Taking false branch
681 err = got_error_msg(GOT_ERR_BAD_PACKFILE16, "short pack file");
682 goto done;
683 } else {
684 ssize_t n;
685
686 n = read(packfd, &pack_hdr, ssizeof(pack_hdr)((ssize_t)(sizeof(pack_hdr))));
687 if (n == -1) {
77
Assuming the condition is false
78
Taking false branch
688 err = got_error_from_errno("read");
689 goto done;
690 }
691 if (n != ssizeof(pack_hdr)((ssize_t)(sizeof(pack_hdr)))) {
79
Assuming the condition is false
80
Taking false branch
692 err = got_error(GOT_ERR_IO6);
693 goto done;
694 }
695 if (pack_hdr.signature != htobe32(GOT_PACKFILE_SIGNATURE)(__uint32_t)(__builtin_constant_p(0x5041434b) ? (__uint32_t)(
((__uint32_t)(0x5041434b) & 0xff) << 24 | ((__uint32_t
)(0x5041434b) & 0xff00) << 8 | ((__uint32_t)(0x5041434b
) & 0xff0000) >> 8 | ((__uint32_t)(0x5041434b) &
0xff000000) >> 24) : __swap32md(0x5041434b))
) {
81
'?' condition is true
82
Assuming the condition is false
83
Taking false branch
696 err = got_error_msg(GOT_ERR_BAD_PACKFILE16,
697 "bad pack file signature");
698 goto done;
699 }
700 if (pack_hdr.version != htobe32(GOT_PACKFILE_VERSION)(__uint32_t)(__builtin_constant_p(2) ? (__uint32_t)(((__uint32_t
)(2) & 0xff) << 24 | ((__uint32_t)(2) & 0xff00)
<< 8 | ((__uint32_t)(2) & 0xff0000) >> 8 | (
(__uint32_t)(2) & 0xff000000) >> 24) : __swap32md(2
))
) {
84
'?' condition is true
85
Assuming the condition is false
86
Taking false branch
701 err = got_error_msg(GOT_ERR_BAD_PACKFILE16,
702 "bad pack file version");
703 goto done;
704 }
705 nobj = be32toh(pack_hdr.nobjects)(__uint32_t)(__builtin_constant_p(pack_hdr.nobjects) ? (__uint32_t
)(((__uint32_t)(pack_hdr.nobjects) & 0xff) << 24 | (
(__uint32_t)(pack_hdr.nobjects) & 0xff00) << 8 | ((
__uint32_t)(pack_hdr.nobjects) & 0xff0000) >> 8 | (
(__uint32_t)(pack_hdr.nobjects) & 0xff000000) >> 24
) : __swap32md(pack_hdr.nobjects))
;
87
'?' condition is false
706 if (nobj == 0 &&
88
Assuming 'nobj' is equal to 0
90
Taking true branch
707 packfile_size > ssizeof(pack_hdr)((ssize_t)(sizeof(pack_hdr))) + SHA1_DIGEST_LENGTH20)
89
Assuming the condition is true
708 return got_error_msg(GOT_ERR_BAD_PACKFILE16,
91
Potential leak of memory pointed to by 'progress'
709 "bad pack file with zero objects");
710 if (nobj != 0 &&
711 packfile_size <= ssizeof(pack_hdr)((ssize_t)(sizeof(pack_hdr))) + SHA1_DIGEST_LENGTH20)
712 return got_error_msg(GOT_ERR_BAD_PACKFILE16,
713 "empty pack file with non-zero object count");
714 }
715
716 /*
717 * If the pack file contains no objects, we may only need to update
718 * references in our repository. The caller will take care of that.
719 */
720 if (nobj == 0)
721 goto done;
722
723 if (lseek(packfd, 0, SEEK_SET0) == -1) {
724 err = got_error_from_errno("lseek");
725 goto done;
726 }
727
728 if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, imsg_idxfds) == -1) {
729 err = got_error_from_errno("socketpair");
730 goto done;
731 }
732 idxpid = fork();
733 if (idxpid == -1) {
734 err= got_error_from_errno("fork");
735 goto done;
736 } else if (idxpid == 0)
737 got_privsep_exec_child(imsg_idxfds,
738 GOT_PATH_PROG_INDEX_PACK"/home/ben/bin" "/" "got-index-pack", tmppackpath);
739 if (close(imsg_idxfds[1]) == -1) {
740 err = got_error_from_errno("close");
741 goto done;
742 }
743 imsg_init(&idxibuf, imsg_idxfds[0]);
744
745 npackfd = dup(packfd);
746 if (npackfd == -1) {
747 err = got_error_from_errno("dup");
748 goto done;
749 }
750 err = got_privsep_send_index_pack_req(&idxibuf, (*pack_hash)->sha1,
751 npackfd);
752 if (err != NULL((void *)0))
753 goto done;
754 npackfd = -1;
755 err = got_privsep_send_index_pack_outfd(&idxibuf, nidxfd);
756 if (err != NULL((void *)0))
757 goto done;
758 nidxfd = -1;
759 for (i = 0; i < nitems(tmpfds)(sizeof((tmpfds)) / sizeof((tmpfds)[0])); i++) {
760 err = got_privsep_send_tmpfd(&idxibuf, tmpfds[i]);
761 if (err != NULL((void *)0))
762 goto done;
763 tmpfds[i] = -1;
764 }
765 done = 0;
766 while (!done) {
767 int nobj_total, nobj_indexed, nobj_loose, nobj_resolved;
768
769 err = got_privsep_recv_index_progress(&done, &nobj_total,
770 &nobj_indexed, &nobj_loose, &nobj_resolved,
771 &idxibuf);
772 if (err != NULL((void *)0))
773 goto done;
774 if (nobj_indexed != 0) {
775 err = progress_cb(progress_arg, NULL((void *)0),
776 packfile_size, nobj_total,
777 nobj_indexed, nobj_loose, nobj_resolved);
778 if (err)
779 break;
780 }
781 imsg_clear(&idxibuf);
782 }
783 if (close(imsg_idxfds[0]) == -1) {
784 err = got_error_from_errno("close");
785 goto done;
786 }
787 if (waitpid(idxpid, &idxstatus, 0) == -1) {
788 err = got_error_from_errno("waitpid");
789 goto done;
790 }
791
792 err = got_object_id_str(&id_str, *pack_hash);
793 if (err)
794 goto done;
795 if (asprintf(&packpath, "%s/%s/pack-%s.pack",
796 repo_path, GOT_OBJECTS_PACK_DIR"objects/pack", id_str) == -1) {
797 err = got_error_from_errno("asprintf");
798 goto done;
799 }
800
801 if (asprintf(&idxpath, "%s/%s/pack-%s.idx",
802 repo_path, GOT_OBJECTS_PACK_DIR"objects/pack", id_str) == -1) {
803 err = got_error_from_errno("asprintf");
804 goto done;
805 }
806
807 if (rename(tmppackpath, packpath) == -1) {
808 err = got_error_from_errno3("rename", tmppackpath, packpath);
809 goto done;
810 }
811 free(tmppackpath);
812 tmppackpath = NULL((void *)0);
813 if (rename(tmpidxpath, idxpath) == -1) {
814 err = got_error_from_errno3("rename", tmpidxpath, idxpath);
815 goto done;
816 }
817 free(tmpidxpath);
818 tmpidxpath = NULL((void *)0);
819
820done:
821 if (tmppackpath && unlink(tmppackpath) == -1 && err == NULL((void *)0))
822 err = got_error_from_errno2("unlink", tmppackpath);
823 if (tmpidxpath && unlink(tmpidxpath) == -1 && err == NULL((void *)0))
824 err = got_error_from_errno2("unlink", tmpidxpath);
825 if (nfetchfd != -1 && close(nfetchfd) == -1 && err == NULL((void *)0))
826 err = got_error_from_errno("close");
827 if (npackfd != -1 && close(npackfd) == -1 && err == NULL((void *)0))
828 err = got_error_from_errno("close");
829 if (packfd != -1 && close(packfd) == -1 && err == NULL((void *)0))
830 err = got_error_from_errno("close");
831 if (idxfd != -1 && close(idxfd) == -1 && err == NULL((void *)0))
832 err = got_error_from_errno("close");
833 for (i = 0; i < nitems(tmpfds)(sizeof((tmpfds)) / sizeof((tmpfds)[0])); i++) {
834 if (tmpfds[i] != -1 && close(tmpfds[i]) == -1 && err == NULL((void *)0))
835 err = got_error_from_errno("close");
836 }
837 free(tmppackpath);
838 free(tmpidxpath);
839 free(idxpath);
840 free(packpath);
841 free(ref_prefix);
842 free(progress);
843
844 TAILQ_FOREACH(pe, &have_refs, entry)for((pe) = ((&have_refs)->tqh_first); (pe) != ((void *
)0); (pe) = ((pe)->entry.tqe_next))
{
845 free((char *)pe->path);
846 free(pe->data);
847 }
848 got_pathlist_free(&have_refs);
849 got_ref_list_free(&my_refs);
850 if (err) {
851 free(*pack_hash);
852 *pack_hash = NULL((void *)0);
853 TAILQ_FOREACH(pe, refs, entry)for((pe) = ((refs)->tqh_first); (pe) != ((void *)0); (pe) =
((pe)->entry.tqe_next))
{
854 free((void *)pe->path);
855 free(pe->data);
856 }
857 got_pathlist_free(refs);
858 TAILQ_FOREACH(pe, symrefs, entry)for((pe) = ((symrefs)->tqh_first); (pe) != ((void *)0); (pe
) = ((pe)->entry.tqe_next))
{
859 free((void *)pe->path);
860 free(pe->data);
861 }
862 got_pathlist_free(symrefs);
863 }
864 return err;
865}