Postfix3.3.1
全て データ構造 ファイル 関数 変数 型定義 マクロ定義
mymalloc.c
[詳解]
1 /*++
2 /* NAME
3 /* mymalloc 3
4 /* SUMMARY
5 /* memory management wrappers
6 /* SYNOPSIS
7 /* #include <mymalloc.h>
8 /*
9 /* void *mymalloc(len)
10 /* ssize_t len;
11 /*
12 /* void *myrealloc(ptr, len)
13 /* void *ptr;
14 /* ssize_t len;
15 /*
16 /* void myfree(ptr)
17 /* void *ptr;
18 /*
19 /* char *mystrdup(str)
20 /* const char *str;
21 /*
22 /* char *mystrndup(str, len)
23 /* const char *str;
24 /* ssize_t len;
25 /*
26 /* char *mymemdup(ptr, len)
27 /* const char *ptr;
28 /* ssize_t len;
29 /* DESCRIPTION
30 /* This module performs low-level memory management with error
31 /* handling. A call of these functions either succeeds or it does
32 /* not return at all.
33 /*
34 /* To save memory, zero-length strings are shared and read-only.
35 /* The caller must not attempt to modify the null terminator.
36 /* This code is enabled unless NO_SHARED_EMPTY_STRINGS is
37 /* defined at compile time (for example, you have an sscanf()
38 /* routine that pushes characters back into its input).
39 /*
40 /* mymalloc() allocates the requested amount of memory. The memory
41 /* is not set to zero.
42 /*
43 /* myrealloc() resizes memory obtained from mymalloc() or myrealloc()
44 /* to the requested size. The result pointer value may differ from
45 /* that given via the \fIptr\fR argument.
46 /*
47 /* myfree() takes memory obtained from mymalloc() or myrealloc()
48 /* and makes it available for other use.
49 /*
50 /* mystrdup() returns a dynamic-memory copy of its null-terminated
51 /* argument. This routine uses mymalloc().
52 /*
53 /* mystrndup() returns a dynamic-memory copy of at most \fIlen\fR
54 /* leading characters of its null-terminated
55 /* argument. The result is null-terminated. This routine uses mymalloc().
56 /*
57 /* mymemdup() makes a copy of the memory pointed to by \fIptr\fR
58 /* with length \fIlen\fR. The result is NOT null-terminated.
59 /* This routine uses mymalloc().
60 /* SEE ALSO
61 /* msg(3) diagnostics interface
62 /* DIAGNOSTICS
63 /* Problems are reported via the msg(3) diagnostics routines:
64 /* the requested amount of memory is not available; improper use
65 /* is detected; other fatal errors.
66 /* LICENSE
67 /* .ad
68 /* .fi
69 /* The Secure Mailer license must be distributed with this software.
70 /* AUTHOR(S)
71 /* Wietse Venema
72 /* IBM T.J. Watson Research
73 /* P.O. Box 704
74 /* Yorktown Heights, NY 10598, USA
75 /*
76 /* Wietse Venema
77 /* Google, Inc.
78 /* 111 8th Avenue
79 /* New York, NY 10011, USA
80 /*--*/
81 
82 /* System libraries. */
83 
84 #include "sys_defs.h"
85 #include <stdlib.h>
86 #include <stddef.h>
87 #include <string.h>
88 
89 /* Application-specific. */
90 
91 #include "msg.h"
92 #include "mymalloc.h"
93 
94  /*
95  * Structure of an annotated memory block. In order to detect spurious
96  * free() calls we prepend a signature to memory given to the application.
97  * In order to detect access to free()d blocks, overwrite each block as soon
98  * as it is passed to myfree(). With the code below, the user data has
99  * integer alignment or better.
100  */
101 typedef struct MBLOCK {
102  int signature; /* set when block is active */
103  ssize_t length; /* user requested length */
104  union {
106  char payload[1]; /* actually a bunch of bytes */
107  } u;
108 } MBLOCK;
109 
110 #define SIGNATURE 0xdead
111 #define FILLER 0xff
112 
113 #define CHECK_IN_PTR(ptr, real_ptr, len, fname) { \
114  if (ptr == 0) \
115  msg_panic("%s: null pointer input", fname); \
116  real_ptr = (MBLOCK *) (ptr - offsetof(MBLOCK, u.payload[0])); \
117  if (real_ptr->signature != SIGNATURE) \
118  msg_panic("%s: corrupt or unallocated memory block", fname); \
119  real_ptr->signature = 0; \
120  if ((len = real_ptr->length) < 1) \
121  msg_panic("%s: corrupt memory block length", fname); \
122 }
123 
124 #define CHECK_OUT_PTR(ptr, real_ptr, len) { \
125  real_ptr->signature = SIGNATURE; \
126  real_ptr->length = len; \
127  ptr = real_ptr->u.payload; \
128 }
129 
130 #define SPACE_FOR(len) (offsetof(MBLOCK, u.payload[0]) + len)
131 
132  /*
133  * Optimization for short strings. We share one copy with multiple callers.
134  * This differs from normal heap memory in two ways, because the memory is
135  * shared:
136  *
137  * - It must be read-only to avoid horrible bugs. This is OK because there is
138  * no legitimate reason to modify the null terminator.
139  *
140  * - myfree() cannot overwrite the memory with a filler pattern like it can do
141  * with heap memory. Therefore, some dangling pointer bugs will be masked.
142  */
143 #ifndef NO_SHARED_EMPTY_STRINGS
144 static const char empty_string[] = "";
145 
146 #endif
147 
148 /* mymalloc - allocate memory or bust */
149 
150 void *mymalloc(ssize_t len)
151 {
152  void *ptr;
153  MBLOCK *real_ptr;
154 
155  /*
156  * Note: for safety reasons the request length is a signed type. This
157  * allows us to catch integer overflow problems that weren't already
158  * caught up-stream.
159  */
160  if (len < 1)
161  msg_panic("mymalloc: requested length %ld", (long) len);
162 #ifdef MYMALLOC_FUZZ
163  len += MYMALLOC_FUZZ;
164 #endif
165  if ((real_ptr = (MBLOCK *) malloc(SPACE_FOR(len))) == 0)
166  msg_fatal("mymalloc: insufficient memory for %ld bytes: %m",
167  (long) len);
168  CHECK_OUT_PTR(ptr, real_ptr, len);
169  memset(ptr, FILLER, len);
170  return (ptr);
171 }
172 
173 /* myrealloc - reallocate memory or bust */
174 
175 void *myrealloc(void *ptr, ssize_t len)
176 {
177  MBLOCK *real_ptr;
178  ssize_t old_len;
179 
180 #ifndef NO_SHARED_EMPTY_STRINGS
181  if (ptr == empty_string)
182  return (mymalloc(len));
183 #endif
184 
185  /*
186  * Note: for safety reasons the request length is a signed type. This
187  * allows us to catch integer overflow problems that weren't already
188  * caught up-stream.
189  */
190  if (len < 1)
191  msg_panic("myrealloc: requested length %ld", (long) len);
192 #ifdef MYMALLOC_FUZZ
193  len += MYMALLOC_FUZZ;
194 #endif
195  CHECK_IN_PTR(ptr, real_ptr, old_len, "myrealloc");
196  if ((real_ptr = (MBLOCK *) realloc((void *) real_ptr, SPACE_FOR(len))) == 0)
197  msg_fatal("myrealloc: insufficient memory for %ld bytes: %m",
198  (long) len);
199  CHECK_OUT_PTR(ptr, real_ptr, len);
200  if (len > old_len)
201  memset(ptr + old_len, FILLER, len - old_len);
202  return (ptr);
203 }
204 
205 /* myfree - release memory */
206 
207 void myfree(void *ptr)
208 {
209  MBLOCK *real_ptr;
210  ssize_t len;
211 
212 #ifndef NO_SHARED_EMPTY_STRINGS
213  if (ptr != empty_string) {
214 #endif
215  CHECK_IN_PTR(ptr, real_ptr, len, "myfree");
216  memset((void *) real_ptr, FILLER, SPACE_FOR(len));
217  free((void *) real_ptr);
218 #ifndef NO_SHARED_EMPTY_STRINGS
219  }
220 #endif
221 }
222 
223 /* mystrdup - save string to heap */
224 
225 char *mystrdup(const char *str)
226 {
227  size_t len;
228 
229  if (str == 0)
230  msg_panic("mystrdup: null pointer argument");
231 #ifndef NO_SHARED_EMPTY_STRINGS
232  if (*str == 0)
233  return ((char *) empty_string);
234 #endif
235  if ((len = strlen(str) + 1) > SSIZE_T_MAX)
236  msg_panic("mystrdup: string length >= SSIZE_T_MAX");
237  return (strcpy(mymalloc(len), str));
238 }
239 
240 /* mystrndup - save substring to heap */
241 
242 char *mystrndup(const char *str, ssize_t len)
243 {
244  char *result;
245  char *cp;
246 
247  if (str == 0)
248  msg_panic("mystrndup: null pointer argument");
249  if (len < 0)
250  msg_panic("mystrndup: requested length %ld", (long) len);
251 #ifndef NO_SHARED_EMPTY_STRINGS
252  if (*str == 0)
253  return ((char *) empty_string);
254 #endif
255  if ((cp = memchr(str, 0, len)) != 0)
256  len = cp - str;
257  result = memcpy(mymalloc(len + 1), str, len);
258  result[len] = 0;
259  return (result);
260 }
261 
262 /* mymemdup - copy memory */
263 
264 char *mymemdup(const void *ptr, ssize_t len)
265 {
266  if (ptr == 0)
267  msg_panic("mymemdup: null pointer argument");
268  return (memcpy(mymalloc(len), ptr, len));
269 }
void myfree(void *ptr)
Definition: mymalloc.c:207
char * mystrdup(const char *str)
Definition: mymalloc.c:225
ALIGN_TYPE align
Definition: mymalloc.c:105
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
void * myrealloc(void *ptr, ssize_t len)
Definition: mymalloc.c:175
#define FILLER
Definition: mymalloc.c:111
int signature
Definition: mymalloc.c:102
union MBLOCK::@4 u
char payload[1]
Definition: mymalloc.c:106
#define CHECK_OUT_PTR(ptr, real_ptr, len)
Definition: mymalloc.c:124
struct MBLOCK MBLOCK
#define SPACE_FOR(len)
Definition: mymalloc.c:130
#define CHECK_IN_PTR(ptr, real_ptr, len, fname)
Definition: mymalloc.c:113
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
char * mystrndup(const char *str, ssize_t len)
Definition: mymalloc.c:242
#define ALIGN_TYPE
Definition: sys_defs.h:1553
#define SSIZE_T_MAX
Definition: sys_defs.h:1687
char * mymemdup(const void *ptr, ssize_t len)
Definition: mymalloc.c:264
ssize_t length
Definition: mymalloc.c:103
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150