Fix printf funcs on memory pressure with floats (#1275)

Cosmopolitan's printf-family functions will currently crash if one tries
formatting a floating point number with a larger precision (large enough
that gdtoa attempts to allocate memory to format the number) while under
memory pressure (i.e. when malloc fails) because gdtoa fails to check if
malloc fails.

The added tests (which would previously crash under cosmopolitan without
this patch) show how to reproduce the issue.

This patch fixes this, and adds the aforementioned tests.
This commit is contained in:
Gabriel Ravier 2024-09-01 23:42:14 +02:00 committed by GitHub
parent ae57fa2c4e
commit a089c07ddc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 86 additions and 5 deletions

View file

@ -49,6 +49,8 @@ __gdtoa_rv_alloc(int i, ThInfo **PTI)
j <<= 1)
k++;
r = (int *)__gdtoa_Balloc(k, PTI);
if (r == NULL)
return NULL;
*r = k;
return (char *)(r + 1);
}

View file

@ -246,6 +246,9 @@ dtoa(double d0, int mode, int ndigits, int *decpt, int *sign, char **rve)
i = 1;
}
s = s0 = __gdtoa_rv_alloc(i, &TI);
if (s0 == NULL)
goto ret1;
if (mode > 1 && Rounding != 1)
leftright = 0;
if (ilim >= 0 && ilim <= Quick_max && try_quick) {
@ -614,7 +617,8 @@ retc:
--s;
ret1:
__gdtoa_Bfree(b, &TI);
*s = 0;
if (s != NULL)
*s = 0;
*decpt = k + 1;
if (rve)
*rve = s;

View file

@ -286,6 +286,8 @@ gdtoa(const FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, in
i = 1;
}
s = s0 = __gdtoa_rv_alloc(i, &TI);
if (s0 == NULL)
goto ret1;
if (mode <= 1)
rdir = 0;
else if ( (rdir = fpi->rounding - 1) !=0) {
@ -673,10 +675,12 @@ ret:
__gdtoa_Bfree(mhi, &TI);
}
ret1:
while(s > s0 && s[-1] == '0')
--s;
if (s != NULL)
while(s > s0 && s[-1] == '0')
--s;
__gdtoa_Bfree(b, &TI);
*s = 0;
if (s != NULL)
*s = 0;
*decpt = k + 1;
if (rve)
*rve = s;

View file

@ -129,12 +129,16 @@ __gdtoa_Balloc(int k, ThInfo **PTI)
} else {
x = 1 << k;
rv = malloc(sizeof(Bigint) + (x-1)*sizeof(ULong));
if (rv == NULL)
goto ret;
rv->k = k;
rv->maxwds = x;
}
rv->sign = rv->wds = 0;
ret:
if (TI == &TI0)
__gdtoa_unlock();
rv->sign = rv->wds = 0;
return rv;
}