Message ID | xny42drz8h.fsf@greed.delorie.com |
---|---|
State | New, archived |
Headers | show |
It would be more backward-compatible to represent minor overflows as negative numbers that are equivalent to the correct answers modulo (UINT_MAX + 1). That way, callers can continue to retrieve the correct values by casting int to unsigned. The code can use -1 to represent a value greater than UINT_MAX. This all should be doable just as efficiently as the proposed patch.
On 09/27/2016 03:07 PM, Paul Eggert wrote: > It would be more backward-compatible to represent minor overflows as > negative numbers that are equivalent to the correct answers modulo > (UINT_MAX + 1). That way, callers can continue to retrieve the > correct values by casting int to unsigned. The code can use -1 to > represent a value greater than UINT_MAX. This all should be doable > just as efficiently as the proposed patch. Agreed, I had not considered that case. It would certainly make the interface as useful as it could be with a 32-bit address space, but it would still be mostly useless on a 64-bit system (even with 48-bit VA). I just double checked that C11 does continue to contain the clause that allows the conversion to work: ~~~ 6.3.1.3 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.60) 60) The rules describe arithmetic on the mathematical value, not the value of a given type of expression. ~~~ This way you could cast the values to 'unsigned int' and know you had a valid result as long as it was less than '(unsigned int)-1' (reserved for overflow). DJ, Care to make a version 2 of the patch?
diff --git a/malloc/malloc.c b/malloc/malloc.c index ef04360..4f438ef 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -224,6 +224,7 @@ #include <unistd.h> #include <stdio.h> /* needed for malloc_stats */ #include <errno.h> +#include <limits.h> #include <shlib-compat.h> @@ -4633,18 +4634,29 @@ int_mallinfo (mstate av, struct mallinfo *m) } } - m->smblks += nfastblocks; - m->ordblks += nblocks; - m->fordblks += avail; - m->uordblks += av->system_mem - avail; - m->arena += av->system_mem; - m->fsmblks += fastavail; +/* Saturated add - add ADD to SUM. If the result exceeds the range of + "int", set SUM to INT_MAX instead. Assumes ADD and SUM are + positive. The published ABI prevents us from bumping "int" to a + larger type. */ +#define SAT_ADD(SUM, ADD) \ + ({ INTERNAL_SIZE_T tmp = (INTERNAL_SIZE_T)(SUM) + (INTERNAL_SIZE_T)(ADD); SUM = (tmp > INT_MAX) ? INT_MAX : tmp; }) + +/* Likewise, but assign ADD to SUM. */ +#define SAT_SET(SUM, ADD) \ + ({ SUM = ((INTERNAL_SIZE_T)(ADD) > INT_MAX) ? INT_MAX : (ADD); }) + + SAT_ADD (m->smblks, nfastblocks); + SAT_ADD (m->ordblks, nblocks); + SAT_ADD (m->fordblks, avail); + SAT_ADD (m->uordblks, av->system_mem - avail); + SAT_ADD (m->arena, av->system_mem); + SAT_ADD (m->fsmblks, fastavail); if (av == &main_arena) { - m->hblks = mp_.n_mmaps; - m->hblkhd = mp_.mmapped_mem; - m->usmblks = 0; - m->keepcost = chunksize (av->top); + SAT_SET (m->hblks, mp_.n_mmaps); + SAT_SET (m->hblkhd, mp_.mmapped_mem); + SAT_SET (m->usmblks, 0); + SAT_SET (m->keepcost, chunksize (av->top)); } }