From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <e@80x24.org>
X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on dcvr.yhbt.net
X-Spam-Level: 
X-Spam-ASN:  
X-Spam-Status: No, score=-4.2 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00,
	DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,
	T_SCC_BODY_TEXT_LINE shortcircuit=no autolearn=ham autolearn_force=no
	version=3.4.6
Received: from localhost (dcvr.yhbt.net [127.0.0.1])
	by dcvr.yhbt.net (Postfix) with ESMTP id 7AEE01F461
	for <meta@public-inbox.org>; Mon, 27 Nov 2023 21:57:14 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=80x24.org;
	s=selector1; t=1701122234;
	bh=CaFL7pQ1DGRfftyk3uS5CWw3wMmtq79U3W+U9HYBLYs=;
	h=From:To:Subject:Date:In-Reply-To:References:From;
	b=UlUkIUYM6CJz9+qfWDWOaisBDrJwc24OvCZ/Q3tLoHtKJFcvZtsZxDv66uyoyH14I
	 3D1RZoLki7rHmywgZAUmFE9iOwUgrbZTXNK5rdl7uccQNvQmr6BohLm8xtIvnlmI76
	 MaJKWKQR4KRkNADOmUBNYovzR7IlzQa1+m3MKCEI=
From: Eric Wong <e@80x24.org>
To: meta@public-inbox.org
Subject: [PATCH 2/2] xap_helper.h: avoid some off_t vs size_t problems
Date: Mon, 27 Nov 2023 21:54:39 +0000
Message-ID: <20231127215439.91487-3-e@80x24.org>
In-Reply-To: <20231127215439.91487-1-e@80x24.org>
References: <20231127215439.91487-1-e@80x24.org>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
List-Id: <meta.public-inbox.org>

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(-)

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);