Sync usage with man page.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / mymalloc.c
blobecce11412f179185e89f406de150442b82d6dcab
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* mymalloc 3
6 /* SUMMARY
7 /* memory management wrappers
8 /* SYNOPSIS
9 /* #include <mymalloc.h>
11 /* char *mymalloc(len)
12 /* ssize_t len;
14 /* char *myrealloc(ptr, len)
15 /* char *ptr;
16 /* ssize_t len;
18 /* void myfree(ptr)
19 /* char *ptr;
21 /* char *mystrdup(str)
22 /* const char *str;
24 /* char *mystrndup(str, len)
25 /* const char *str;
26 /* ssize_t len;
28 /* char *mymemdup(ptr, len)
29 /* const char *ptr;
30 /* ssize_t len;
31 /* DESCRIPTION
32 /* This module performs low-level memory management with error
33 /* handling. A call of these functions either succeeds or it does
34 /* not return at all.
36 /* To save memory, zero-length strings are shared and read-only.
37 /* The caller must not attempt to modify the null terminator.
38 /* This code is enabled unless NO_SHARED_EMPTY_STRINGS is
39 /* defined at compile time (for example, you have an sscanf()
40 /* routine that pushes characters back into its input).
42 /* mymalloc() allocates the requested amount of memory. The memory
43 /* is not set to zero.
45 /* myrealloc() resizes memory obtained from mymalloc() or myrealloc()
46 /* to the requested size. The result pointer value may differ from
47 /* that given via the \fIptr\fR argument.
49 /* myfree() takes memory obtained from mymalloc() or myrealloc()
50 /* and makes it available for other use.
52 /* mystrdup() returns a dynamic-memory copy of its null-terminated
53 /* argument. This routine uses mymalloc().
55 /* mystrndup() returns a dynamic-memory copy of at most \fIlen\fR
56 /* leading characters of its null-terminated
57 /* argument. The result is null-terminated. This routine uses mymalloc().
59 /* mymemdup() makes a copy of the memory pointed to by \fIptr\fR
60 /* with length \fIlen\fR. The result is NOT null-terminated.
61 /* This routine uses mymalloc().
62 /* SEE ALSO
63 /* msg(3) diagnostics interface
64 /* DIAGNOSTICS
65 /* Problems are reported via the msg(3) diagnostics routines:
66 /* the requested amount of memory is not available; improper use
67 /* is detected; other fatal errors.
68 /* LICENSE
69 /* .ad
70 /* .fi
71 /* The Secure Mailer license must be distributed with this software.
72 /* AUTHOR(S)
73 /* Wietse Venema
74 /* IBM T.J. Watson Research
75 /* P.O. Box 704
76 /* Yorktown Heights, NY 10598, USA
77 /*--*/
79 /* System libraries. */
81 #include "sys_defs.h"
82 #include <stdlib.h>
83 #include <stddef.h>
84 #include <string.h>
86 /* Application-specific. */
88 #include "msg.h"
89 #include "mymalloc.h"
92 * Structure of an annotated memory block. In order to detect spurious
93 * free() calls we prepend a signature to memory given to the application.
94 * In order to detect access to free()d blocks, overwrite each block as soon
95 * as it is passed to myfree(). With the code below, the user data has
96 * integer alignment or better.
98 typedef struct MBLOCK {
99 int signature; /* set when block is active */
100 ssize_t length; /* user requested length */
101 union {
102 ALIGN_TYPE align;
103 char payload[1]; /* actually a bunch of bytes */
104 } u;
105 } MBLOCK;
107 #define SIGNATURE 0xdead
108 #define FILLER 0xff
110 #define CHECK_IN_PTR(ptr, real_ptr, len, fname) { \
111 if (ptr == 0) \
112 msg_panic("%s: null pointer input", fname); \
113 real_ptr = (MBLOCK *) (ptr - offsetof(MBLOCK, u.payload[0])); \
114 if (real_ptr->signature != SIGNATURE) \
115 msg_panic("%s: corrupt or unallocated memory block", fname); \
116 real_ptr->signature = 0; \
117 if ((len = real_ptr->length) < 1) \
118 msg_panic("%s: corrupt memory block length", fname); \
121 #define CHECK_OUT_PTR(ptr, real_ptr, len) { \
122 real_ptr->signature = SIGNATURE; \
123 real_ptr->length = len; \
124 ptr = real_ptr->u.payload; \
127 #define SPACE_FOR(len) (offsetof(MBLOCK, u.payload[0]) + len)
130 * Optimization for short strings. We share one copy with multiple callers.
131 * This differs from normal heap memory in two ways, because the memory is
132 * shared:
134 * - It must be read-only to avoid horrible bugs. This is OK because there is
135 * no legitimate reason to modify the null terminator.
137 * - myfree() cannot overwrite the memory with a filler pattern like it can do
138 * with heap memory. Therefore, some dangling pointer bugs will be masked.
140 #ifndef NO_SHARED_EMPTY_STRINGS
141 static const char empty_string[] = "";
143 #endif
145 /* mymalloc - allocate memory or bust */
147 char *mymalloc(ssize_t len)
149 char *ptr;
150 MBLOCK *real_ptr;
153 * Note: for safety reasons the request length is a signed type. This
154 * allows us to catch integer overflow problems that weren't already
155 * caught up-stream.
157 if (len < 1)
158 msg_panic("mymalloc: requested length %ld", (long) len);
159 if ((real_ptr = (MBLOCK *) malloc(SPACE_FOR(len))) == 0)
160 msg_fatal("mymalloc: insufficient memory: %m");
161 CHECK_OUT_PTR(ptr, real_ptr, len);
162 memset(ptr, FILLER, len);
163 return (ptr);
166 /* myrealloc - reallocate memory or bust */
168 char *myrealloc(char *ptr, ssize_t len)
170 MBLOCK *real_ptr;
171 ssize_t old_len;
173 #ifndef NO_SHARED_EMPTY_STRINGS
174 if (ptr == empty_string)
175 return (mymalloc(len));
176 #endif
179 * Note: for safety reasons the request length is a signed type. This
180 * allows us to catch integer overflow problems that weren't already
181 * caught up-stream.
183 if (len < 1)
184 msg_panic("myrealloc: requested length %ld", (long) len);
185 CHECK_IN_PTR(ptr, real_ptr, old_len, "myrealloc");
186 if ((real_ptr = (MBLOCK *) realloc((char *) real_ptr, SPACE_FOR(len))) == 0)
187 msg_fatal("myrealloc: insufficient memory: %m");
188 CHECK_OUT_PTR(ptr, real_ptr, len);
189 if (len > old_len)
190 memset(ptr + old_len, FILLER, len - old_len);
191 return (ptr);
194 /* myfree - release memory */
196 void myfree(char *ptr)
198 MBLOCK *real_ptr;
199 ssize_t len;
201 #ifndef NO_SHARED_EMPTY_STRINGS
202 if (ptr != empty_string) {
203 #endif
204 CHECK_IN_PTR(ptr, real_ptr, len, "myfree");
205 memset((char *) real_ptr, FILLER, SPACE_FOR(len));
206 free((char *) real_ptr);
207 #ifndef NO_SHARED_EMPTY_STRINGS
209 #endif
212 /* mystrdup - save string to heap */
214 char *mystrdup(const char *str)
216 if (str == 0)
217 msg_panic("mystrdup: null pointer argument");
218 #ifndef NO_SHARED_EMPTY_STRINGS
219 if (*str == 0)
220 return ((char *) empty_string);
221 #endif
222 return (strcpy(mymalloc(strlen(str) + 1), str));
225 /* mystrndup - save substring to heap */
227 char *mystrndup(const char *str, ssize_t len)
229 char *result;
230 char *cp;
232 if (str == 0)
233 msg_panic("mystrndup: null pointer argument");
234 if (len < 0)
235 msg_panic("mystrndup: requested length %ld", (long) len);
236 #ifndef NO_SHARED_EMPTY_STRINGS
237 if (*str == 0)
238 return ((char *) empty_string);
239 #endif
240 if ((cp = memchr(str, 0, len)) != 0)
241 len = cp - str;
242 result = memcpy(mymalloc(len + 1), str, len);
243 result[len] = 0;
244 return (result);
247 /* mymemdup - copy memory */
249 char *mymemdup(const char *ptr, ssize_t len)
251 if (ptr == 0)
252 msg_panic("mymemdup: null pointer argument");
253 return (memcpy(mymalloc(len), ptr, len));