740af9
From eb8660e2aae2f0366886e73dc37beb236e89188b Mon Sep 17 00:00:00 2001
740af9
From: Panu Matilainen <pmatilai@redhat.com>
740af9
Date: Thu, 16 Nov 2023 14:22:15 +0200
740af9
Subject: [PATCH 2/2] Fix integer overflow in memory calculations on 32bit
740af9
 systems
740af9
740af9
"long int" on at least x86 Linux is exactly the same as a plain "int",
740af9
so calculations can easily overflow. 32bit systems are not expected to
740af9
have hundreds of gigabytes of memory but a 32bit process on a x86_64 can
740af9
run into all sorts of funny things, such having 500GB system memory. At
740af9
which point the type capable of addressing all of process memory is
740af9
absolutely useless for calculating the total memory.
740af9
740af9
Use uint64_t in the memory calculations to make the size explicit. Of course
740af9
one day we may cross that border too, but I hope to be retired by then.
740af9
740af9
Fixes https://issues.redhat.com/browse/RHEL-16557
740af9
---
740af9
 rpmio/macro.c | 20 +++++++++++---------
740af9
 1 file changed, 11 insertions(+), 9 deletions(-)
740af9
740af9
diff --git a/rpmio/macro.c b/rpmio/macro.c
740af9
index 98067442555f7c458ea4976d96b5438db01bd031..354b06b0ed34c030638788da5d397b7ba108e806 100644
740af9
--- a/rpmio/macro.c
740af9
+++ b/rpmio/macro.c
740af9
@@ -1177,30 +1177,32 @@ static void doShescape(MacroBuf mb, rpmMacroEntry me, ARGV_t argv, size_t *parse
740af9
     mbAppend(mb, '\'');
740af9
 }
740af9
 
740af9
-static unsigned long getmem_total(void)
740af9
+static uint64_t getmem_total(void)
740af9
 {
740af9
-    unsigned long mem = 0;
740af9
+    uint64_t mem = 0;
740af9
     long int pagesize = sysconf(_SC_PAGESIZE);
740af9
     long int pages = sysconf(_SC_PHYS_PAGES);
740af9
 
740af9
-    if (pagesize < 0)
740af9
+    if (pagesize <= 0)
740af9
 	pagesize = 4096;
740af9
-    if (pages > 0)
740af9
-	mem = pages * pagesize;
740af9
+    if (pages > 0) {
740af9
+	/* Cast needed to force 64bit calculation on 32bit systems */
740af9
+	mem = (uint64_t)pages * pagesize;
740af9
+    }
740af9
 
740af9
     return mem;
740af9
 }
740af9
 
740af9
-static unsigned long getmem_proc(int thread)
740af9
+static uint64_t getmem_proc(int thread)
740af9
 {
740af9
-    unsigned long mem = getmem_total();
740af9
+    uint64_t mem = getmem_total();
740af9
     /*
740af9
      * Conservative estimates for thread use on 32bit systems where address
740af9
      * space is an issue: 2GB for bare metal, 3GB for a 32bit process
740af9
      * on a 64bit system.
740af9
      */
740af9
     if (thread) {
740af9
-	unsigned long vmem = mem;
740af9
+	uint64_t vmem = mem;
740af9
 #if __WORDSIZE == 32
740af9
 	vmem = UINT32_MAX / 2;
740af9
 #else
740af9
@@ -1224,7 +1226,7 @@ static void doGetncpus(MacroBuf mb, rpmMacroEntry me, ARGV_t argv, size_t *parse
740af9
     const char *arg = argv[1] ? argv[1] : "total";
740af9
     char buf[32];
740af9
     unsigned int ncpus = getncpus();
740af9
-    unsigned long mem = 0;
740af9
+    uint64_t mem = 0;
740af9
 
740af9
     if (rstreq(arg, "total")) {
740af9
 	/* nothing */
740af9
-- 
740af9
2.43.0
740af9