LCOV - code coverage report
Current view: top level - lib/gltests - malloca.c (source / functions) Hit Total Coverage
Test: GNU Libidn Lines: 17 19 89.5 %
Date: 2020-07-22 17:53:13 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Safe automatic memory allocation.
       2             :    Copyright (C) 2003, 2006-2007, 2009-2020 Free Software Foundation, Inc.
       3             :    Written by Bruno Haible <bruno@clisp.org>, 2003, 2018.
       4             : 
       5             :    This program is free software; you can redistribute it and/or modify
       6             :    it under the terms of the GNU General Public License as published by
       7             :    the Free Software Foundation; either version 3, or (at your option)
       8             :    any later version.
       9             : 
      10             :    This program is distributed in the hope that it will be useful,
      11             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :    GNU General Public License for more details.
      14             : 
      15             :    You should have received a copy of the GNU General Public License
      16             :    along with this program; if not, see <https://www.gnu.org/licenses/>.  */
      17             : 
      18             : #define _GL_USE_STDLIB_ALLOC 1
      19             : #include <config.h>
      20             : 
      21             : /* Specification.  */
      22             : #include "malloca.h"
      23             : 
      24             : #include "verify.h"
      25             : 
      26             : /* The speed critical point in this file is freea() applied to an alloca()
      27             :    result: it must be fast, to match the speed of alloca().  The speed of
      28             :    mmalloca() and freea() in the other case are not critical, because they
      29             :    are only invoked for big memory sizes.
      30             :    Here we use a bit in the address as an indicator, an idea by Ondřej Bílka.
      31             :    malloca() can return three types of pointers:
      32             :      - Pointers ≡ 0 mod 2*sa_alignment_max come from stack allocation.
      33             :      - Pointers ≡ sa_alignment_max mod 2*sa_alignment_max come from heap
      34             :        allocation.
      35             :      - NULL comes from a failed heap allocation.  */
      36             : 
      37             : /* Type for holding very small pointer differences.  */
      38             : typedef unsigned char small_t;
      39             : /* Verify that it is wide enough.  */
      40             : verify (2 * sa_alignment_max - 1 <= (small_t) -1);
      41             : 
      42             : void *
      43      250000 : mmalloca (size_t n)
      44             : {
      45             : #if HAVE_ALLOCA
      46             :   /* Allocate one more word, used to determine the address to pass to freea(),
      47             :      and room for the alignment ≡ sa_alignment_max mod 2*sa_alignment_max.  */
      48      250000 :   size_t nplus = n + sizeof (small_t) + 2 * sa_alignment_max - 1;
      49             : 
      50      250000 :   if (nplus >= n)
      51             :     {
      52      250000 :       char *mem = (char *) malloc (nplus);
      53             : 
      54      250000 :       if (mem != NULL)
      55             :         {
      56      250000 :           char *p =
      57      250000 :             (char *)((((uintptr_t)mem + sizeof (small_t) + sa_alignment_max - 1)
      58      250000 :                       & ~(uintptr_t)(2 * sa_alignment_max - 1))
      59      250000 :                      + sa_alignment_max);
      60             :           /* Here p >= mem + sizeof (small_t),
      61             :              and p <= mem + sizeof (small_t) + 2 * sa_alignment_max - 1
      62             :              hence p + n <= mem + nplus.
      63             :              So, the memory range [p, p+n) lies in the allocated memory range
      64             :              [mem, mem + nplus).  */
      65      250000 :           ((small_t *) p)[-1] = p - mem;
      66             :           /* p ≡ sa_alignment_max mod 2*sa_alignment_max.  */
      67      250000 :           return p;
      68             :         }
      69             :     }
      70             :   /* Out of memory.  */
      71           0 :   return NULL;
      72             : #else
      73             : # if !MALLOC_0_IS_NONNULL
      74             :   if (n == 0)
      75             :     n = 1;
      76             : # endif
      77             :   return malloc (n);
      78             : #endif
      79             : }
      80             : 
      81             : #if HAVE_ALLOCA
      82             : void
      83      500000 : freea (void *p)
      84             : {
      85             :   /* Check argument.  */
      86      500000 :   if ((uintptr_t) p & (sa_alignment_max - 1))
      87             :     {
      88             :       /* p was not the result of a malloca() call.  Invalid argument.  */
      89           0 :       abort ();
      90             :     }
      91             :   /* Determine whether p was a non-NULL pointer returned by mmalloca().  */
      92      500000 :   if ((uintptr_t) p & sa_alignment_max)
      93             :     {
      94      250000 :       void *mem = (char *) p - ((small_t *) p)[-1];
      95      250000 :       free (mem);
      96             :     }
      97      500000 : }
      98             : #endif
      99             : 
     100             : /*
     101             :  * Hey Emacs!
     102             :  * Local Variables:
     103             :  * coding: utf-8
     104             :  * End:
     105             :  */

Generated by: LCOV version 1.13