From patchwork Thu Oct 6 17:20:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: DJ Delorie X-Patchwork-Id: 16311 Received: (qmail 42329 invoked by alias); 6 Oct 2016 17:20:34 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 42030 invoked by uid 89); 6 Oct 2016 17:20:33 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.6 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=Ensure, sums, arena, sum X-HELO: mx1.redhat.com From: DJ Delorie To: Paul Eggert Cc: carlos@redhat.com, libc-alpha@sourceware.org Subject: Re: [PATCH] [BZ 20628] make mallinfo saturating In-Reply-To: <9b2ad307-2db2-c270-a4b9-97ca87e5208f@cs.ucla.edu> (message from Paul Eggert on Wed, 5 Oct 2016 23:34:07 -0700) Date: Thu, 06 Oct 2016 13:20:29 -0400 Message-ID: MIME-Version: 1.0 Version 3. Cast SUM to unsigned first, in case it's pre-wrapped. Expanded comment. Verified that ADD is always INTERNAL_SIZE_T so no need to cast that to unsigned. [BZ #20628] * malloc/malloc.c (int_mallinfo): Use saturating add instead of overflow to collect statistics into a fixed "int" container. diff --git a/malloc/malloc.c b/malloc/malloc.c index ef04360..9d4018f 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -224,6 +224,7 @@ #include #include /* needed for malloc_stats */ #include +#include #include @@ -4594,8 +4595,8 @@ int_mallinfo (mstate av, struct mallinfo *m) mchunkptr p; INTERNAL_SIZE_T avail; INTERNAL_SIZE_T fastavail; - int nblocks; - int nfastblocks; + INTERNAL_SIZE_T nblocks; + INTERNAL_SIZE_T nfastblocks; /* Ensure initialization */ if (av->top == 0) @@ -4633,18 +4634,38 @@ 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" (or, wrapped, "unsigned int"), set SUM to UINT_MAX instead + ((int)-1). Assumes ADD and SUM reflect positive values, even when + they wrap to negative, and that SUM is type "int". The published + ABI prevents us from bumping "int" to a larger type. Note: this + macro doesn't handle overflow when INTERNAL_SIZE_T is the same size + as "int", but in that case, the things we're counting wouldn't + cause an overflow anyway. + + The net result is that sums which would wrap around and become + misleading positive values again, stop at -1, so any positive value + we report is accurate, and any negative number other than -1 we + report can be cast to unsigned to become accurate. */ +#define SAT_ADD(SUM, ADD) \ + ({ INTERNAL_SIZE_T tmp = (INTERNAL_SIZE_T)(unsigned)(SUM) + (INTERNAL_SIZE_T)(ADD); SUM = (tmp > UINT_MAX) ? -1 : tmp; }) + +/* Likewise, but assign ADD to SUM. */ +#define SAT_SET(SUM, ADD) \ + ({ SUM = ((INTERNAL_SIZE_T)(ADD) > UINT_MAX) ? -1 : (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)); } }