pkg-monitoring-plugins/gl/malloca.c

113 lines
3.6 KiB
C
Raw Normal View History

2013-11-26 22:57:29 +00:00
/* Safe automatic memory allocation.
2023-10-18 07:29:37 +00:00
Copyright (C) 2003, 2006-2007, 2009-2023 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003, 2018.
2013-11-26 22:57:29 +00:00
2023-10-18 07:29:37 +00:00
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
2013-11-26 22:57:29 +00:00
2023-10-18 07:29:37 +00:00
This file is distributed in the hope that it will be useful,
2013-11-26 22:57:29 +00:00
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2023-10-18 07:29:37 +00:00
GNU Lesser General Public License for more details.
2013-11-26 22:57:29 +00:00
2023-10-18 07:29:37 +00:00
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
2013-11-26 22:57:29 +00:00
#define _GL_USE_STDLIB_ALLOC 1
2013-11-26 22:57:29 +00:00
#include <config.h>
/* Specification. */
#include "malloca.h"
2023-10-18 07:29:37 +00:00
#include <stdckdint.h>
2023-10-18 07:29:37 +00:00
#include "idx.h"
2013-11-26 22:57:29 +00:00
/* The speed critical point in this file is freea() applied to an alloca()
result: it must be fast, to match the speed of alloca(). The speed of
mmalloca() and freea() in the other case are not critical, because they
2023-10-18 07:29:37 +00:00
are only invoked for big memory sizes.
Here we use a bit in the address as an indicator, an idea by Ondřej Bílka.
malloca() can return three types of pointers:
- Pointers 0 mod 2*sa_alignment_max come from stack allocation.
- Pointers sa_alignment_max mod 2*sa_alignment_max come from heap
allocation.
- NULL comes from a failed heap allocation. */
/* Type for holding very small pointer differences. */
typedef unsigned char small_t;
/* Verify that it is wide enough. */
static_assert (2 * sa_alignment_max - 1 <= (small_t) -1);
2013-11-26 22:57:29 +00:00
void *
mmalloca (size_t n)
{
#if HAVE_ALLOCA
2023-10-18 07:29:37 +00:00
/* Allocate one more word, used to determine the address to pass to freea(),
and room for the alignment sa_alignment_max mod 2*sa_alignment_max. */
uintptr_t alignment2_mask = 2 * sa_alignment_max - 1;
int plus = sizeof (small_t) + alignment2_mask;
idx_t nplus;
if (!ckd_add (&nplus, n, plus) && !xalloc_oversized (nplus, 1))
2013-11-26 22:57:29 +00:00
{
2023-10-18 07:29:37 +00:00
char *mem = (char *) malloc (nplus);
2013-11-26 22:57:29 +00:00
2023-10-18 07:29:37 +00:00
if (mem != NULL)
2013-11-26 22:57:29 +00:00
{
2023-10-18 07:29:37 +00:00
uintptr_t umem = (uintptr_t)mem, umemplus;
/* The ckd_add avoids signed integer overflow on
theoretical platforms where UINTPTR_MAX <= INT_MAX. */
ckd_add (&umemplus, umem, sizeof (small_t) + sa_alignment_max - 1);
idx_t offset = ((umemplus & ~alignment2_mask)
+ sa_alignment_max - umem);
void *vp = mem + offset;
small_t *p = vp;
/* Here p >= mem + sizeof (small_t),
and p <= mem + sizeof (small_t) + 2 * sa_alignment_max - 1
hence p + n <= mem + nplus.
So, the memory range [p, p+n) lies in the allocated memory range
[mem, mem + nplus). */
p[-1] = offset;
/* p ≡ sa_alignment_max mod 2*sa_alignment_max. */
2013-11-26 22:57:29 +00:00
return p;
}
}
/* Out of memory. */
return NULL;
#else
# if !MALLOC_0_IS_NONNULL
if (n == 0)
n = 1;
# endif
return malloc (n);
#endif
}
#if HAVE_ALLOCA
void
freea (void *p)
{
2023-10-18 07:29:37 +00:00
/* Check argument. */
if ((uintptr_t) p & (sa_alignment_max - 1))
2013-11-26 22:57:29 +00:00
{
2023-10-18 07:29:37 +00:00
/* p was not the result of a malloca() call. Invalid argument. */
abort ();
}
/* Determine whether p was a non-NULL pointer returned by mmalloca(). */
if ((uintptr_t) p & sa_alignment_max)
{
void *mem = (char *) p - ((small_t *) p)[-1];
free (mem);
2013-11-26 22:57:29 +00:00
}
}
#endif
2023-10-18 07:29:37 +00:00
/*
* Hey Emacs!
* Local Variables:
* coding: utf-8
* End:
*/