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
This commit is contained in:
Panu Matilainen 2023-11-16 14:22:15 +02:00
parent d0e03b21ca
commit 1cd9f9077a
1 changed files with 11 additions and 9 deletions

View File

@ -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 */