Annotation of embedaddon/libiconv/srclib/malloca.c, revision 1.1.1.3

1.1       misho       1: /* Safe automatic memory allocation.
1.1.1.3 ! misho       2:    Copyright (C) 2003, 2006-2007, 2009-2019 Free Software Foundation, Inc.
        !             3:    Written by Bruno Haible <bruno@clisp.org>, 2003, 2018.
1.1       misho       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
1.1.1.3 ! misho      16:    along with this program; if not, see <https://www.gnu.org/licenses/>.  */
1.1       misho      17: 
1.1.1.2   misho      18: #define _GL_USE_STDLIB_ALLOC 1
1.1       misho      19: #include <config.h>
                     20: 
                     21: /* Specification.  */
                     22: #include "malloca.h"
                     23: 
1.1.1.2   misho      24: #include "verify.h"
                     25: 
1.1       misho      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
1.1.1.3 ! misho      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);
1.1       misho      41: 
                     42: void *
                     43: mmalloca (size_t n)
                     44: {
                     45: #if HAVE_ALLOCA
1.1.1.3 ! misho      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:   size_t nplus = n + sizeof (small_t) + 2 * sa_alignment_max - 1;
1.1       misho      49: 
                     50:   if (nplus >= n)
                     51:     {
1.1.1.3 ! misho      52:       char *mem = (char *) malloc (nplus);
1.1       misho      53: 
1.1.1.3 ! misho      54:       if (mem != NULL)
1.1.1.2   misho      55:         {
1.1.1.3 ! misho      56:           char *p =
        !            57:             (char *)((((uintptr_t)mem + sizeof (small_t) + sa_alignment_max - 1)
        !            58:                       & ~(uintptr_t)(2 * sa_alignment_max - 1))
        !            59:                      + 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:           ((small_t *) p)[-1] = p - mem;
        !            66:           /* p ≡ sa_alignment_max mod 2*sa_alignment_max.  */
1.1.1.2   misho      67:           return p;
                     68:         }
1.1       misho      69:     }
                     70:   /* Out of memory.  */
                     71:   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: freea (void *p)
                     84: {
1.1.1.3 ! misho      85:   /* Check argument.  */
        !            86:   if ((uintptr_t) p & (sa_alignment_max - 1))
1.1       misho      87:     {
1.1.1.3 ! misho      88:       /* p was not the result of a malloca() call.  Invalid argument.  */
        !            89:       abort ();
        !            90:     }
        !            91:   /* Determine whether p was a non-NULL pointer returned by mmalloca().  */
        !            92:   if ((uintptr_t) p & sa_alignment_max)
        !            93:     {
        !            94:       void *mem = (char *) p - ((small_t *) p)[-1];
        !            95:       free (mem);
1.1       misho      96:     }
                     97: }
                     98: #endif
1.1.1.3 ! misho      99: 
        !           100: /*
        !           101:  * Hey Emacs!
        !           102:  * Local Variables:
        !           103:  * coding: utf-8
        !           104:  * End:
        !           105:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>