1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
$NetBSD: patch-ab,v 1.3 2003/11/22 15:59:24 tron Exp $
--- lib/xmalloc.c.orig Thu Nov 21 21:39:59 2002
+++ lib/xmalloc.c Sat Nov 22 16:53:38 2003
@@ -23,6 +23,7 @@
#if STDC_HEADERS
# include <stdlib.h>
+# include <string.h>
#else
void *calloc ();
void *malloc ();
@@ -43,6 +44,10 @@
/* The following tests require AC_PREREQ(2.54). */
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
#ifndef HAVE_MALLOC
"you must run the autoconf test for a GNU libc compatible malloc"
#endif
@@ -58,6 +63,15 @@
/* If non NULL, call this function when memory is exhausted. */
void (*xalloc_fail_func) PARAMS ((void)) = 0;
+/* Return true if array of N objects, each of size S, cannot exist due
+ to arithmetic overflow. S must be nonzero. */
+
+static inline int
+array_size_overflow (size_t n, size_t s)
+{
+ return SIZE_MAX / s < n;
+}
+
/* If XALLOC_FAIL_FUNC is NULL, or does return, display this message
before exiting when memory is exhausted. Goes through gettext. */
char const xalloc_msg_memory_exhausted[] = N_("memory exhausted");
@@ -70,8 +84,20 @@
error (xalloc_exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted));
/* The `noreturn' cannot be given to error, since it may return if
its first argument is 0. To help compilers understand the
- xalloc_die does terminate, call exit. */
- exit (EXIT_FAILURE);
+ xalloc_die does terminate, call abort. */
+ abort ();
+}
+
+/* Allocate an array of N objects, each with S bytes of memory,
+ dynamically, with error checking. S must be nonzero. */
+
+inline void *
+xnmalloc (size_t n, size_t s)
+{
+ void *p;
+ if (array_size_overflow (n, s) || ! (p = malloc (n * s)))
+ xalloc_die ();
+ return p;
}
/* Allocate N bytes of memory dynamically, with error checking. */
@@ -79,10 +105,16 @@
void *
xmalloc (size_t n)
{
- void *p;
+ return xnmalloc (n, 1);
+}
- p = malloc (n);
- if (p == 0)
+/* Change the size of an allocated block of memory P to an array of N
+ objects each of S bytes, with error checking. S must be nonzero. */
+
+inline void *
+xnrealloc (void *p, size_t n, size_t s)
+{
+ if (array_size_overflow (n, s) || ! (p = realloc (p, n * s)))
xalloc_die ();
return p;
}
@@ -93,21 +125,39 @@
void *
xrealloc (void *p, size_t n)
{
- p = realloc (p, n);
- if (p == 0)
- xalloc_die ();
- return p;
+ return xnrealloc (p, n, 1);
}
-/* Allocate memory for N elements of S bytes, with error checking. */
+/* Allocate S bytes of zeroed memory dynamically, with error checking.
+ There's no need for xnzalloc (N, S), since it would be equivalent
+ to xcalloc (N, S). */
+
+void *
+xzalloc (size_t s)
+{
+ return memset (xmalloc (s), 0, s);
+}
+
+/* Allocate zeroed memory for N elements of S bytes, with error
+ checking. S must be nonzero. */
void *
xcalloc (size_t n, size_t s)
{
void *p;
-
- p = calloc (n, s);
- if (p == 0)
+ /* Test for overflow, since some calloc implementations don't have
+ proper overflow checks. */
+ if (array_size_overflow (n, s) || ! (p = calloc (n, s)))
xalloc_die ();
return p;
+}
+
+/* Clone an object P of size S, with error checking. There's no need
+ for xnclone (P, N, S), since xclone (P, N * S) works without any
+ need for an arithmetic overflow check. */
+
+void *
+xclone (void const *p, size_t s)
+{
+ return memcpy (xmalloc (s), p, s);
}
|