On Tue, Nov 09, 2021 at 02:14:38PM +0200, Nir Soffer wrote:
 > @@ -44,12 +44,14 @@ generic_vector_reserve (struct
generic_vector *v, size_t n, size_t itemsize)
 >    size_t reqcap, newcap;
 >
 >    reqcap = v->cap + n;
 > -  if (reqcap < v->cap)
 > +  if (reqcap * itemsize < v->cap * itemsize) {
 > +    errno = ENOMEM;
 >      return -1; /* overflow */
 > +  }
 >
 >    newcap = (v->cap * 3 + 1) / 2;
 
 Should we use:
 
     newcap = v->cap + (v->cap + 1) / 2
 
 so we don't overflow too early?
 
Sure, nice improvement.  On a 32-bit platform, if v->cap is
2,000,000,000, this changes that particular calculation from
852,516,352 to 3,000,000,000.  But then again, on a 32-bit platform,
it is unlikely that you have enough address space to hold that many
items in memory in the first place.
 And if we overflow - meaning that we cannot grow by factor of 1.5,
 grow to maximum size:
 
     if (newcap * itemsize < v->cap * itemsize)
        newcap = SIZE_MAX / itemsize;
 
 This makes a difference when itemsize is 1 or 2. The current
 code will stop growing efficiently when allocation is 1.45g, and
 then go back to realloc() on every call. 
Also an interesting idea, but I don't think it's necessary.  After
all, this only matters on a 32-bit platform; but attempting to realloc
nearly 4G of memory in one call WILL fail (with a 32-bit address
space, you're lucky if you can address more than 3G, because the OS
reserved another 1G for itself; not to mention that it is not just
this one array that you are trying to resize, but everything else
already in memory that is competing for usage) - you've probably hit
ENOMEM long before getting to even the 2.7G cutoff point where we
degrade back to linear realloc.
 
 > -  if (newcap < reqcap)
 > +  if (newcap * itemsize < reqcap * itemsize)
 >      newcap = reqcap;
 
 If we handle overflow before, we can keep the old check
 comparing caps.
 
 I can post a patch with this changes if you like. 
I hadn't pushed just yet, so I incorporated your suggestion, and the
result is now commit 884052e054 in libnbd, and 0c342208d5 in nbdkit.
-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  
qemu.org | 
libvirt.org