/*++ /* NAME /* mymalloc 3 /* SUMMARY /* memory management wrappers /* SYNOPSIS /* #include <mymalloc.h> /* /* char *mymalloc(len) /* int len; /* /* char *myrealloc(ptr, len) /* char *ptr; /* int len; /* /* void myfree(ptr) /* char *ptr; /* /* char *mystrdup(str) /* const char *str; /* /* char *mystrndup(str, len) /* const char *str; /* int len; /* /* char *mymemdup(ptr, len) /* const char *ptr; /* int len; /* DESCRIPTION /* This module performs low-level memory management with error /* handling. A call of these functions either succeeds or it does /* not return at all. /* /* mymalloc() allocates the requested amount of memory. The memory /* is not set to zero. /* /* myrealloc() resizes memory obtained from mymalloc() or myrealloc() /* to the requested size. The result pointer value may differ from /* that given via the \fIptr\fR argument. /* /* myfree() takes memory obtained from mymalloc() or myrealloc() /* and makes it available for other use. /* /* mystrdup() returns a dynamic-memory copy of its null-terminated /* argument. This routine uses mymalloc(). /* /* mystrndup() returns a dynamic-memory copy of at most \fIlen\fR /* leading characters of its null-terminated /* argument. The result is null-terminated. This routine uses mymalloc(). /* /* mymemdup() makes a copy of the memory pointed to by \fIptr\fR /* with length \fIlen\fR. The result is NOT null-terminated. /* This routine uses mymalloc(). /* SEE ALSO /* msg(3) diagnostics interface /* DIAGNOSTICS /* Problems are reported via the msg(3) diagnostics routines: /* the requested amount of memory is not available; improper use /* is detected; other fatal errors. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System libraries. */ #include "sys_defs.h" #include <stdlib.h> #include <stddef.h> #include <string.h> /* Application-specific. */ #include "msg.h" #include "mymalloc.h" /* * Structure of an annotated memory block. In order to detect spurious * free() calls we prepend a signature to memory given to the application. * In order to detect access to free()d blocks, overwrite each block as soon * as it is passed to myfree(). With the code below, the user data has * integer alignment or better. */ typedef struct MBLOCK { int signature; /* set when block is active */ int length; /* user requested length */ union { ALIGN_TYPE align; char payload[1]; /* actually a bunch of bytes */ } u; } MBLOCK; #define SIGNATURE 0xdead #define FILLER 0xff #define CHECK_IN_PTR(ptr, real_ptr, len, fname) { \ if (ptr == 0) \ msg_panic("%s: null pointer input", fname); \ real_ptr = (MBLOCK *) (ptr - offsetof(MBLOCK, u.payload[0])); \ if (real_ptr->signature != SIGNATURE) \ msg_panic("%s: corrupt or unallocated memory block", fname); \ real_ptr->signature = 0; \ if ((len = real_ptr->length) < 1) \ msg_panic("%s: corrupt memory block length", fname); \ } #define CHECK_OUT_PTR(ptr, real_ptr, len) { \ real_ptr->signature = SIGNATURE; \ real_ptr->length = len; \ ptr = real_ptr->u.payload; \ } #define SPACE_FOR(len) (offsetof(MBLOCK, u.payload[0]) + len) /* mymalloc - allocate memory or bust */ char *mymalloc(int len) { char *ptr; MBLOCK *real_ptr; if (len < 1) msg_panic("mymalloc: requested length %d", len); if ((real_ptr = (MBLOCK *) malloc(SPACE_FOR(len))) == 0) msg_fatal("mymalloc: insufficient memory: %m"); CHECK_OUT_PTR(ptr, real_ptr, len); memset(ptr, FILLER, len); return (ptr); } /* myrealloc - reallocate memory or bust */ char *myrealloc(char *ptr, int len) { MBLOCK *real_ptr; int old_len; if (len < 1) msg_panic("myrealloc: requested length %d", len); CHECK_IN_PTR(ptr, real_ptr, old_len, "myrealloc"); if ((real_ptr = (MBLOCK *) realloc((char *) real_ptr, SPACE_FOR(len))) == 0) msg_fatal("myrealloc: insufficient memory: %m"); CHECK_OUT_PTR(ptr, real_ptr, len); if (len > old_len) memset(ptr + old_len, FILLER, len - old_len); return (ptr); } /* myfree - release memory */ void myfree(char *ptr) { MBLOCK *real_ptr; int len; CHECK_IN_PTR(ptr, real_ptr, len, "myfree"); memset((char *) real_ptr, FILLER, SPACE_FOR(len)); free((char *) real_ptr); } /* mystrdup - save string to heap */ char *mystrdup(const char *str) { if (str == 0) msg_panic("mystrdup: null pointer argument"); return (strcpy(mymalloc(strlen(str) + 1), str)); } /* mystrndup - save substring to heap */ char *mystrndup(const char *str, int len) { char *result; char *cp; if (str == 0) msg_panic("mystrndup: null pointer argument"); if ((cp = memchr(str, 0, len)) != 0) len = cp - str; result = memcpy(mymalloc(len + 1), str, len); result[len] = 0; return (result); } /* mymemdup - copy memory */ char *mymemdup(const char *ptr, int len) { if (ptr == 0) msg_panic("mymemdup: null pointer argument"); return (memcpy(mymalloc(len), ptr, len)); }