buffer_t *buf;
char *p;
- buf = buffer_create_dynamic(data_stack_pool,
+ buf = buffer_create_dynamic(pool_datastack_create(),
sizeof(reply) + 256, (size_t)-1);
memset(&reply, 0, sizeof(reply));
buffer_append(buf, &reply, sizeof(reply));
random_fill(nonce, sizeof(nonce));
t_push();
- buf = buffer_create_static(data_stack_pool,
+ buf = buffer_create_static(pool_datastack_create(),
MAX_BASE64_ENCODED_SIZE(sizeof(nonce))+1);
base64_encode(nonce, sizeof(nonce), buf);
if (credentials == NULL || strlen(credentials) != sizeof(digest)*2)
return FALSE;
- digest_buf = buffer_create_data(data_stack_pool,
+ digest_buf = buffer_create_data(pool_datastack_create(),
digest, sizeof(digest));
if (hex_to_binary(credentials, digest_buf) <= 0)
return FALSE;
else {
i++;
len = request->data_size - i;
- pass = p_strndup(data_stack_pool, data+i, len);
+ pass = p_strndup(unsafe_data_stack_pool,
+ data+i, len);
break;
}
}
{
buffer_t *buf;
- buf = buffer_create_dynamic(data_stack_pool, 256, (size_t)-1);
+ buf = buffer_create_dynamic(pool_datastack_create(), 256, (size_t)-1);
reply->username_idx = 0;
buffer_append(buf, auth_request->user, strlen(auth_request->user)+1);
}
}
- buf = buffer_create_data(data_stack_pool, buf_data, sizeof(buf_data));
+ buf = buffer_create_data(pool_datastack_create(),
+ buf_data, sizeof(buf_data));
buffer_append(buf, &result, sizeof(result));
if (str != NULL) {
t_push();
- buf = buffer_create_dynamic(data_stack_pool, size*2, (size_t)-1);
+ buf = buffer_create_dynamic(pool_datastack_create(),
+ size*2, (size_t)-1);
buffer_append(buf, "+ ", 2);
base64_encode(data, size, buf);
buffer_append(buf, "\r\n", 2);
}
linelen = strlen(line);
- buf = buffer_create_static_hard(data_stack_pool, linelen);
+ buf = buffer_create_static_hard(pool_datastack_create(), linelen);
if (base64_decode((const unsigned char *) line, linelen,
NULL, buf) <= 0) {
size_t i, count;
/* find the oldest clients and put them to destroy-buffer */
- destroy_buf = buffer_create_static_hard(data_stack_pool,
+ destroy_buf = buffer_create_static_hard(pool_datastack_create(),
sizeof(struct imap_client *) *
CLIENT_DESTROY_OLDEST_COUNT);
hash_foreach(clients, client_hash_destroy_oldest, destroy_buf);
return TRUE;
}
memset(&old_flags, 0, sizeof(old_flags));
- old_flags.pool = data_stack_pool;
+ old_flags.pool = pool_datastack_create();
client_save_custom_flags(&old_flags, status.custom_flags,
status.custom_flags_count);
return NULL;
}
- buf = buffer_create_dynamic(data_stack_pool,
+ buf = buffer_create_dynamic(pool_datastack_create(),
32 * sizeof(enum mail_sort_type),
(size_t)-1);
i_assert(hdr_ctx.dest_size <= size->virtual_size);
} else {
hdr_ctx.dest =
- buffer_create_dynamic(data_stack_pool,
+ buffer_create_dynamic(pool_datastack_create(),
I_MIN(size->virtual_size, 8192),
(size_t)-1);
if (!fetch_header_fields(input, header_section, &hdr_ctx))
separately rather than parsing the full header so mail storage
can try to cache them. */
ctx.body_fetch_from_cache = TRUE;
- buffer = buffer_create_dynamic(data_stack_pool, 64, (size_t)-1);
+ buffer = buffer_create_dynamic(pool_datastack_create(), 64, (size_t)-1);
for (body = bodies; body != NULL; body = body->next) {
if (strncmp(body->section, "HEADER.FIELDS ", 14) != 0) {
ctx.body_fetch_from_cache = FALSE;
ctx = t_new(struct sort_context, 1);
/* normalize sorting program */
- buf = buffer_create_data(data_stack_pool, norm_prog, sizeof(norm_prog));
+ buf = buffer_create_data(pool_datastack_create(),
+ norm_prog, sizeof(norm_prog));
mail_sort_normalize(sort_program, buf);
memcpy(ctx->sort_program, norm_prog, sizeof(ctx->sort_program));
if (str == NULL)
return NULL;
- addr = message_address_parse(data_stack_pool,
+ addr = message_address_parse(pool_datastack_create(),
(const unsigned char *) str,
(size_t)-1, 1);
return addr != NULL ? addr->mailbox : NULL;
if (found_at) {
char *s;
- s = p_strdup_until(data_stack_pool, msgid, p);
+ s = p_strdup_until(unsafe_data_stack_pool,
+ msgid, p);
strip_lwsp(s);
return s;
}
if (subject == NULL)
return;
- subject = imap_get_base_subject_cased(data_stack_pool, subject,
+ subject = imap_get_base_subject_cased(pool_datastack_create(), subject,
&is_reply_or_forward);
if (*subject == '\0')
return;
{
buffer_t *dest;
- dest = buffer_create_dynamic(data_stack_pool, size, (size_t)-1);
+ dest = buffer_create_dynamic(pool_datastack_create(), size, (size_t)-1);
_charset_utf8_ucase(data, size, dest, 0);
if (utf8_size_r != NULL)
*utf8_size_r = buffer_get_used_size(dest);
len = strlen(bodystructure);
str = t_str_new(len);
- input = i_stream_create_from_data(data_stack_pool, bodystructure, len);
+ input = i_stream_create_from_data(pool_datastack_create(),
+ bodystructure, len);
(void)i_stream_read(input);
parser = imap_parser_create(input, NULL, (size_t)-1);
i_assert(field < IMAP_ENVELOPE_FIELDS);
- input = i_stream_create_from_data(data_stack_pool, envelope,
+ input = i_stream_create_from_data(pool_datastack_create(), envelope,
strlen(envelope));
parser = imap_parser_create(input, NULL, (size_t)-1);
string_t *str;
char *ret;
- i_assert(pool != data_stack_pool);
-
if (value == NULL)
return "NIL";
int i;
memset(&cache_rec, 0, sizeof(cache_rec));
- buffer = buffer_create_dynamic(data_stack_pool, 4096, (size_t)-1);
+ buffer = buffer_create_dynamic(pool_datastack_create(),
+ 4096, (size_t)-1);
orig_cached_fields = mail_cache_get_fields(cache, rec);
cached_fields = orig_cached_fields & ~MAIL_CACHE_HEADERS_MASK;
t_push();
- buffer = buffer_create_dynamic(data_stack_pool, 512, (size_t)-1);
+ buffer = buffer_create_dynamic(pool_datastack_create(),
+ 512, (size_t)-1);
while (*headers != NULL) {
if (buffer_get_used_size(buffer) != 0)
buffer_append(buffer, "\n", 1);
i_assert((max_records+1) <
SSIZE_T_MAX / sizeof(struct modify_log_expunge));
- buf = buffer_create_static_hard(data_stack_pool, (max_records+1) *
+ buf = buffer_create_static_hard(pool_datastack_create(),
+ (max_records+1) *
sizeof(struct modify_log_expunge));
before = 0;
i_assert((max_records+1) <
SSIZE_T_MAX / sizeof(struct modify_log_expunge));
- buf = buffer_create_static_hard(data_stack_pool, (max_records+1) *
+ buf = buffer_create_static_hard(pool_datastack_create(),
+ (max_records+1) *
sizeof(struct modify_log_expunge));
before = 0;
}
/* we're at the 3rd field now, which begins the list of custom flags */
- buf = buffer_create_dynamic(data_stack_pool,
+ buf = buffer_create_dynamic(pool_datastack_create(),
MAIL_CUSTOM_FLAGS_COUNT *
sizeof(const char *),
MAX_CUSTOM_FLAGS * sizeof(const char *));
t_push();
- input = i_stream_create_mmap(in_fd, data_stack_pool,
+ input = i_stream_create_mmap(in_fd, pool_datastack_create(),
1024*256, 0, 0, FALSE);
i_stream_set_read_limit(input, size);
- output = o_stream_create_file(out_fd, data_stack_pool, 1024, FALSE);
+ output = o_stream_create_file(out_fd, pool_datastack_create(),
+ 1024, FALSE);
o_stream_set_blocking(output, 60000, NULL, NULL);
ret = o_stream_send_istream(output, input);
message_tokenize_skip_comments(tok, FALSE);
message_tokenize_dot_token(tok, FALSE);
- if (pool != data_stack_pool)
+ if (!pool->datastack_pool)
t_push();
mailbox = t_str_new(128);
domain = t_str_new(256);
if (ingroup)
(void)new_address(pool, &next_addr);
- if (pool != data_stack_pool)
+ if (!pool->datastack_pool)
t_pop();
message_tokenize_deinit(tok);
struct message_header_line *hdr;
int found = FALSE;
- hdr_search_ctx = message_header_search_init(data_stack_pool,
+ hdr_search_ctx = message_header_search_init(pool_datastack_create(),
ctx->body_ctx->key,
ctx->body_ctx->charset,
NULL);
enum charset_result result;
size_t block_pos, inbuf_size, inbuf_left, ret;
- outbuf = buffer_create_static(data_stack_pool, DECODE_BLOCK_SIZE);
+ outbuf = buffer_create_static(pool_datastack_create(),
+ DECODE_BLOCK_SIZE);
for (block_pos = 0; block_pos < buffer_get_used_size(block); ) {
if (buffer_get_used_size(ctx->decode_buf) == 0) {
/* we can use the buffer directly without copying */
{
const unsigned char *data;
buffer_t *decodebuf;
+ pool_t pool;
size_t data_size, pos;
uoff_t old_limit;
ssize_t ret;
if (ctx->translation == NULL)
ctx->translation = charset_to_utf8_begin("ascii", NULL);
- ctx->decode_buf = buffer_create_static(data_stack_pool, 256);
- ctx->match_buf = buffer_create_static_hard(data_stack_pool,
+ ctx->decode_buf = buffer_create_static(pool_datastack_create(), 256);
+ ctx->match_buf = buffer_create_static_hard(pool_datastack_create(),
sizeof(size_t) *
ctx->body_ctx->key_len);
pos = data_size;
t_push();
+ pool = pool_datastack_create();
if (ctx->content_qp) {
- decodebuf = buffer_create_static_hard(data_stack_pool,
- data_size);
+ decodebuf = buffer_create_static_hard(pool, data_size);
quoted_printable_decode(data, data_size,
&data_size, decodebuf);
} else if (ctx->content_base64) {
size_t size = MAX_BASE64_DECODED_SIZE(data_size);
- decodebuf = buffer_create_static_hard(data_stack_pool,
- size);
+ decodebuf = buffer_create_static_hard(pool, size);
if (base64_decode(data, data_size,
&data_size, decodebuf) < 0) {
break;
}
} else {
- decodebuf = buffer_create_const_data(data_stack_pool,
- data, data_size);
+ decodebuf = buffer_create_const_data(pool, data,
+ data_size);
}
ret = message_search_body_block(ctx, decodebuf);
return TRUE;
}
- decodebuf = buffer_create_static_hard(data_stack_pool, text_size);
+ decodebuf = buffer_create_static_hard(pool_datastack_create(),
+ text_size);
if (*encoding == 'Q')
quoted_printable_decode(text, text_size, NULL, decodebuf);
int i, already_sorted;
/* copy the wanted_headers array */
- buffer = buffer_create_dynamic(data_stack_pool, 256, (size_t)-1);
+ buffer = buffer_create_dynamic(pool_datastack_create(),
+ 256, (size_t)-1);
already_sorted = TRUE;
for (i = 0; arr[i] != NULL; i++) {
if (i > 0 && already_sorted &&
data = buffer_get_modifyable_data(mail->data.headers, &size);
size /= sizeof(struct cached_header *);
- buffer = buffer_create_dynamic(data_stack_pool, 128, (size_t)-1);
+ buffer = buffer_create_dynamic(pool_datastack_create(),
+ 128, (size_t)-1);
for (i = 0; i < size; i++)
buffer_append(buffer, &data[i]->name, sizeof(const char *));
buffer_append(buffer, &null, sizeof(const char *));
t_push();
if (idx < data->header_data_cached) {
/* it's already in header_data. */
- istream = i_stream_create_from_data(data_stack_pool,
+ istream = i_stream_create_from_data(pool_datastack_create(),
str_data(data->header_data),
str_len(data->header_data));
/* we might be parsing a bit more.. */
}
data->header_data_cached_partial = TRUE;
- istream = i_stream_create_from_data(data_stack_pool,
+ istream = i_stream_create_from_data(pool_datastack_create(),
str, strlen(str));
}
if (index_mail_cache_can_add(mail, MAIL_CACHE_MESSAGEPART)) {
t_push();
- buffer = buffer_create_dynamic(data_stack_pool,
+ buffer = buffer_create_dynamic(pool_datastack_create(),
1024, (size_t)-1);
message_part_serialize(mail->data.parts, buffer);
struct message_address *addr;
string_t *str;
- addr = message_address_parse(data_stack_pool,
+ addr = message_address_parse(pool_datastack_create(),
ctx->hdr->full_value,
ctx->hdr->full_value_len,
0);
fname++;
t_push();
- output = o_stream_create_file(fd, data_stack_pool, 4096, FALSE);
+ output = o_stream_create_file(fd, pool_datastack_create(), 4096, FALSE);
o_stream_set_blocking(output, 60000, NULL, NULL);
if (!mail_storage_save(ibox->box.storage, path, input, output,
*have_headers = *have_body = have_text = FALSE;
- headers = buffer_create_dynamic(data_stack_pool, 128, (size_t)-1);
+ headers = buffer_create_dynamic(pool_datastack_create(),
+ 128, (size_t)-1);
for (; args != NULL; args = args->next) {
search_arg_analyze(args, headers, have_headers,
have_body, &have_text);
mempool-alloconly.c \
mempool-datastack.c \
mempool-system.c \
+ mempool-unsafe-datastack.c \
mkdir-parents.c \
mmap-anon.c \
mmap-util.c \
pool_alloconly_clear,
- TRUE
+ TRUE,
+ FALSE
};
pool_t pool_alloconly_create(const char *name, size_t size)
pool_data_stack_clear,
+ TRUE,
TRUE
};
-pool_t data_stack_pool = &static_data_stack_pool;
+struct datastack_pool {
+ struct pool pool;
+ int refcount;
+
+ unsigned int data_stack_frame;
+};
+
+pool_t pool_datastack_create(void)
+{
+ struct datastack_pool *dpool;
+
+ dpool = t_new(struct datastack_pool, 1);
+ dpool->pool = static_data_stack_pool;
+ dpool->refcount = 1;
+ dpool->data_stack_frame = data_stack_frame;
+ return &dpool->pool;
+}
static const char *pool_data_stack_get_name(pool_t pool __attr_unused__)
{
return "data stack";
}
-static void pool_data_stack_ref(pool_t pool __attr_unused__)
+static void pool_data_stack_ref(pool_t pool)
{
+ struct datastack_pool *dpool = (struct datastack_pool *) pool;
+
+ if (dpool->data_stack_frame != data_stack_frame)
+ i_panic("pool_data_stack_ref(): stack frame changed");
+
+ dpool->refcount++;
}
-static void pool_data_stack_unref(pool_t pool __attr_unused__)
+static void pool_data_stack_unref(pool_t pool)
{
+ struct datastack_pool *dpool = (struct datastack_pool *) pool;
+
+ if (dpool->data_stack_frame != data_stack_frame)
+ i_panic("pool_data_stack_unref(): stack frame changed");
+
+ dpool->refcount--;
+ i_assert(dpool->refcount >= 0);
}
static void *pool_data_stack_malloc(pool_t pool __attr_unused__, size_t size)
{
+ struct datastack_pool *dpool = (struct datastack_pool *) pool;
+
if (size == 0 || size > SSIZE_T_MAX)
i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
+ if (dpool->data_stack_frame != data_stack_frame)
+ i_panic("pool_data_stack_malloc(): stack frame changed");
+
return t_malloc0(size);
}
-static void pool_data_stack_free(pool_t pool __attr_unused__,
- void *mem __attr_unused__)
+static void pool_data_stack_free(pool_t pool, void *mem __attr_unused__)
{
+ struct datastack_pool *dpool = (struct datastack_pool *) pool;
+
+ if (dpool->data_stack_frame != data_stack_frame)
+ i_panic("pool_data_stack_free(): stack frame changed");
}
-static void *pool_data_stack_realloc(pool_t pool __attr_unused__, void *mem,
+static void *pool_data_stack_realloc(pool_t pool, void *mem,
size_t old_size, size_t new_size)
{
+ struct datastack_pool *dpool = (struct datastack_pool *) pool;
void *new_mem;
/* @UNSAFE */
if (new_size == 0 || new_size > SSIZE_T_MAX)
i_panic("Trying to allocate %"PRIuSIZE_T" bytes", new_size);
+ if (dpool->data_stack_frame != data_stack_frame)
+ i_panic("pool_data_stack_realloc(): stack frame changed");
+
if (mem == NULL)
return pool_data_stack_malloc(pool, new_size);
pool_system_clear,
- FALSE
+ FALSE,
+ FALSE
};
pool_t system_pool = &static_system_pool;
--- /dev/null
+/* Copyright (c) 2002-2003 Timo Sirainen */
+
+#include "lib.h"
+#include "mempool.h"
+
+#include <stdlib.h>
+
+static const char *pool_unsafe_data_stack_get_name(pool_t pool);
+static void pool_unsafe_data_stack_ref(pool_t pool);
+static void pool_unsafe_data_stack_unref(pool_t pool);
+static void *pool_unsafe_data_stack_malloc(pool_t pool, size_t size);
+static void pool_unsafe_data_stack_free(pool_t pool, void *mem);
+static void *pool_unsafe_data_stack_realloc(pool_t pool, void *mem,
+ size_t old_size, size_t new_size);
+static void pool_unsafe_data_stack_clear(pool_t pool);
+
+static struct pool static_unsafe_data_stack_pool = {
+ pool_unsafe_data_stack_get_name,
+
+ pool_unsafe_data_stack_ref,
+ pool_unsafe_data_stack_unref,
+
+ pool_unsafe_data_stack_malloc,
+ pool_unsafe_data_stack_free,
+
+ pool_unsafe_data_stack_realloc,
+
+ pool_unsafe_data_stack_clear,
+
+ TRUE,
+ TRUE
+};
+
+pool_t unsafe_data_stack_pool = &static_unsafe_data_stack_pool;
+
+static const char *pool_unsafe_data_stack_get_name(pool_t pool __attr_unused__)
+{
+ return "unsafe data stack";
+}
+
+static void pool_unsafe_data_stack_ref(pool_t pool __attr_unused__)
+{
+}
+
+static void pool_unsafe_data_stack_unref(pool_t pool __attr_unused__)
+{
+}
+
+static void *pool_unsafe_data_stack_malloc(pool_t pool __attr_unused__,
+ size_t size)
+{
+ if (size == 0 || size > SSIZE_T_MAX)
+ i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
+
+ return t_malloc0(size);
+}
+
+static void pool_unsafe_data_stack_free(pool_t pool __attr_unused__,
+ void *mem __attr_unused__)
+{
+}
+
+static void *pool_unsafe_data_stack_realloc(pool_t pool __attr_unused__,
+ void *mem,
+ size_t old_size, size_t new_size)
+{
+ void *new_mem;
+
+ /* @UNSAFE */
+ if (new_size == 0 || new_size > SSIZE_T_MAX)
+ i_panic("Trying to allocate %"PRIuSIZE_T" bytes", new_size);
+
+ if (mem == NULL)
+ return pool_unsafe_data_stack_malloc(pool, new_size);
+
+ if (old_size >= new_size)
+ return mem;
+
+ if (!t_try_realloc(mem, new_size)) {
+ new_mem = t_malloc(new_size);
+ memcpy(new_mem, mem, old_size);
+ mem = new_mem;
+ }
+
+ memset((char *) mem + old_size, 0, new_size - old_size);
+ return mem;
+}
+
+static void pool_unsafe_data_stack_clear(pool_t pool __attr_unused__)
+{
+}
void (*clear)(pool_t pool);
unsigned int alloconly_pool:1;
+ unsigned int datastack_pool:1;
};
/* system_pool uses calloc() + realloc() + free() */
extern pool_t system_pool;
-/* memory allocated from data_stack is valid only until next t_pop() call. */
-extern pool_t data_stack_pool;
+/* memory allocated from data_stack is valid only until next t_pop() call.
+ No checks are performed. */
+extern pool_t unsafe_data_stack_pool;
/* Create a new alloc-only pool. Note that `size' specifies the initial
malloc()ed block size, part of it is used internally. */
pool_t pool_alloconly_create(const char *name, size_t size);
+/* When allocating memory from returned pool, the data stack frame must be
+ the same as it was when calling this function. pool_unref() also checks
+ that the stack frame is the same. This should make it quite safe to use. */
+pool_t pool_datastack_create(void);
+
/* Pools should be used through these macros: */
#define pool_get_name(pool) (pool)->get_name(pool)
#define pool_ref(pool) (pool)->ref(pool)
string_t *t_str_new(size_t initial_size)
{
- return str_new(data_stack_pool, initial_size);
+ return str_new(pool_datastack_create(), initial_size);
}
void str_free(string_t *str)
i_assert(format != NULL);
- if (pool != data_stack_pool)
+ if (!pool->datastack_pool)
t_push();
VA_COPY(args2, args);
#else
vsprintf(ret, format, args2);
#endif
- if (pool != data_stack_pool)
+ if (!pool->datastack_pool)
t_pop();
return ret;
}
const char *t_strdup(const char *str)
{
- return p_strdup(data_stack_pool, str);
+ return p_strdup(unsafe_data_stack_pool, str);
}
char *t_strdup_noconst(const char *str)
{
- return p_strdup(data_stack_pool, str);
+ return p_strdup(unsafe_data_stack_pool, str);
}
const char *t_strdup_empty(const char *str)
{
- return p_strdup_empty(data_stack_pool, str);
+ return p_strdup_empty(unsafe_data_stack_pool, str);
}
const char *t_strdup_until(const void *start, const void *end)
{
- return p_strdup_until(data_stack_pool, start, end);
+ return p_strdup_until(unsafe_data_stack_pool, start, end);
}
const char *t_strndup(const void *str, size_t max_chars)
{
- return p_strndup(data_stack_pool, str, max_chars);
+ return p_strndup(unsafe_data_stack_pool, str, max_chars);
}
const char *t_strdup_printf(const char *format, ...)
const char *ret;
va_start(args, format);
- ret = p_strdup_vprintf(data_stack_pool, format, args);
+ ret = p_strdup_vprintf(unsafe_data_stack_pool, format, args);
va_end(args);
return ret;
const char *t_strdup_vprintf(const char *format, va_list args)
{
- return p_strdup_vprintf(data_stack_pool, format, args);
+ return p_strdup_vprintf(unsafe_data_stack_pool, format, args);
}
const char *t_strconcat(const char *str1, ...)
t_push();
- buf = buffer_create_dynamic(data_stack_pool, size*2, (size_t)-1);
+ buf = buffer_create_dynamic(pool_datastack_create(),
+ size*2, (size_t)-1);
buffer_append(buf, "+ ", 2);
base64_encode(data, size, buf);
buffer_append(buf, "\r\n", 2);
}
linelen = strlen(line);
- buf = buffer_create_static_hard(data_stack_pool, linelen);
+ buf = buffer_create_static_hard(pool_datastack_create(), linelen);
if (base64_decode((const unsigned char *) line, linelen,
NULL, buf) <= 0) {
size_t i, count;
/* find the oldest clients and put them to destroy-buffer */
- destroy_buf = buffer_create_static_hard(data_stack_pool,
+ destroy_buf = buffer_create_static_hard(pool_datastack_create(),
sizeof(struct pop3_client *) *
CLIENT_DESTROY_OLDEST_COUNT);
hash_foreach(clients, client_hash_destroy_oldest, destroy_buf);