options, and new features, see the NewStuff file next to this ChangeLog.
+Exim version 4.next
+-----------------
+
+JH/01 Replace the store_release() internal interface with store_newblock(),
+ which internalises the check required to safely use the old one, plus
+ the allocate and data copy operations duplicated in both (!) of the
+ extant use locations.
+
Exim version 4.90
-----------------
/* header_size += 256; */
header_size *= 2;
if (!store_extend(next->text, oldsize, header_size))
- {
- BOOL release_ok = store_last_get[store_pool] == next->text;
- uschar *newtext = store_get(header_size);
- memcpy(newtext, next->text, ptr);
- if (release_ok) store_release(next->text);
- next->text = newtext;
- }
+ next->text = store_newblock(next->text, header_size, ptr);
}
/* Cope with receiving a binary zero. There is dispute about whether
* 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
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;
+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 (b = chainbase[store_pool]; b; b = b->next)
{
- storeblock *bb = b->next;
- if (bb != NULL && CS block == CS 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;
/* 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)
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)
memset(bb, 0xF0, bb->length+ALIGNED_SIZEOF_STOREBLOCK);
- #endif /* COMPILE_UTILITY */
+#endif /* COMPILE_UTILITY */
free(bb);
return;
}
+/************************************************
+* 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;
+}
+
+
/*************************************************
#define store_get(size) store_get_3(size, __FILE__, __LINE__)
#define store_get_perm(size) store_get_perm_3(size, __FILE__, __LINE__)
#define store_malloc(size) store_malloc_3(size, __FILE__, __LINE__)
-#define store_release(addr) store_release_3(addr, __FILE__, __LINE__)
+#define store_newblock(addr,newsize,datalen) \
+ store_newblock_3(addr, newsize, datalen, __FILE__, __LINE__)
#define store_reset(addr) store_reset_3(addr, __FILE__, __LINE__)
/* The real functions */
-extern BOOL store_extend_3(void *, int, int, const char *, int); /* The */
-extern void store_free_3(void *, const char *, int); /* value of the */
-extern void *store_get_3(int, const char *, int); /* 2nd arg is */
-extern void *store_get_perm_3(int, const char *, int); /* __FILE__ in */
-extern void *store_malloc_3(int, const char *, int); /* every call, */
-extern void store_release_3(void *, const char *, int); /* so give its */
-extern void store_reset_3(void *, const char *, int); /* correct type */
+/* The value of the 2nd arg is __FILE__ in every call, so give its correct type */
+extern BOOL store_extend_3(void *, int, int, const char *, int);
+extern void store_free_3(void *, const char *, int);
+extern void *store_get_3(int, const char *, int);
+extern void *store_get_perm_3(int, const char *, int);
+extern void *store_malloc_3(int, const char *, int);
+extern void *store_newblock_3(void *, int, int, const char *, int);
+extern void store_reset_3(void *, const char *, int);
#endif /* STORE_H */
store_last_get. */
if (!store_extend(g->s, oldsize, g->size))
- {
- BOOL release_ok = store_last_get[store_pool] == g->s;
- uschar *newstring = store_get(g->size);
- memcpy(newstring, g->s, p);
- if (release_ok) store_release(g->s);
- g->s = newstring;
- }
+ g->s = store_newblock(g->s, g->size, p);
}