| line |
true |
false |
branch |
|
102
|
0 |
0 |
if (pid == 0) return 1; |
|
103
|
0 |
0 |
return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH); |
|
|
0 |
0 |
return !(kill((pid_t)pid, 0) == -1 && errno == ESRCH); |
|
110
|
110 |
0 |
if (__atomic_compare_exchange_n(&hdr->mutex, &expected, mypid, |
|
113
|
0 |
0 |
if (spin < 32) { |
|
123
|
0 |
0 |
if (cur != 0) { |
|
126
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT && cur >= GRAPH_MUTEX_BIT) { |
|
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT && cur >= GRAPH_MUTEX_BIT) { |
|
|
0 |
0 |
if (rc == -1 && errno == ETIMEDOUT && cur >= GRAPH_MUTEX_BIT) { |
|
128
|
0 |
0 |
if (!graph_pid_alive(pid) && |
|
129
|
0 |
0 |
__atomic_compare_exchange_n(&hdr->mutex, &cur, 0, |
|
143
|
0 |
110 |
if (__atomic_load_n(&hdr->mutex_waiters, __ATOMIC_RELAXED) > 0) |
|
157
|
90 |
0 |
for (uint32_t w = 0; w < bwords; w++) { |
|
159
|
0 |
90 |
if (word == ~(uint64_t)0) continue; |
|
162
|
0 |
90 |
if (idx >= max) return -1; |
|
179
|
0 |
80 |
if (idx < 0) return -1; |
|
187
|
11 |
0 |
if (src >= h->hdr->max_nodes || dst >= h->hdr->max_nodes) return 0; |
|
|
0 |
11 |
if (src >= h->hdr->max_nodes || dst >= h->hdr->max_nodes) return 0; |
|
188
|
10 |
1 |
if (!graph_bit_set(h->node_bitmap, src) || !graph_bit_set(h->node_bitmap, dst)) |
|
|
0 |
10 |
if (!graph_bit_set(h->node_bitmap, src) || !graph_bit_set(h->node_bitmap, dst)) |
|
191
|
0 |
10 |
if (eidx < 0) return 0; |
|
201
|
0 |
5 |
if (node >= h->hdr->max_nodes) return 0; |
|
202
|
0 |
5 |
if (!graph_bit_set(h->node_bitmap, node)) return 0; |
|
205
|
2 |
5 |
while (eidx != GRAPH_NONE) { |
|
206
|
0 |
2 |
if (eidx >= h->hdr->max_edges) break; /* corrupt/attacker edge index: stop */ |
|
221
|
1 |
3 |
if (node >= h->hdr->max_nodes) return 0; |
|
222
|
0 |
3 |
if (!graph_bit_set(h->node_bitmap, node)) return 0; |
|
224
|
20 |
3 |
for (uint32_t src = 0; src < max_n; src++) { |
|
225
|
3 |
17 |
if (src == node) continue; |
|
226
|
13 |
4 |
if (!graph_bit_set(h->node_bitmap, src)) continue; |
|
229
|
3 |
4 |
while (eidx != GRAPH_NONE) { |
|
230
|
0 |
3 |
if (eidx >= h->hdr->max_edges) break; |
|
232
|
2 |
1 |
if (h->edges[eidx].dst == node) { |
|
282
|
1 |
21 |
if (node >= h->hdr->max_nodes) return 0; |
|
288
|
0 |
8 |
if (node >= h->hdr->max_nodes) return 0; |
|
291
|
11 |
8 |
while (eidx != GRAPH_NONE) { |
|
292
|
0 |
11 |
if (eidx >= h->hdr->max_edges) break; |
|
338
|
206 |
11 |
for (uint32_t i = 0; i < max_nodes; i++) heads[i] = GRAPH_NONE; |
|
346
|
0 |
13 |
if (!h) { |
|
348
|
0 |
0 |
if (backing_fd >= 0) close(backing_fd); |
|
360
|
3 |
10 |
h->path = path ? strdup(path) : NULL; |
|
368
|
0 |
2 |
if (hdr->magic != GRAPH_MAGIC) return 0; |
|
369
|
0 |
2 |
if (hdr->version != GRAPH_VERSION) return 0; |
|
370
|
2 |
0 |
if (hdr->max_nodes == 0 || hdr->max_edges == 0) return 0; |
|
|
0 |
2 |
if (hdr->max_nodes == 0 || hdr->max_edges == 0) return 0; |
|
371
|
2 |
0 |
if (hdr->max_nodes > 0x7FFFFFFFu || hdr->max_edges > 0x7FFFFFFFu) return 0; |
|
|
0 |
2 |
if (hdr->max_nodes > 0x7FFFFFFFu || hdr->max_edges > 0x7FFFFFFFu) return 0; |
|
372
|
0 |
2 |
if (hdr->total_size != file_size) return 0; |
|
373
|
0 |
2 |
if (hdr->total_size != graph_total_size(hdr->max_nodes, hdr->max_edges)) return 0; |
|
381
|
0 |
2 |
if (hdr->node_data_off != exp_node_data) return 0; |
|
382
|
0 |
2 |
if (hdr->node_heads_off != exp_node_heads) return 0; |
|
383
|
0 |
2 |
if (hdr->node_bitmap_off != exp_node_bitmap) return 0; |
|
384
|
0 |
2 |
if (hdr->edge_data_off != exp_edge_data) return 0; |
|
385
|
0 |
2 |
if (hdr->edge_bitmap_off != exp_edge_bitmap) return 0; |
|
392
|
3 |
0 |
for (int attempt = 0; attempt < 100; attempt++) { |
|
394
|
2 |
1 |
if (fd >= 0) { (void)fchmod(fd, mode); return fd; } /* exact mode: umask narrowed the O_EXCL create */ |
|
395
|
0 |
1 |
if (errno != EEXIST) { GRAPH_ERR("create %s: %s", path, strerror(errno)); return -1; } |
|
|
0 |
0 |
if (errno != EEXIST) { GRAPH_ERR("create %s: %s", path, strerror(errno)); return -1; } |
|
397
|
1 |
0 |
if (fd >= 0) return fd; |
|
398
|
0 |
0 |
if (errno == ENOENT) continue; /* creator unlinked between our two opens; retry */ |
|
399
|
0 |
0 |
GRAPH_ERR("open %s: %s", path, strerror(errno)); /* ELOOP => symlink rejected */ |
|
402
|
0 |
0 |
GRAPH_ERR("open %s: create/attach kept racing", path); |
|
408
|
10 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
409
|
0 |
10 |
if (max_nodes == 0) { GRAPH_ERR("max_nodes must be > 0"); return NULL; } |
|
|
0 |
0 |
if (max_nodes == 0) { GRAPH_ERR("max_nodes must be > 0"); return NULL; } |
|
410
|
0 |
10 |
if (max_edges == 0) { GRAPH_ERR("max_edges must be > 0"); return NULL; } |
|
|
0 |
0 |
if (max_edges == 0) { GRAPH_ERR("max_edges must be > 0"); return NULL; } |
|
411
|
0 |
10 |
if (max_nodes > UINT32_MAX - 63) { GRAPH_ERR("max_nodes too large"); return NULL; } |
|
|
0 |
0 |
if (max_nodes > UINT32_MAX - 63) { GRAPH_ERR("max_nodes too large"); return NULL; } |
|
412
|
0 |
10 |
if (max_edges > UINT32_MAX - 63) { GRAPH_ERR("max_edges too large"); return NULL; } |
|
|
0 |
0 |
if (max_edges > UINT32_MAX - 63) { GRAPH_ERR("max_edges too large"); return NULL; } |
|
427
|
7 |
3 |
if (anonymous) { |
|
430
|
0 |
7 |
if (base == MAP_FAILED) { GRAPH_ERR("mmap: %s", strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (base == MAP_FAILED) { GRAPH_ERR("mmap: %s", strerror(errno)); return NULL; } |
|
433
|
0 |
3 |
if (fd < 0) return NULL; |
|
434
|
0 |
3 |
if (flock(fd, LOCK_EX) < 0) { GRAPH_ERR("flock: %s", strerror(errno)); close(fd); return NULL; } |
|
|
0 |
0 |
if (flock(fd, LOCK_EX) < 0) { GRAPH_ERR("flock: %s", strerror(errno)); close(fd); return NULL; } |
|
436
|
0 |
3 |
if (fstat(fd, &st) < 0) { GRAPH_ERR("fstat: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; } |
|
|
0 |
0 |
if (fstat(fd, &st) < 0) { GRAPH_ERR("fstat: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; } |
|
438
|
1 |
2 |
if (!is_new && (uint64_t)st.st_size < sizeof(GraphHeader)) { |
|
|
0 |
1 |
if (!is_new && (uint64_t)st.st_size < sizeof(GraphHeader)) { |
|
439
|
0 |
0 |
GRAPH_ERR("%s: file too small (%lld)", path, (long long)st.st_size); |
|
442
|
2 |
1 |
if (is_new && ftruncate(fd, (off_t)total) < 0) { |
|
|
0 |
2 |
if (is_new && ftruncate(fd, (off_t)total) < 0) { |
|
443
|
0 |
0 |
GRAPH_ERR("ftruncate: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; |
|
445
|
1 |
2 |
map_size = is_new ? (size_t)total : (size_t)st.st_size; |
|
447
|
0 |
3 |
if (base == MAP_FAILED) { GRAPH_ERR("mmap: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; } |
|
|
0 |
0 |
if (base == MAP_FAILED) { GRAPH_ERR("mmap: %s", strerror(errno)); flock(fd, LOCK_UN); close(fd); return NULL; } |
|
448
|
1 |
2 |
if (!is_new) { |
|
449
|
0 |
1 |
if (!graph_validate_header((GraphHeader *)base, (uint64_t)st.st_size)) { |
|
450
|
0 |
0 |
GRAPH_ERR("invalid graph file"); munmap(base, map_size); flock(fd, LOCK_UN); close(fd); return NULL; |
|
457
|
2 |
7 |
if (fd >= 0) { flock(fd, LOCK_UN); close(fd); } |
|
463
|
2 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
464
|
0 |
2 |
if (max_nodes == 0) { GRAPH_ERR("max_nodes must be > 0"); return NULL; } |
|
|
0 |
0 |
if (max_nodes == 0) { GRAPH_ERR("max_nodes must be > 0"); return NULL; } |
|
465
|
0 |
2 |
if (max_edges == 0) { GRAPH_ERR("max_edges must be > 0"); return NULL; } |
|
|
0 |
0 |
if (max_edges == 0) { GRAPH_ERR("max_edges must be > 0"); return NULL; } |
|
466
|
2 |
0 |
if (max_nodes > UINT32_MAX - 63 || max_edges > UINT32_MAX - 63) { |
|
|
0 |
2 |
if (max_nodes > UINT32_MAX - 63 || max_edges > UINT32_MAX - 63) { |
|
467
|
0 |
0 |
GRAPH_ERR("max_nodes/max_edges too large"); return NULL; |
|
471
|
2 |
0 |
int fd = memfd_create(name ? name : "graph", MFD_CLOEXEC | MFD_ALLOW_SEALING); |
|
472
|
0 |
2 |
if (fd < 0) { GRAPH_ERR("memfd_create: %s", strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (fd < 0) { GRAPH_ERR("memfd_create: %s", strerror(errno)); return NULL; } |
|
473
|
0 |
2 |
if (ftruncate(fd, (off_t)total) < 0) { |
|
474
|
0 |
0 |
GRAPH_ERR("ftruncate: %s", strerror(errno)); close(fd); return NULL; |
|
478
|
0 |
2 |
if (base == MAP_FAILED) { GRAPH_ERR("mmap: %s", strerror(errno)); close(fd); return NULL; } |
|
|
0 |
0 |
if (base == MAP_FAILED) { GRAPH_ERR("mmap: %s", strerror(errno)); close(fd); return NULL; } |
|
484
|
1 |
0 |
if (errbuf) errbuf[0] = '\0'; |
|
486
|
0 |
1 |
if (fstat(fd, &st) < 0) { GRAPH_ERR("fstat: %s", strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (fstat(fd, &st) < 0) { GRAPH_ERR("fstat: %s", strerror(errno)); return NULL; } |
|
487
|
0 |
1 |
if ((uint64_t)st.st_size < sizeof(GraphHeader)) { GRAPH_ERR("too small"); return NULL; } |
|
|
0 |
0 |
if ((uint64_t)st.st_size < sizeof(GraphHeader)) { GRAPH_ERR("too small"); return NULL; } |
|
490
|
0 |
1 |
if (base == MAP_FAILED) { GRAPH_ERR("mmap: %s", strerror(errno)); return NULL; } |
|
|
0 |
0 |
if (base == MAP_FAILED) { GRAPH_ERR("mmap: %s", strerror(errno)); return NULL; } |
|
491
|
0 |
1 |
if (!graph_validate_header((GraphHeader *)base, (uint64_t)st.st_size)) { |
|
492
|
0 |
0 |
GRAPH_ERR("invalid graph"); munmap(base, ms); return NULL; |
|
495
|
0 |
1 |
if (myfd < 0) { GRAPH_ERR("fcntl: %s", strerror(errno)); munmap(base, ms); return NULL; } |
|
|
0 |
0 |
if (myfd < 0) { GRAPH_ERR("fcntl: %s", strerror(errno)); munmap(base, ms); return NULL; } |
|
500
|
0 |
13 |
if (!h) return; |
|
501
|
2 |
11 |
if (h->notify_fd >= 0) close(h->notify_fd); |
|
502
|
3 |
10 |
if (h->backing_fd >= 0) close(h->backing_fd); |
|
503
|
13 |
0 |
if (h->hdr) munmap(h->hdr, h->mmap_size); |
|
509
|
1 |
0 |
if (!h || !h->hdr) return 0; |
|
|
0 |
1 |
if (!h || !h->hdr) return 0; |
|
514
|
0 |
2 |
if (h->notify_fd >= 0) return h->notify_fd; |
|
516
|
0 |
2 |
if (efd < 0) return -1; |
|
522
|
0 |
3 |
if (h->notify_fd < 0) return 0; |
|
528
|
0 |
2 |
if (h->notify_fd < 0) return -1; |
|
530
|
0 |
2 |
if (read(h->notify_fd, &v, sizeof(v)) != sizeof(v)) return -1; |