/* #ident "@(#)smail/src:RELEASE-3_2_0_121:alloc.h,v 1.21 2005/07/20 20:34:56 woods Exp" */ /* * Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll * Copyright (C) 1992 Ronald S. Karr * * See the file COPYING, distributed with smail, for restriction * and warranty information. */ /* * alloc.h: * block storage allocation * This allows a given storage allocation to be associated * with a group of other storage allocations. It is * possible to free or test for existence of the class. * * A block a pointer to a chain of segments. Each segment * refers to one storage allocation. A block also contains * the total number of segments allocated. If this number is * zero, then no storage is associated with the block. */ /* * block allocation data structure */ struct block { struct bseg *next; /* if cnt > 0 then next holds segment chain */ int cnt; /* number of segments in the block */ }; struct bseg { struct bseg *next; /* if != NULL, then next alloc in block */ char *data; /* the storage allocated */ }; /* * handy macros to determine if a block is active */ #define is_memory(block_ptr) ((struct block *)(block_ptr)->cnt) #define is_free(block_ptr) (!(struct block *)(block_ptr)->cnt) /* * X_CHECK - check for the xmalloc magic number * * As a debugging aid against double xfree(), as well as to protect against the * the use of freed storage, the integer X_MAGIC is stored at the beginning of * each block allocated with xmalloc(). This integer is then cleared after a * call to xfree() has marked the block as free. * * The macro X_CHECK() checks for the X_MAGIC value and calls panic() if it * does not exist and iff x_dont_panic is false. This macro should be used * whenever a pointer value which might be freed and reallocated multiple times * is used (e.g. in the STR_*() macros). xfree() itself checks that it doesn't * try to free storage thats already marked as free. * * In an ideal world we would put another, different, canary value at the * precise end of the requested storage, but that would require keeping track * of the requested size of each block, e.g. by storing it right next to the * magic number at the start of the block. In a perfect world that second * canary value would be impossible for an attacker to predict (i.e. it might * be a random number that's obtained at startup), but of course in the real * world that number would be scattered all over at all kinds of predictable * locations so the attacker could probably find and copy it anyway. * * XXX if we knew the size of the ALIGNED_TYPE then we could provide more bits * of random data for this canary on machines where we have more room to store * them in. Maybe we should at least try to force sign extension to fill out * the empty bits with ones so that they are more obvious from a debugger. * * XXX maybe the x_dont_panic flag should be promoted to be handled by panic() * so that this macro could just use panic() instead of having to use * write_log() and abort() directly. */ #define X_MAGIC ((ALIGNED_TYPE)0xe8f987b1) #define X_CHECK_MESSAGE "X_CHECK failed! ptr=%p, line=%d, file=%s Please trace under a debugger!" #define X_CHECK(p) \ (((ALIGNED_TYPE *)(p))[-1] != X_MAGIC ? \ (write_log(WRITE_LOG_PANIC|WRITE_LOG_SYS|WRITE_LOG_TTY,\ X_CHECK_MESSAGE, \ (POINTER_TYPE)(p), \ __LINE__, \ __FILE__), \ x_dont_panic ? \ FAIL : \ (abort(), 0)) \ : SUCCEED) /* use these macros to panic code which should not generate a panic */ #define X_NO_PANIC() (x_dont_panic = TRUE) #define X_PANIC_OKAY() (x_dont_panic = FALSE) /* XXX this should be an all-uppercase symbol to warn users of side-effects!!! */ #define xrealloc(ptr, sz) \ (X_CHECK(ptr) == SUCCEED ? \ priv_xrealloc(ptr, sz) : \ NULL) #define XFREE_NULL_MESSAGE "xfree(NULL) called at line=%d, file=%s Please trace under a debugger!" /* XXX this might best be an all-uppercase symbol to warn users of side-effects!!! */ /* XXX should this honour x_dont_panic!?!?!? */ #define xfree(ptr) \ ((ptr == NULL) ? \ (panic(EX_SOFTWARE, \ XFREE_NULL_MESSAGE, \ __LINE__, __FILE__),FAIL) : \ (X_CHECK(ptr) == SUCCEED ? \ (priv_xfree(ptr),SUCCEED) : \ FAIL)) #define X_IS_XALLOC(p) (((ALIGNED_TYPE *)(p))[-1] == X_MAGIC) /* external variables defined in alloc.c */ extern int x_dont_panic; /* dont panic in X_CHECK() */ /* external functions defined in alloc.c */ extern char *xmalloc __P((size_t)); extern char *priv_xrealloc __P((char *, size_t)); extern void priv_xfree __P((char *)); extern char *bmalloc __P((size_t, struct block *)); extern char *brealloc __P((char *, size_t, struct block *)); extern void bfree __P((char *, struct block *)); extern struct block *malloc_block __P((void)); extern void realloc_block __P((char *, struct block *, struct block *)); extern void free_block __P((struct block *)); /* * Local Variables: * c-file-style: "smail" * End: */