/* enable the POSIX prototypes of mmap/munmap on Solaris */ #ifdef __sun # if __STDC_VERSION__ >= 199901L # define _XOPEN_SOURCE 600 # else # define _XOPEN_SOURCE 500 # endif #endif #ifndef _WIN32 #include #endif #if !defined USE_MMAP \ && _POSIX_MAPPED_FILES > 0 \ && (_POSIX_VERSION >= 200809L || _POSIX_MEMORY_PROTECTION > 0) #include #if !defined MAP_ANONYMOUS && defined MAP_ANON #define MAP_ANONYMOUS MAP_ANON #endif #ifdef MAP_ANONYMOUS #include #if PAGESIZE <= 0 static long pagesize; #define PAGESIZE pagesize ? pagesize : (pagesize = sysconf (_SC_PAGESIZE)) #endif #define USE_MMAP 1 #endif #endif /* we assume natural alignment, uulib only uses ints and chars */ #define ALIGN 1 #define GUARDS 4 static void * safe_alloc (size_t size) { #if USE_MMAP size_t rounded = (size + ALIGN - 1) & ~(ALIGN - 1); size_t page = PAGESIZE; size_t page_rounded = (rounded + page - 1) & ~(page - 1); void *base = mmap (0, page_rounded + page * GUARDS * 2, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (base == (void *)-1) return 0; mprotect (base, page * GUARDS, PROT_NONE); /* beginning */ mprotect (page_rounded + page * GUARDS + (char *)base, page * GUARDS, PROT_NONE); /* end */ return page * GUARDS + (page_rounded - rounded) + (char *)base; #else return malloc (size); #endif } static void safe_free (void *mem, size_t size) { #if USE_MMAP size_t rounded = (size + ALIGN - 1) & ~(ALIGN - 1); size_t page = PAGESIZE; size_t page_rounded = (rounded + page - 1) & ~(page - 1); if (!mem) return; mem = (char *)mem - page * GUARDS - (page_rounded - rounded); munmap (mem, page_rounded + page * GUARDS * 2); #else free (size); #endif }