Revamp xalloc interface so that it can check for address arithmetic overflow.
[gnulib.git] / lib / xmalloc.c
1 /* xmalloc.c -- malloc with out of memory checking
2
3    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4    1999, 2000, 2002, 2003 Free Software Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software Foundation,
18    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #if HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include "xalloc.h"
25
26 #include <stdbool.h>
27 #include <stdlib.h>
28
29 #include "gettext.h"
30 #define _(msgid) gettext (msgid)
31 #define N_(msgid) msgid
32
33 #include "error.h"
34 #include "exitfail.h"
35
36 #ifndef SIZE_MAX
37 # define SIZE_MAX ((size_t) -1)
38 #endif
39
40 #ifndef HAVE_MALLOC
41 "you must run the autoconf test for a GNU libc compatible malloc"
42 #endif
43
44 #ifndef HAVE_REALLOC
45 "you must run the autoconf test for a GNU libc compatible realloc"
46 #endif
47
48 /* If non NULL, call this function when memory is exhausted. */
49 void (*xalloc_fail_func) (void) = 0;
50
51 /* Return true if array of N objects, each of size S, cannot exist due
52    to arithmetic overflow.  S must be nonzero.  */
53
54 static inline bool
55 array_size_overflow (size_t n, size_t s)
56 {
57   return SIZE_MAX / s < n;
58 }
59
60 /* If XALLOC_FAIL_FUNC is NULL, or does return, display this message
61    before exiting when memory is exhausted.  Goes through gettext. */
62 char const xalloc_msg_memory_exhausted[] = N_("memory exhausted");
63
64 void
65 xalloc_die (void)
66 {
67   if (xalloc_fail_func)
68     (*xalloc_fail_func) ();
69   error (exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted));
70   /* The `noreturn' cannot be given to error, since it may return if
71      its first argument is 0.  To help compilers understand the
72      xalloc_die does terminate, call abort.  */
73   abort ();
74 }
75
76 /* Allocate an array of N objects, each with S bytes of memory,
77    dynamically, with error checking.  S must be nonzero.  */
78
79 inline void *
80 xnmalloc (size_t n, size_t s)
81 {
82   void *p;
83   if (array_size_overflow (n, s) || ! (p = malloc (n * s)))
84     xalloc_die ();
85   return p;
86 }
87
88 /* Allocate N bytes of memory dynamically, with error checking.  */
89
90 void *
91 xmalloc (size_t n)
92 {
93   return xnmalloc (n, 1);
94 }
95
96 /* Change the size of an allocated block of memory P to an array of N
97    objects each of S bytes, with error checking.  S must be nonzero.  */
98
99 inline void *
100 xnrealloc (void *p, size_t n, size_t s)
101 {
102   if (array_size_overflow (n, s) || ! (p = realloc (p, n * s)))
103     xalloc_die ();
104   return p;
105 }
106
107 /* Change the size of an allocated block of memory P to N bytes,
108    with error checking.  */
109
110 void *
111 xrealloc (void *p, size_t n)
112 {
113   return xnrealloc (p, n, 1);
114 }
115
116 /* Allocate S bytes of zeroed memory dynamically, with error checking.
117    There's no need for xnzalloc (N, S), since it would be equivalent
118    to xcalloc (N, S).  */
119
120 void *
121 xzalloc (size_t s)
122 {
123   return memset (xmalloc (s), 0, s);
124 }
125
126 /* Allocate zeroed memory for N elements of S bytes, with error
127    checking.  S must be nonzero.  */
128
129 void *
130 xcalloc (size_t n, size_t s)
131 {
132   void *p;
133   /* Test for overflow, since some calloc implementations don't have
134      proper overflow checks.  */
135   if (array_size_overflow (n, s) || ! (p = calloc (n, s)))
136     xalloc_die ();
137   return p;
138 }
139
140 /* Clone an object P of size S, with error checking.  There's no need
141    for xnclone (P, N, S), since xclone (P, N * S) works without any
142    need for an arithmetic overflow check.  */
143
144 void *
145 xclone (void const *p, size_t s)
146 {
147   return memcpy (xmalloc (s), p, s);
148 }