Initial commit to Gerrit
[profile/ivi/ntp.git] / ElectricFence / efence.c
1 /*
2  * Electric Fence - Red-Zone memory allocator.
3  * Bruce Perens, 1988, 1993
4  * 
5  * This is a special version of malloc() and company for debugging software
6  * that is suspected of overrunning or underrunning the boundaries of a
7  * malloc buffer, or touching free memory.
8  *
9  * It arranges for each malloc buffer to be followed (or preceded)
10  * in the address space by an inaccessable virtual memory page,
11  * and for free memory to be inaccessable. If software touches the
12  * inaccessable page, it will get an immediate segmentation
13  * fault. It is then trivial to uncover the offending code using a debugger.
14  *
15  * An advantage of this product over most malloc debuggers is that this one
16  * detects reading out of bounds as well as writing, and this one stops on
17  * the exact instruction that causes the error, rather than waiting until the
18  * next boundary check.
19  *
20  * There is one product that debugs malloc buffer overruns
21  * better than Electric Fence: "Purify" from Purify Systems, and that's only
22  * a small part of what Purify does. I'm not affiliated with Purify, I just
23  * respect a job well done.
24  *
25  * This version of malloc() should not be linked into production software,
26  * since it tremendously increases the time and memory overhead of malloc().
27  * Each malloc buffer will consume a minimum of two virtual memory pages,
28  * this is 16 kilobytes on many systems. On some systems it will be necessary
29  * to increase the amount of swap space in order to debug large programs that
30  * perform lots of allocation, because of the per-buffer overhead.
31  */
32 #include "efence.h"
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <memory.h>
36 #include <string.h>
37
38 #ifdef  malloc
39 #undef  malloc
40 #endif
41
42 #ifdef  calloc
43 #undef  calloc
44 #endif
45
46 static const char       version[] = "\n  Electric Fence 2.0.5"
47  " Copyright (C) 1987-1995 Bruce Perens.\n";
48
49 /*
50  * MEMORY_CREATION_SIZE is the amount of memory to get from the operating
51  * system at one time. We'll break that memory down into smaller pieces for
52  * malloc buffers. One megabyte is probably a good value.
53  */
54 #define                 MEMORY_CREATION_SIZE    1024 * 1024
55
56 /*
57  * Enum Mode indicates the status of a malloc buffer.
58  */
59 enum _Mode {
60         NOT_IN_USE = 0, /* Available to represent a malloc buffer. */
61         FREE,           /* A free buffer. */
62         ALLOCATED,      /* A buffer that is in use. */
63         PROTECTED,      /* A freed buffer that can not be allocated again. */
64         INTERNAL_USE    /* A buffer used internally by malloc(). */
65 };
66 typedef enum _Mode      Mode;
67
68 /*
69  * Struct Slot contains all of the information about a malloc buffer except
70  * for the contents of its memory.
71  */
72 struct _Slot {
73         void *          userAddress;
74         void *          internalAddress;
75         size_t          userSize;
76         size_t          internalSize;
77         Mode            mode;
78 };
79 typedef struct _Slot    Slot;
80
81 /*
82  * EF_ALIGNMENT is a global variable used to control the default alignment
83  * of buffers returned by malloc(), calloc(), and realloc(). It is all-caps
84  * so that its name matches the name of the environment variable that is used
85  * to set it. This gives the programmer one less name to remember.
86  * If the value is -1, it will be set from the environment or sizeof(int)
87  * at run time.
88  */
89 int             EF_ALIGNMENT = -1;
90
91 /*
92  * EF_PROTECT_FREE is a global variable used to control the disposition of
93  * memory that is released using free(). It is all-caps so that its name
94  * matches the name of the environment variable that is used to set it.
95  * If its value is greater non-zero, memory released by free is made
96  * inaccessable and never allocated again. Any software that touches free
97  * memory will then get a segmentation fault. If its value is zero, freed
98  * memory will be available for reallocation, but will still be inaccessable
99  * until it is reallocated.
100  * If the value is -1, it will be set from the environment or to 0 at run-time.
101  */
102 int             EF_PROTECT_FREE = -1;
103
104 /*
105  * EF_PROTECT_BELOW is used to modify the behavior of the allocator. When
106  * its value is non-zero, the allocator will place an inaccessable page
107  * immediately _before_ the malloc buffer in the address space, instead
108  * of _after_ it. Use this to detect malloc buffer under-runs, rather than
109  * over-runs. It won't detect both at the same time, so you should test your
110  * software twice, once with this value clear, and once with it set.
111  * If the value is -1, it will be set from the environment or to zero at
112  * run-time
113  */
114 int             EF_PROTECT_BELOW = -1;
115
116 /*
117  * EF_ALLOW_MALLOC_0 is set if Electric Fence is to allow malloc(0). I
118  * trap malloc(0) by default because it is a common source of bugs.
119  */
120 int             EF_ALLOW_MALLOC_0 = -1;
121
122 /*
123  * allocationList points to the array of slot structures used to manage the
124  * malloc arena.
125  */
126 static Slot *           allocationList = 0;
127
128 /*
129  * allocationListSize is the size of the allocation list. This will always
130  * be a multiple of the page size.
131  */
132 static size_t           allocationListSize = 0;
133
134 /*
135  * slotCount is the number of Slot structures in allocationList.
136  */
137 static size_t           slotCount = 0;
138
139 /*
140  * unUsedSlots is the number of Slot structures that are currently available
141  * to represent new malloc buffers. When this number gets too low, we will
142  * create new slots.
143  */
144 static size_t           unUsedSlots = 0;
145
146 /*
147  * slotsPerPage is the number of slot structures that fit in a virtual
148  * memory page.
149  */
150 static size_t           slotsPerPage = 0;
151
152 /*
153  * internalUse is set when allocating and freeing the allocatior-internal
154  * data structures.
155  */
156 static int              internalUse = 0;
157
158 /*
159  * noAllocationListProtection is set to tell malloc() and free() not to
160  * manipulate the protection of the allocation list. This is only set in
161  * realloc(), which does it to save on slow system calls, and in
162  * allocateMoreSlots(), which does it because it changes the allocation list.
163  */
164 static int              noAllocationListProtection = 0;
165
166 /*
167  * bytesPerPage is set at run-time to the number of bytes per virtual-memory
168  * page, as returned by Page_Size().
169  */
170 static size_t           bytesPerPage = 0;
171
172 /*
173  * internalError is called for those "shouldn't happen" errors in the
174  * allocator.
175  */
176 static void
177 internalError(void)
178 {
179         EF_Abort("Internal error in allocator.");
180 }
181
182 /*
183  * initialize sets up the memory allocation arena and the run-time
184  * configuration information.
185  */
186 static void
187 initialize(void)
188 {
189         size_t  size = MEMORY_CREATION_SIZE;
190         size_t  slack;
191         char *  string;
192         Slot *  slot;
193
194         EF_Print(version);
195
196         /*
197          * Import the user's environment specification of the default
198          * alignment for malloc(). We want that alignment to be under
199          * user control, since smaller alignment lets us catch more bugs,
200          * however some software will break if malloc() returns a buffer
201          * that is not word-aligned.
202          *
203          * I would like
204          * alignment to be zero so that we could catch all one-byte
205          * overruns, however if malloc() is asked to allocate an odd-size
206          * buffer and returns an address that is not word-aligned, or whose
207          * size is not a multiple of the word size, software breaks.
208          * This was the case with the Sun string-handling routines,
209          * which can do word fetches up to three bytes beyond the end of a
210          * string. I handle this problem in part by providing
211          * byte-reference-only versions of the string library functions, but
212          * there are other functions that break, too. Some in X Windows, one
213          * in Sam Leffler's TIFF library, and doubtless many others.
214          */
215         if ( EF_ALIGNMENT == -1 ) {
216                 if ( (string = getenv("EF_ALIGNMENT")) != 0 )
217                         EF_ALIGNMENT = (size_t)atoi(string);
218                 else
219                         EF_ALIGNMENT = sizeof(int);
220         }
221
222         /*
223          * See if the user wants to protect the address space below a buffer,
224          * rather than that above a buffer.
225          */
226         if ( EF_PROTECT_BELOW == -1 ) {
227                 if ( (string = getenv("EF_PROTECT_BELOW")) != 0 )
228                         EF_PROTECT_BELOW = (atoi(string) != 0);
229                 else
230                         EF_PROTECT_BELOW = 0;
231         }
232
233         /*
234          * See if the user wants to protect memory that has been freed until
235          * the program exits, rather than until it is re-allocated.
236          */
237         if ( EF_PROTECT_FREE == -1 ) {
238                 if ( (string = getenv("EF_PROTECT_FREE")) != 0 )
239                         EF_PROTECT_FREE = (atoi(string) != 0);
240                 else
241                         EF_PROTECT_FREE = 0;
242         }
243
244         /*
245          * See if the user wants to allow malloc(0).
246          */
247         if ( EF_ALLOW_MALLOC_0 == -1 ) {
248                 if ( (string = getenv("EF_ALLOW_MALLOC_0")) != 0 )
249                         EF_ALLOW_MALLOC_0 = (atoi(string) != 0);
250                 else
251                         EF_ALLOW_MALLOC_0 = 0;
252         }
253
254         /*
255          * Get the run-time configuration of the virtual memory page size.
256          */
257         bytesPerPage = Page_Size();
258
259         /*
260          * Figure out how many Slot structures to allocate at one time.
261          */
262         slotCount = slotsPerPage = bytesPerPage / sizeof(Slot);
263         allocationListSize = bytesPerPage;
264
265         if ( allocationListSize > size )
266                 size = allocationListSize;
267
268         if ( (slack = size % bytesPerPage) != 0 )
269                 size += bytesPerPage - slack;
270
271         /*
272          * Allocate memory, and break it up into two malloc buffers. The
273          * first buffer will be used for Slot structures, the second will
274          * be marked free.
275          */
276         slot = allocationList = (Slot *)Page_Create(size);
277         memset((char *)allocationList, 0, allocationListSize);
278
279         slot[0].internalSize = slot[0].userSize = allocationListSize;
280         slot[0].internalAddress = slot[0].userAddress = allocationList;
281         slot[0].mode = INTERNAL_USE;
282         if ( size > allocationListSize ) {
283                 slot[1].internalAddress = slot[1].userAddress
284                  = ((char *)slot[0].internalAddress) + slot[0].internalSize;
285                 slot[1].internalSize
286                  = slot[1].userSize = size - slot[0].internalSize;
287                 slot[1].mode = FREE;
288         }
289
290         /*
291          * Deny access to the free page, so that we will detect any software
292          * that treads upon free memory.
293          */
294         Page_DenyAccess(slot[1].internalAddress, slot[1].internalSize);
295
296         /*
297          * Account for the two slot structures that we've used.
298          */
299         unUsedSlots = slotCount - 2;
300 }
301
302 /*
303  * allocateMoreSlots is called when there are only enough slot structures
304  * left to support the allocation of a single malloc buffer.
305  */
306 static void
307 allocateMoreSlots(void)
308 {
309         size_t  newSize = allocationListSize + bytesPerPage;
310         void *  newAllocation;
311         void *  oldAllocation = allocationList;
312
313         Page_AllowAccess(allocationList, allocationListSize);
314         noAllocationListProtection = 1;
315         internalUse = 1;
316
317         newAllocation = malloc(newSize);
318         memcpy(newAllocation, allocationList, allocationListSize);
319         memset(&(((char *)newAllocation)[allocationListSize]), 0, bytesPerPage);
320
321         allocationList = (Slot *)newAllocation;
322         allocationListSize = newSize;
323         slotCount += slotsPerPage;
324         unUsedSlots += slotsPerPage;
325
326         free(oldAllocation);
327
328         /*
329          * Keep access to the allocation list open at this point, because
330          * I am returning to memalign(), which needs that access.
331          */
332         noAllocationListProtection = 0;
333         internalUse = 0;
334 }
335
336 /*
337  * This is the memory allocator. When asked to allocate a buffer, allocate
338  * it in such a way that the end of the buffer is followed by an inaccessable
339  * memory page. If software overruns that buffer, it will touch the bad page
340  * and get an immediate segmentation fault. It's then easy to zero in on the
341  * offending code with a debugger.
342  *
343  * There are a few complications. If the user asks for an odd-sized buffer,
344  * we would have to have that buffer start on an odd address if the byte after
345  * the end of the buffer was to be on the inaccessable page. Unfortunately,
346  * there is lots of software that asks for odd-sized buffers and then
347  * requires that the returned address be word-aligned, or the size of the
348  * buffer be a multiple of the word size. An example are the string-processing
349  * functions on Sun systems, which do word references to the string memory
350  * and may refer to memory up to three bytes beyond the end of the string.
351  * For this reason, I take the alignment requests to memalign() and valloc()
352  * seriously, and 
353  * 
354  * Electric Fence wastes lots of memory. I do a best-fit allocator here
355  * so that it won't waste even more. It's slow, but thrashing because your
356  * working set is too big for a system's RAM is even slower. 
357  */
358 extern C_LINKAGE void *
359 memalign(size_t alignment, size_t userSize)
360 {
361         register Slot * slot;
362         register size_t count;
363         Slot *          fullSlot = 0;
364         Slot *          emptySlots[2];
365         size_t          internalSize;
366         size_t          slack;
367         char *          address;
368
369         if ( allocationList == 0 )
370                 initialize();
371
372         if ( userSize == 0 && !EF_ALLOW_MALLOC_0 )
373                 EF_Abort("Allocating 0 bytes, probably a bug.");
374
375         /*
376          * If EF_PROTECT_BELOW is set, all addresses returned by malloc()
377          * and company will be page-aligned.
378          */
379         if ( !EF_PROTECT_BELOW && alignment > 1 ) {
380                 if ( (slack = userSize % alignment) != 0 )
381                         userSize += alignment - slack;
382         }
383
384         /*
385          * The internal size of the buffer is rounded up to the next page-size
386          * boudary, and then we add another page's worth of memory for the
387          * dead page.
388          */
389         internalSize = userSize + bytesPerPage;
390         if ( (slack = internalSize % bytesPerPage) != 0 )
391                 internalSize += bytesPerPage - slack;
392
393         /*
394          * These will hold the addresses of two empty Slot structures, that
395          * can be used to hold information for any memory I create, and any
396          * memory that I mark free.
397          */
398         emptySlots[0] = 0;
399         emptySlots[1] = 0;
400
401         /*
402          * The internal memory used by the allocator is currently
403          * inaccessable, so that errant programs won't scrawl on the
404          * allocator's arena. I'll un-protect it here so that I can make
405          * a new allocation. I'll re-protect it before I return.
406          */
407         if ( !noAllocationListProtection )
408                 Page_AllowAccess(allocationList, allocationListSize);
409
410         /*
411          * If I'm running out of empty slots, create some more before
412          * I don't have enough slots left to make an allocation.
413          */
414         if ( !internalUse && unUsedSlots < 7 ) {
415                 allocateMoreSlots();
416         }
417         
418         /*
419          * Iterate through all of the slot structures. Attempt to find a slot
420          * containing free memory of the exact right size. Accept a slot with
421          * more memory than we want, if the exact right size is not available.
422          * Find two slot structures that are not in use. We will need one if
423          * we split a buffer into free and allocated parts, and the second if
424          * we have to create new memory and mark it as free.
425          *
426          */
427         
428         for ( slot = allocationList, count = slotCount ; count > 0; count-- ) {
429                 if ( slot->mode == FREE
430                  && slot->internalSize >= internalSize ) {
431                         if ( !fullSlot
432                          ||slot->internalSize < fullSlot->internalSize){
433                                 fullSlot = slot;
434                                 if ( slot->internalSize == internalSize
435                                  && emptySlots[0] )
436                                         break;  /* All done, */
437                         }
438                 }
439                 else if ( slot->mode == NOT_IN_USE ) {
440                         if ( !emptySlots[0] )
441                                 emptySlots[0] = slot;
442                         else if ( !emptySlots[1] )
443                                 emptySlots[1] = slot;
444                         else if ( fullSlot
445                          && fullSlot->internalSize == internalSize )
446                                 break;  /* All done. */
447                 }
448                 slot++;
449         }
450         if ( !emptySlots[0] )
451                 internalError();
452
453         if ( !fullSlot ) {
454                 /*
455                  * I get here if I haven't been able to find a free buffer
456                  * with all of the memory I need. I'll have to create more
457                  * memory. I'll mark it all as free, and then split it into
458                  * free and allocated portions later.
459                  */
460                 size_t  chunkSize = MEMORY_CREATION_SIZE;
461
462                 if ( !emptySlots[1] )
463                         internalError();
464
465                 if ( chunkSize < internalSize )
466                         chunkSize = internalSize;
467
468                 if ( (slack = chunkSize % bytesPerPage) != 0 )
469                         chunkSize += bytesPerPage - slack;
470
471                 /* Use up one of the empty slots to make the full slot. */
472                 fullSlot = emptySlots[0];
473                 emptySlots[0] = emptySlots[1];
474                 fullSlot->internalAddress = Page_Create(chunkSize);
475                 fullSlot->internalSize = chunkSize;
476                 fullSlot->mode = FREE;
477                 unUsedSlots--;
478         }
479
480         /*
481          * If I'm allocating memory for the allocator's own data structures,
482          * mark it INTERNAL_USE so that no errant software will be able to
483          * free it.
484          */
485         if ( internalUse )
486                 fullSlot->mode = INTERNAL_USE;
487         else
488                 fullSlot->mode = ALLOCATED;
489
490         /*
491          * If the buffer I've found is larger than I need, split it into
492          * an allocated buffer with the exact amount of memory I need, and
493          * a free buffer containing the surplus memory.
494          */
495         if ( fullSlot->internalSize > internalSize ) {
496                 emptySlots[0]->internalSize
497                  = fullSlot->internalSize - internalSize;
498                 emptySlots[0]->internalAddress
499                  = ((char *)fullSlot->internalAddress) + internalSize;
500                 emptySlots[0]->mode = FREE;
501                 fullSlot->internalSize = internalSize;
502                 unUsedSlots--;
503         }
504
505         if ( !EF_PROTECT_BELOW ) {
506                 /*
507                  * Arrange the buffer so that it is followed by an inaccessable
508                  * memory page. A buffer overrun that touches that page will
509                  * cause a segmentation fault.
510                  */
511                 address = (char *)fullSlot->internalAddress;
512
513                 /* Set up the "live" page. */
514                 if ( internalSize - bytesPerPage > 0 )
515                                 Page_AllowAccess(
516                                  fullSlot->internalAddress
517                                 ,internalSize - bytesPerPage);
518                         
519                 address += internalSize - bytesPerPage;
520
521                 /* Set up the "dead" page. */
522                 if ( EF_PROTECT_FREE )
523                         Page_Delete(address, bytesPerPage);
524                 else
525                         Page_DenyAccess(address, bytesPerPage);
526
527                 /* Figure out what address to give the user. */
528                 address -= userSize;
529         }
530         else {  /* EF_PROTECT_BELOW != 0 */
531                 /*
532                  * Arrange the buffer so that it is preceded by an inaccessable
533                  * memory page. A buffer underrun that touches that page will
534                  * cause a segmentation fault.
535                  */
536                 address = (char *)fullSlot->internalAddress;
537
538                 /* Set up the "dead" page. */
539                 if ( EF_PROTECT_FREE )
540                         Page_Delete(address, bytesPerPage);
541                 else
542                         Page_DenyAccess(address, bytesPerPage);
543                         
544                 address += bytesPerPage;
545
546                 /* Set up the "live" page. */
547                 if ( internalSize - bytesPerPage > 0 )
548                         Page_AllowAccess(address, internalSize - bytesPerPage);
549         }
550
551         fullSlot->userAddress = address;
552         fullSlot->userSize = userSize;
553
554         /*
555          * Make the pool's internal memory inaccessable, so that the program
556          * being debugged can't stomp on it.
557          */
558         if ( !internalUse )
559                 Page_DenyAccess(allocationList, allocationListSize);
560
561         return address;
562 }
563
564 /*
565  * Find the slot structure for a user address.
566  */
567 static Slot *
568 slotForUserAddress(void * address)
569 {
570         register Slot * slot = allocationList;
571         register size_t count = slotCount;
572         
573         for ( ; count > 0; count-- ) {
574                 if ( slot->userAddress == address )
575                         return slot;
576                 slot++;
577         }
578
579         return 0;
580 }
581
582 /*
583  * Find the slot structure for an internal address.
584  */
585 static Slot *
586 slotForInternalAddress(void * address)
587 {
588         register Slot * slot = allocationList;
589         register size_t count = slotCount;
590         
591         for ( ; count > 0; count-- ) {
592                 if ( slot->internalAddress == address )
593                         return slot;
594                 slot++;
595         }
596         return 0;
597 }
598
599 /*
600  * Given the internal address of a buffer, find the buffer immediately
601  * before that buffer in the address space. This is used by free() to
602  * coalesce two free buffers into one.
603  */
604 static Slot *
605 slotForInternalAddressPreviousTo(void * address)
606 {
607         register Slot * slot = allocationList;
608         register size_t count = slotCount;
609         
610         for ( ; count > 0; count-- ) {
611                 if ( ((char *)slot->internalAddress)
612                  + slot->internalSize == address )
613                         return slot;
614                 slot++;
615         }
616         return 0;
617 }
618
619 extern C_LINKAGE void
620 free(void * address)
621 {
622         Slot *  slot;
623         Slot *  previousSlot = 0;
624         Slot *  nextSlot = 0;
625
626         if ( address == 0 )
627                 return;
628
629         if ( allocationList == 0 )
630                 EF_Abort("free() called before first malloc().");
631
632         if ( !noAllocationListProtection )
633                 Page_AllowAccess(allocationList, allocationListSize);
634
635         slot = slotForUserAddress(address);
636
637         if ( !slot )
638                 EF_Abort("free(%a): address not from malloc().", address);
639
640         if ( slot->mode != ALLOCATED ) {
641                 if ( internalUse && slot->mode == INTERNAL_USE )
642                         /* Do nothing. */;
643                 else {
644                         EF_Abort(
645                          "free(%a): freeing free memory."
646                         ,address);
647                 }
648         }
649
650         if ( EF_PROTECT_FREE )
651                 slot->mode = PROTECTED;
652         else
653                 slot->mode = FREE;
654
655         previousSlot = slotForInternalAddressPreviousTo(slot->internalAddress);
656         nextSlot = slotForInternalAddress(
657          ((char *)slot->internalAddress) + slot->internalSize);
658
659         if ( previousSlot
660          && (previousSlot->mode == FREE || previousSlot->mode == PROTECTED) ) {
661                 /* Coalesce previous slot with this one. */
662                 previousSlot->internalSize += slot->internalSize;
663                 if ( EF_PROTECT_FREE )
664                         previousSlot->mode = PROTECTED;
665
666                 slot->internalAddress = slot->userAddress = 0;
667                 slot->internalSize = slot->userSize = 0;
668                 slot->mode = NOT_IN_USE;
669                 slot = previousSlot;
670                 unUsedSlots++;
671         }
672         if ( nextSlot
673          && (nextSlot->mode == FREE || nextSlot->mode == PROTECTED) ) {
674                 /* Coalesce next slot with this one. */
675                 slot->internalSize += nextSlot->internalSize;
676                 nextSlot->internalAddress = nextSlot->userAddress = 0;
677                 nextSlot->internalSize = nextSlot->userSize = 0;
678                 nextSlot->mode = NOT_IN_USE;
679                 unUsedSlots++;
680         }
681
682         slot->userAddress = slot->internalAddress;
683         slot->userSize = slot->internalSize;
684
685         /*
686          * Free memory is _always_ set to deny access. When EF_PROTECT_FREE
687          * is true, free memory is never reallocated, so it remains access
688          * denied for the life of the process. When EF_PROTECT_FREE is false, 
689          * the memory may be re-allocated, at which time access to it will be
690          * allowed again.
691          *
692          * Some operating systems allow munmap() with single-page resolution,
693          * and allow you to un-map portions of a region, rather than the
694          * entire region that was mapped with mmap(). On those operating
695          * systems, we can release protected free pages with Page_Delete(),
696          * in the hope that the swap space attached to those pages will be
697          * released as well.
698          */
699         if ( EF_PROTECT_FREE )
700             Page_Delete(slot->internalAddress, slot->internalSize);
701         else
702             Page_DenyAccess(slot->internalAddress, slot->internalSize);
703
704         if ( !noAllocationListProtection )
705                 Page_DenyAccess(allocationList, allocationListSize);
706 }
707
708 extern C_LINKAGE void *
709 realloc(void * oldBuffer, size_t newSize)
710 {
711         void *  newBuffer = malloc(newSize);
712
713         if ( oldBuffer ) {
714                 size_t  size;
715                 Slot *  slot;
716
717                 Page_AllowAccess(allocationList, allocationListSize);
718                 noAllocationListProtection = 1;
719                 
720                 slot = slotForUserAddress(oldBuffer);
721
722                 if ( slot == 0 )
723                         EF_Abort(
724                          "realloc(%a, %d): address not from malloc()."
725                         ,oldBuffer
726                         ,newSize);
727
728                 if ( newSize < (size = slot->userSize) )
729                         size = newSize;
730
731                 if ( size > 0 )
732                         memcpy(newBuffer, oldBuffer, size);
733
734                 free(oldBuffer);
735                 noAllocationListProtection = 0;
736                 Page_DenyAccess(allocationList, allocationListSize);
737
738                 if ( size < newSize )
739                         memset(&(((char *)newBuffer)[size]), 0, newSize - size);
740                 
741                 /* Internal memory was re-protected in free() */
742         }
743
744         return newBuffer;
745 }
746
747 extern C_LINKAGE void *
748 malloc(size_t size)
749 {
750         if ( allocationList == 0 )
751                 initialize();   /* This sets EF_ALIGNMENT */
752
753         return memalign(EF_ALIGNMENT, size);
754 }
755
756 extern C_LINKAGE void *
757 calloc(size_t nelem, size_t elsize)
758 {
759         size_t  size = nelem * elsize;
760         void *  allocation = malloc(size);
761
762         memset(allocation, 0, size);
763         return allocation;
764 }
765
766 /*
767  * This will catch more bugs if you remove the page alignment, but it
768  * will break some software.
769  */
770 extern C_LINKAGE void *
771 valloc (size_t size)
772 {
773         return memalign(bytesPerPage, size);
774 }
775
776 #ifdef __hpux
777 /*
778  * HP-UX 8/9.01 strcat reads a word past source when doing unaligned copies!
779  * Work around it here. The bug report has been filed with HP.
780  */
781 char *strcat(char *d, const char *s)
782 {
783         strcpy(d+strlen(d), s);
784         return d;
785 }
786 #endif