From b26fa40428f9372c3020d78d821f42dbabc78d47 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 27 Nov 2023 04:05:47 +0000 Subject: xap_helper.h: avoid some off_t vs size_t problems We'll introduce a helper to cast off_t to size_t consistently for mmap/munmap/calloc calls which require size_t. Also, an extra check for multiplication overflow can be helpful just in case we end up with a gigantic file roots file. --- lib/PublicInbox/xap_helper.h | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'lib/PublicInbox') diff --git a/lib/PublicInbox/xap_helper.h b/lib/PublicInbox/xap_helper.h index 1d8437c9..5816c24c 100644 --- a/lib/PublicInbox/xap_helper.h +++ b/lib/PublicInbox/xap_helper.h @@ -360,6 +360,13 @@ static void xclose(int fd) EABORT("BUG: close"); } +static size_t off2size(off_t n) +{ + if (n < 0 || (uintmax_t)n > SIZE_MAX) + ABORT("off_t out of size_t range: %lld\n", (long long)n); + return (size_t)n; +} + #define CLEANUP_DUMP_ROOTS __attribute__((__cleanup__(dump_roots_ensure))) static void dump_roots_ensure(void *ptr) { @@ -367,8 +374,9 @@ static void dump_roots_ensure(void *ptr) if (drt->root2off_fd >= 0) xclose(drt->root2off_fd); hdestroy(); // idempotent - if (drt->mm_ptr && munmap(drt->mm_ptr, drt->sb.st_size)) - EABORT("BUG: munmap(%p, %zu)", drt->mm_ptr, drt->sb.st_size); + size_t size = off2size(drt->sb.st_size); + if (drt->mm_ptr && munmap(drt->mm_ptr, size)) + EABORT("BUG: munmap(%p, %zu)", drt->mm_ptr, size); free(drt->entries); fbuf_ensure(&drt->wbuf); } @@ -516,20 +524,18 @@ static bool cmd_dump_roots(struct req *req) // each entry is at least 43 bytes ({OIDHEX}\0{INT}\0), // so /32 overestimates the number of expected entries by // ~%25 (as recommended by Linux hcreate(3) manpage) - size_t est = (drt.sb.st_size / 32) + 1; //+1 for "\0" termination - if ((uint64_t)drt.sb.st_size > (uint64_t)SIZE_MAX) - err(EXIT_FAILURE, "%s size too big (%lld bytes > %zu)", - root2off_file, (long long)drt.sb.st_size, SIZE_MAX); - drt.mm_ptr = mmap(NULL, drt.sb.st_size, PROT_READ, + size_t size = off2size(drt.sb.st_size); + size_t est = (size / 32) + 1; //+1 for "\0" termination + drt.mm_ptr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, drt.root2off_fd, 0); if (drt.mm_ptr == MAP_FAILED) - err(EXIT_FAILURE, "mmap(%zu, %s)", - drt.sb.st_size, root2off_file); - drt.entries = (char **)calloc(est * 2, sizeof(char *)); + err(EXIT_FAILURE, "mmap(%zu, %s)", size, root2off_file); + size_t asize = est * 2; + if (asize < est) ABORT("too many entries: %zu", est); + drt.entries = (char **)calloc(asize, sizeof(char *)); if (!drt.entries) err(EXIT_FAILURE, "calloc(%zu * 2, %zu)", est, sizeof(char *)); - size_t tot = split2argv(drt.entries, (char *)drt.mm_ptr, - drt.sb.st_size, est * 2); + size_t tot = split2argv(drt.entries, (char *)drt.mm_ptr, size, asize); if (tot <= 0) return false; // split2argv already warned on error if (!hcreate(est)) err(EXIT_FAILURE, "hcreate(%zu)", est); -- cgit v1.2.3-24-ge0c7