(root)/
strace-6.5/
src/
xmalloc.c
       1  /*
       2   * Copyright (c) 2015 Dmitry V. Levin <ldv@strace.io>
       3   * Copyright (c) 2015-2021 The strace developers.
       4   * All rights reserved.
       5   *
       6   * SPDX-License-Identifier: LGPL-2.1-or-later
       7   */
       8  
       9  #ifdef HAVE_CONFIG_H
      10  # include "config.h"
      11  #endif
      12  
      13  #include <stdarg.h>
      14  #include <stdio.h>
      15  #include <stdlib.h>
      16  #include <string.h>
      17  
      18  #include "error_prints.h"
      19  #include "macros.h"
      20  #include "xmalloc.h"
      21  
      22  static void
      23  die_out_of_memory(void)
      24  {
      25  	static int recursed;
      26  
      27  	if (recursed)
      28  		exit(1);
      29  	recursed = 1;
      30  
      31  	error_msg_and_die("Out of memory");
      32  }
      33  
      34  void *
      35  xmalloc(size_t size)
      36  {
      37  	void *p = malloc(size);
      38  
      39  	if (!p)
      40  		die_out_of_memory();
      41  
      42  	return p;
      43  }
      44  
      45  void *
      46  xcalloc(size_t nmemb, size_t size)
      47  {
      48  	void *p = calloc(nmemb, size);
      49  
      50  	if (!p)
      51  		die_out_of_memory();
      52  
      53  	return p;
      54  }
      55  
      56  #define HALF_SIZE_T	(((size_t) 1) << (sizeof(size_t) * 4))
      57  
      58  void *
      59  xallocarray(size_t nmemb, size_t size)
      60  {
      61  	size_t bytes = nmemb * size;
      62  
      63  	if ((nmemb | size) >= HALF_SIZE_T &&
      64  	    size && bytes / size != nmemb)
      65  		die_out_of_memory();
      66  
      67  	void *p = malloc(bytes);
      68  
      69  	if (!p)
      70  		die_out_of_memory();
      71  
      72  	return p;
      73  }
      74  
      75  void *
      76  xreallocarray(void *ptr, size_t nmemb, size_t size)
      77  {
      78  	size_t bytes = nmemb * size;
      79  
      80  	if ((nmemb | size) >= HALF_SIZE_T &&
      81  	    size && bytes / size != nmemb)
      82  		die_out_of_memory();
      83  
      84  	void *p = realloc(ptr, bytes);
      85  
      86  	if (!p)
      87  		die_out_of_memory();
      88  
      89  	return p;
      90  }
      91  
      92  void *
      93  xgrowarray(void *const ptr, size_t *const nmemb, const size_t memb_size)
      94  {
      95  	/* this is the same value as glibc DEFAULT_MXFAST */
      96  	enum { DEFAULT_ALLOC_SIZE = 64 * SIZEOF_LONG / 4 };
      97  
      98  	size_t grow_memb;
      99  
     100  	if (ptr == NULL)
     101  		grow_memb = *nmemb ? 0 :
     102  			ROUNDUP_DIV(DEFAULT_ALLOC_SIZE, memb_size);
     103  	else
     104  		grow_memb = (*nmemb >> 1) + 1;
     105  
     106  	if ((*nmemb + grow_memb) < *nmemb)
     107  		die_out_of_memory();
     108  
     109  	*nmemb += grow_memb;
     110  
     111  	return xreallocarray(ptr, *nmemb, memb_size);
     112  }
     113  
     114  char *
     115  xstrdup(const char *str)
     116  {
     117  	if (!str)
     118  		return NULL;
     119  
     120  	char *p = strdup(str);
     121  
     122  	if (!p)
     123  		die_out_of_memory();
     124  
     125  	return p;
     126  }
     127  
     128  char *
     129  xstrndup(const char *str, size_t n)
     130  {
     131  	char *p;
     132  
     133  	if (!str)
     134  		return NULL;
     135  
     136  #ifdef HAVE_STRNDUP
     137  	p = strndup(str, n);
     138  #else
     139  	p = xmalloc(n + 1);
     140  #endif
     141  
     142  	if (!p)
     143  		die_out_of_memory();
     144  
     145  #ifndef HAVE_STRNDUP
     146  	strncpy(p, str, n);
     147  	p[n] = '\0';
     148  #endif
     149  
     150  	return p;
     151  }
     152  
     153  void *
     154  xmemdup(const void *src, size_t size)
     155  {
     156  	if (!src)
     157  		return NULL;
     158  
     159  	return memcpy(xmalloc(size), src, size);
     160  }
     161  
     162  void *
     163  xarraydup(const void *src, size_t nmemb, size_t memb_size)
     164  {
     165  	if (!src)
     166  		return NULL;
     167  
     168  	/* (nmemb * memb_size) checks are already done inside xallocarray */
     169  	return memcpy(xallocarray(nmemb, memb_size), src, nmemb * memb_size);
     170  }
     171  
     172  char *
     173  xasprintf(const char *fmt, ...)
     174  {
     175  	va_list ap;
     176  	va_start(ap, fmt);
     177  
     178  	char *res;
     179  	if (vasprintf(&res, fmt, ap) < 0)
     180  		die_out_of_memory();
     181  
     182  	va_end(ap);
     183  	return res;
     184  }