X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Fstore.c;h=94becbb9004e5adce4344e7ecd07752dabcb519b;hb=f1be21cf0b8b97a64dfe17f2ca05bb4b9efe8d32;hp=4603742350443bd1f643778da6e0647a1e6fbf29;hpb=7f36d675a458b3cf823c977e2cc4b47a6e6c8d4a;p=exim.git diff --git a/src/src/store.c b/src/src/store.c index 460374235..94becbb90 100644 --- a/src/src/store.c +++ b/src/src/store.c @@ -1,10 +1,8 @@ -/* $Cambridge: exim/src/src/store.c,v 1.5 2009/11/16 19:50:37 nm4 Exp $ */ - /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2009 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* Exim gets and frees all its store through these functions. In the original @@ -41,6 +39,9 @@ The following different types of store are recognized: #include "exim.h" +/* keep config.h before memcheck.h, for NVALGRIND */ +#include "config.h" + #include "memcheck.h" @@ -143,40 +144,40 @@ if (size > yield_length[store_pool]) { int length = (size <= STORE_BLOCK_SIZE)? STORE_BLOCK_SIZE : size; int mlength = length + ALIGNED_SIZEOF_STOREBLOCK; - storeblock *newblock = NULL; + storeblock * newblock = NULL; /* Sometimes store_reset() may leave a block for us; check if we can use it */ - if (current_block[store_pool] != NULL && - current_block[store_pool]->next != NULL) + if ( (newblock = current_block[store_pool]) + && (newblock = newblock->next) + && newblock->length < length + ) { - newblock = current_block[store_pool]->next; - if (newblock->length < length) - { - /* Give up on this block, because it's too small */ - store_free(newblock); - newblock = NULL; - } + /* Give up on this block, because it's too small */ + store_free(newblock); + newblock = NULL; } /* If there was no free block, get a new one */ - if (newblock == NULL) + if (!newblock) { pool_malloc += mlength; /* Used in pools */ nonpool_malloc -= mlength; /* Exclude from overall total */ newblock = store_malloc(mlength); newblock->next = NULL; newblock->length = length; - if (chainbase[store_pool] == NULL) chainbase[store_pool] = newblock; - else current_block[store_pool]->next = newblock; + if (!chainbase[store_pool]) + chainbase[store_pool] = newblock; + else + current_block[store_pool]->next = newblock; } current_block[store_pool] = newblock; yield_length[store_pool] = newblock->length; next_yield[store_pool] = - (void *)((char *)current_block[store_pool] + ALIGNED_SIZEOF_STOREBLOCK); - VALGRIND_MAKE_MEM_NOACCESS(next_yield[store_pool], yield_length[store_pool]); + (void *)(CS current_block[store_pool] + ALIGNED_SIZEOF_STOREBLOCK); + (void) VALGRIND_MAKE_MEM_NOACCESS(next_yield[store_pool], yield_length[store_pool]); } /* There's (now) enough room in the current block; the yield is the next @@ -193,7 +194,7 @@ linenumber = linenumber; #else DEBUG(D_memory) { - if (running_in_test_harness) + if (f.running_in_test_harness) debug_printf("---%d Get %5d\n", store_pool, size); else debug_printf("---%d Get %6p %5d %-14s %4d\n", store_pool, @@ -201,10 +202,10 @@ DEBUG(D_memory) } #endif /* COMPILE_UTILITY */ -VALGRIND_MAKE_MEM_UNDEFINED(store_last_get[store_pool], size); +(void) VALGRIND_MAKE_MEM_UNDEFINED(store_last_get[store_pool], size); /* Update next pointer and number of bytes left in the current block. */ -next_yield[store_pool] = (void *)((char *)next_yield[store_pool] + size); +next_yield[store_pool] = (void *)(CS next_yield[store_pool] + size); yield_length[store_pool] -= size; return store_last_get[store_pool]; @@ -272,7 +273,7 @@ int rounded_oldsize = oldsize; if (rounded_oldsize % alignment != 0) rounded_oldsize += alignment - (rounded_oldsize % alignment); -if ((char *)ptr + rounded_oldsize != (char *)(next_yield[store_pool]) || +if (CS ptr + rounded_oldsize != CS (next_yield[store_pool]) || inc > yield_length[store_pool] + rounded_oldsize - oldsize) return FALSE; @@ -285,7 +286,7 @@ linenumber = linenumber; #else DEBUG(D_memory) { - if (running_in_test_harness) + if (f.running_in_test_harness) debug_printf("---%d Ext %5d\n", store_pool, newsize); else debug_printf("---%d Ext %6p %5d %-14s %4d\n", store_pool, ptr, newsize, @@ -294,9 +295,9 @@ DEBUG(D_memory) #endif /* COMPILE_UTILITY */ if (newsize % alignment != 0) newsize += alignment - (newsize % alignment); -next_yield[store_pool] = (char *)ptr + newsize; +next_yield[store_pool] = CS ptr + newsize; yield_length[store_pool] -= newsize - rounded_oldsize; -VALGRIND_MAKE_MEM_UNDEFINED(ptr + oldsize, inc); +(void) VALGRIND_MAKE_MEM_UNDEFINED(ptr + oldsize, inc); return TRUE; } @@ -324,9 +325,9 @@ Returns: nothing void store_reset_3(void *ptr, const char *filename, int linenumber) { -storeblock *bb; -storeblock *b = current_block[store_pool]; -char *bc = (char *)b + ALIGNED_SIZEOF_STOREBLOCK; +storeblock * bb; +storeblock * b = current_block[store_pool]; +char * bc = CS b + ALIGNED_SIZEOF_STOREBLOCK; int newlength; /* Last store operation was not a get */ @@ -336,28 +337,36 @@ store_last_get[store_pool] = NULL; /* See if the place is in the current block - as it often will be. Otherwise, search for the block in which it lies. */ -if ((char *)ptr < bc || (char *)ptr > bc + b->length) +if (CS ptr < bc || CS ptr > bc + b->length) { - for (b = chainbase[store_pool]; b != NULL; b = b->next) + for (b = chainbase[store_pool]; b; b = b->next) { - bc = (char *)b + ALIGNED_SIZEOF_STOREBLOCK; - if ((char *)ptr >= bc && (char *)ptr <= bc + b->length) break; + bc = CS b + ALIGNED_SIZEOF_STOREBLOCK; + if (CS ptr >= bc && CS ptr <= bc + b->length) break; } - if (b == NULL) - log_write(0, LOG_MAIN|LOG_PANIC_DIE, "internal error: store_reset(%d) " + if (!b) + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "internal error: store_reset(%p) " "failed: pool=%d %-14s %4d", ptr, store_pool, filename, linenumber); } /* Back up, rounding to the alignment if necessary. When testing, flatten the released memory. */ -newlength = bc + b->length - (char *)ptr; +newlength = bc + b->length - CS ptr; #ifndef COMPILE_UTILITY -if (running_in_test_harness) memset(ptr, 0xF0, newlength); +if (debug_store) + { + assert_no_variables(ptr, newlength, filename, linenumber); + if (f.running_in_test_harness) + { + (void) VALGRIND_MAKE_MEM_DEFINED(ptr, newlength); + memset(ptr, 0xF0, newlength); + } + } #endif -VALGRIND_MAKE_MEM_NOACCESS(ptr, newlength); +(void) VALGRIND_MAKE_MEM_NOACCESS(ptr, newlength); yield_length[store_pool] = newlength - (newlength % alignment); -next_yield[store_pool] = (char *)ptr + (newlength % alignment); +next_yield[store_pool] = CS ptr + (newlength % alignment); current_block[store_pool] = b; /* Free any subsequent block. Do NOT free the first successor, if our @@ -365,19 +374,29 @@ current block has less than 256 bytes left. This should prevent us from flapping memory. However, keep this block only when it has the default size. */ if (yield_length[store_pool] < STOREPOOL_MIN_SIZE && - b->next != NULL && + b->next && b->next->length == STORE_BLOCK_SIZE) { b = b->next; - VALGRIND_MAKE_MEM_NOACCESS((char *)b + ALIGNED_SIZEOF_STOREBLOCK, b->length - ALIGNED_SIZEOF_STOREBLOCK); +#ifndef COMPILE_UTILITY + if (debug_store) + assert_no_variables(b, b->length + ALIGNED_SIZEOF_STOREBLOCK, + filename, linenumber); +#endif + (void) VALGRIND_MAKE_MEM_NOACCESS(CS b + ALIGNED_SIZEOF_STOREBLOCK, + b->length - ALIGNED_SIZEOF_STOREBLOCK); } bb = b->next; b->next = NULL; -while (bb != NULL) +while ((b = bb)) { - b = bb; +#ifndef COMPILE_UTILITY + if (debug_store) + assert_no_variables(b, b->length + ALIGNED_SIZEOF_STOREBLOCK, + filename, linenumber); +#endif bb = bb->next; pool_malloc -= b->length + ALIGNED_SIZEOF_STOREBLOCK; store_free_3(b, filename, linenumber); @@ -392,7 +411,7 @@ linenumber = linenumber; #else DEBUG(D_memory) { - if (running_in_test_harness) + if (f.running_in_test_harness) debug_printf("---%d Rst ** %d\n", store_pool, pool_malloc); else debug_printf("---%d Rst %6p ** %-14s %4d %d\n", store_pool, ptr, @@ -409,14 +428,8 @@ DEBUG(D_memory) * Release store * ************************************************/ -/* This function is specifically provided for use when reading very -long strings, e.g. header lines. When the string gets longer than a -complete block, it gets copied to a new block. It is helpful to free -the old block iff the previous copy of the string is at its start, -and therefore the only thing in it. Otherwise, for very long strings, -dead store can pile up somewhat disastrously. This function checks that -the pointer it is given is the first thing in a block, and if so, -releases that block. +/* This function checks that the pointer it is given is the first thing in a +block, and if so, releases that block. Arguments: block block of store to consider @@ -426,17 +439,15 @@ Arguments: Returns: nothing */ -void -store_release_3(void *block, const char *filename, int linenumber) +static void +store_release_3(void * block, const char * filename, int linenumber) { -storeblock *b; - /* It will never be the first block, so no need to check that. */ -for (b = chainbase[store_pool]; b != NULL; b = b->next) +for (storeblock * b = chainbase[store_pool]; b; b = b->next) { - storeblock *bb = b->next; - if (bb != NULL && (char *)block == (char *)bb + ALIGNED_SIZEOF_STOREBLOCK) + storeblock * bb = b->next; + if (bb && CS block == CS bb + ALIGNED_SIZEOF_STOREBLOCK) { b->next = bb->next; pool_malloc -= bb->length + ALIGNED_SIZEOF_STOREBLOCK; @@ -444,21 +455,20 @@ for (b = chainbase[store_pool]; b != NULL; b = b->next) /* Cut out the debugging stuff for utilities, but stop picky compilers from giving warnings. */ - #ifdef COMPILE_UTILITY +#ifdef COMPILE_UTILITY filename = filename; linenumber = linenumber; - #else +#else DEBUG(D_memory) - { - if (running_in_test_harness) + if (f.running_in_test_harness) debug_printf("-Release %d\n", pool_malloc); else debug_printf("-Release %6p %-20s %4d %d\n", (void *)bb, filename, linenumber, pool_malloc); - } - if (running_in_test_harness) + + if (f.running_in_test_harness) memset(bb, 0xF0, bb->length+ALIGNED_SIZEOF_STOREBLOCK); - #endif /* COMPILE_UTILITY */ +#endif /* COMPILE_UTILITY */ free(bb); return; @@ -467,6 +477,43 @@ for (b = chainbase[store_pool]; b != NULL; b = b->next) } +/************************************************ +* Move store * +************************************************/ + +/* Allocate a new block big enough to expend to the given size and +copy the current data into it. Free the old one if possible. + +This function is specifically provided for use when reading very +long strings, e.g. header lines. When the string gets longer than a +complete block, it gets copied to a new block. It is helpful to free +the old block iff the previous copy of the string is at its start, +and therefore the only thing in it. Otherwise, for very long strings, +dead store can pile up somewhat disastrously. This function checks that +the pointer it is given is the first thing in a block, and that nothing +has been allocated since. If so, releases that block. + +Arguments: + block + newsize + len + +Returns: new location of data +*/ + +void * +store_newblock_3(void * block, int newsize, int len, + const char * filename, int linenumber) +{ +BOOL release_ok = store_last_get[store_pool] == block; +uschar * newtext = store_get(newsize); + +memcpy(newtext, block, len); +if (release_ok) store_release_3(block, filename, linenumber); +return (void *)newtext; +} + + /************************************************* @@ -491,9 +538,8 @@ store_malloc_3(int size, const char *filename, int linenumber) void *yield; if (size < 16) size = 16; -yield = malloc((size_t)size); -if (yield == NULL) +if (!(yield = malloc((size_t)size))) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to malloc %d bytes of memory: " "called from line %d of %s", size, linenumber, filename); @@ -510,7 +556,7 @@ linenumber = linenumber; /* If running in test harness, spend time making sure all the new store is not filled with zeros so as to catch problems. */ -if (running_in_test_harness) +if (f.running_in_test_harness) { memset(yield, 0xF0, (size_t)size); DEBUG(D_memory) debug_printf("--Malloc %5d %d %d\n", size, pool_malloc, @@ -550,7 +596,7 @@ linenumber = linenumber; #else DEBUG(D_memory) { - if (running_in_test_harness) + if (f.running_in_test_harness) debug_printf("----Free\n"); else debug_printf("----Free %6p %-20s %4d\n", block, filename, linenumber);