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