"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/lib/data-stack.c" between
dovecot-2.3.16.tar.gz and dovecot-2.3.17.tar.gz

About: Dovecot is an IMAP and POP3 server, written with security primarily in mind.

data-stack.c  (dovecot-2.3.16):data-stack.c  (dovecot-2.3.17)
skipping to change at line 115 skipping to change at line 115
{ {
return STACK_BLOCK_DATA(block) + (block->size - block->left); return STACK_BLOCK_DATA(block) + (block->size - block->left);
} }
static void data_stack_last_buffer_reset(bool preserve_data ATTR_UNUSED) static void data_stack_last_buffer_reset(bool preserve_data ATTR_UNUSED)
{ {
if (last_buffer_block != NULL) { if (last_buffer_block != NULL) {
#ifdef DEBUG #ifdef DEBUG
unsigned char *last_alloc_end, *p, *pend; unsigned char *last_alloc_end, *p, *pend;
/* We assume that this function gets called before
current_block changes. */
i_assert(last_buffer_block == current_block);
last_alloc_end = data_stack_after_last_alloc(current_block); last_alloc_end = data_stack_after_last_alloc(current_block);
p = last_alloc_end + MEM_ALIGN(sizeof(size_t)) + last_buffer_size ; p = last_alloc_end + MEM_ALIGN(sizeof(size_t)) + last_buffer_size ;
pend = last_alloc_end + ALLOC_SIZE(last_buffer_size); pend = last_alloc_end + ALLOC_SIZE(last_buffer_size);
#endif #endif
/* reset t_buffer_get() mark - not really needed but makes it /* reset t_buffer_get() mark - not really needed but makes it
easier to notice if t_malloc()/t_push()/t_pop() is called easier to notice if t_malloc()/t_push()/t_pop() is called
between t_buffer_get() and t_buffer_alloc(). between t_buffer_get() and t_buffer_alloc().
do this before we get to i_panic() to avoid recursive do this before we get to i_panic() to avoid recursive
panics. */ panics. */
last_buffer_block = NULL; last_buffer_block = NULL;
#ifdef DEBUG #ifdef DEBUG
/* NOTE: If the below panic triggers, it may also be due to an
internal bug in data-stack (since this is rather complex). Whi
le
debugging whether that is the case, it's a good idea to change
the
i_panic() to abort(). Otherwise the i_panic() changes the
data-stack's internal state and complicates debugging. */
while (p < pend) while (p < pend)
if (*p++ != CLEAR_CHR) if (*p++ != CLEAR_CHR)
i_panic("t_buffer_get(): buffer overflow"); i_panic("t_buffer_get(): buffer overflow");
if (!preserve_data) { if (!preserve_data) {
p = last_alloc_end; p = last_alloc_end;
memset(p, CLEAR_CHR, SENTRY_COUNT); memset(p, CLEAR_CHR, SENTRY_COUNT);
} }
#endif #endif
} }
skipping to change at line 161 skipping to change at line 170
/* allocate new block */ /* allocate new block */
frame = t_buffer_get(sizeof(*frame)); frame = t_buffer_get(sizeof(*frame));
frame->prev = current_frame; frame->prev = current_frame;
current_frame = frame; current_frame = frame;
/* mark our current position */ /* mark our current position */
current_frame->block = current_block; current_frame->block = current_block;
current_frame->block_space_left = current_block->left; current_frame->block_space_left = current_block->left;
current_frame->last_alloc_size = 0; current_frame->last_alloc_size = 0;
current_frame->marker = marker; current_frame->marker = marker;
#ifdef DEBUG
current_frame->alloc_bytes = 0;
current_frame->alloc_count = 0;
#endif
t_buffer_alloc(sizeof(*frame)); t_buffer_alloc(sizeof(*frame));
#ifndef STATIC_CHECKER #ifndef STATIC_CHECKER
return data_stack_frame_id++; return data_stack_frame_id++;
#else #else
struct data_stack_frame *ds_frame = i_new(struct data_stack_frame, 1); struct data_stack_frame *ds_frame = i_new(struct data_stack_frame, 1);
ds_frame->id = data_stack_frame_id++; ds_frame->id = data_stack_frame_id++;
return ds_frame; return ds_frame;
#endif #endif
skipping to change at line 394 skipping to change at line 407
static void data_stack_send_grow_event(size_t last_alloc_size) static void data_stack_send_grow_event(size_t last_alloc_size)
{ {
if (event_datastack_deinitialized) { if (event_datastack_deinitialized) {
/* already in the deinitialization code - /* already in the deinitialization code -
don't send more events */ don't send more events */
return; return;
} }
if (event_datastack == NULL) if (event_datastack == NULL)
event_datastack = event_create(NULL); event_datastack = event_create(NULL);
event_set_name(event_datastack, "data_stack_grow"); event_set_name(event_datastack, "data_stack_grow");
if (!event_want_debug(event_datastack))
return;
const char *backtrace;
if (backtrace_get(&backtrace) == 0)
event_add_str(event_datastack, "backtrace", backtrace);
event_add_int(event_datastack, "alloc_size", data_stack_get_alloc_size()) ; event_add_int(event_datastack, "alloc_size", data_stack_get_alloc_size()) ;
event_add_int(event_datastack, "used_size", data_stack_get_used_size()); event_add_int(event_datastack, "used_size", data_stack_get_used_size());
event_add_int(event_datastack, "last_alloc_size", last_alloc_size); event_add_int(event_datastack, "last_alloc_size", last_alloc_size);
event_add_int(event_datastack, "last_block_size", current_block->size); event_add_int(event_datastack, "last_block_size", current_block->size);
#ifdef DEBUG #ifdef DEBUG
event_add_int(event_datastack, "frame_alloc_bytes", event_add_int(event_datastack, "frame_alloc_bytes",
current_frame->alloc_bytes); current_frame->alloc_bytes);
event_add_int(event_datastack, "frame_alloc_count", event_add_int(event_datastack, "frame_alloc_count",
current_frame->alloc_count); current_frame->alloc_count);
#endif #endif
event_add_str(event_datastack, "frame_marker", current_frame->marker); event_add_str(event_datastack, "frame_marker", current_frame->marker);
/* It's possible that the data stack gets grown and shrunk rapidly.
Try to avoid doing expensive work if the event isn't even used for
anything. Note that at this point all the event fields must be
set already that might potentially be used by the filters. */
if (!event_want_debug(event_datastack))
return;
/* Getting backtrace is potentially inefficient, so do it after
checking if the event is wanted. Note that this prevents using the
backtrace field in event field comparisons. */
const char *backtrace;
if (backtrace_get(&backtrace) == 0)
event_add_str(event_datastack, "backtrace", backtrace);
string_t *str = t_str_new(128); string_t *str = t_str_new(128);
str_printfa(str, "total_used=%zu, total_alloc=%zu, last_alloc_size=%zu", str_printfa(str, "total_used=%zu, total_alloc=%zu, last_alloc_size=%zu",
data_stack_get_used_size(), data_stack_get_used_size(),
data_stack_get_alloc_size(), data_stack_get_alloc_size(),
last_alloc_size); last_alloc_size);
#ifdef DEBUG #ifdef DEBUG
str_printfa(str, ", frame_bytes=%llu, frame_alloc_count=%u", str_printfa(str, ", frame_bytes=%llu, frame_alloc_count=%u",
current_frame->alloc_bytes, current_frame->alloc_count); current_frame->alloc_bytes, current_frame->alloc_count);
#endif #endif
e_debug(event_datastack, "Growing data stack by %zu for '%s' (%s)", e_debug(event_datastack, "Growing data stack by %zu for '%s' (%s)",
skipping to change at line 493 skipping to change at line 514
ret = data_stack_after_last_alloc(current_block); ret = data_stack_after_last_alloc(current_block);
#ifdef DEBUG #ifdef DEBUG
if (current_block->left - alloc_size < current_block->left_lowwater) if (current_block->left - alloc_size < current_block->left_lowwater)
current_block->left_lowwater = current_block->left - alloc_size; current_block->left_lowwater = current_block->left - alloc_size;
#endif #endif
if (permanent) if (permanent)
current_block->left -= alloc_size; current_block->left -= alloc_size;
if (warn) T_BEGIN { if (warn) T_BEGIN {
/* sending event can cause errno changes. */
#ifdef DEBUG
i_assert(errno == old_errno);
#else
int old_errno = errno;
#endif
/* warn after allocation, so if e_debug() wants to /* warn after allocation, so if e_debug() wants to
allocate more memory we don't go to infinite loop */ allocate more memory we don't go to infinite loop */
data_stack_send_grow_event(alloc_size); data_stack_send_grow_event(alloc_size);
/* reset errno back to what it was */
errno = old_errno;
} T_END; } T_END;
#ifdef DEBUG #ifdef DEBUG
memcpy(ret, &size, sizeof(size)); memcpy(ret, &size, sizeof(size));
ret = PTR_OFFSET(ret, MEM_ALIGN(sizeof(size))); ret = PTR_OFFSET(ret, MEM_ALIGN(sizeof(size)));
/* make sure the sentry contains CLEAR_CHRs. it might not if we /* make sure the sentry contains CLEAR_CHRs. it might not if we
had used t_buffer_get(). */ had used t_buffer_get(). */
memset(PTR_OFFSET(ret, size), CLEAR_CHR, memset(PTR_OFFSET(ret, size), CLEAR_CHR,
MEM_ALIGN(size + SENTRY_COUNT) - size); MEM_ALIGN(size + SENTRY_COUNT) - size);
/* we rely on errno not changing. it shouldn't. */ /* we rely on errno not changing. it shouldn't. */
skipping to change at line 534 skipping to change at line 563
bool ATTR_NO_SANITIZE_INTEGER bool ATTR_NO_SANITIZE_INTEGER
t_try_realloc(void *mem, size_t size) t_try_realloc(void *mem, size_t size)
{ {
size_t debug_adjust = 0, last_alloc_size; size_t debug_adjust = 0, last_alloc_size;
unsigned char *after_last_alloc; unsigned char *after_last_alloc;
if (unlikely(size == 0 || size > SSIZE_T_MAX)) if (unlikely(size == 0 || size > SSIZE_T_MAX))
i_panic("Trying to allocate %zu bytes", size); i_panic("Trying to allocate %zu bytes", size);
block_canary_check(current_block); block_canary_check(current_block);
data_stack_last_buffer_reset(TRUE);
last_alloc_size = current_frame->last_alloc_size; last_alloc_size = current_frame->last_alloc_size;
/* see if we're trying to grow the memory we allocated last */ /* see if we're trying to grow the memory we allocated last */
after_last_alloc = data_stack_after_last_alloc(current_block); after_last_alloc = data_stack_after_last_alloc(current_block);
#ifdef DEBUG #ifdef DEBUG
debug_adjust = MEM_ALIGN(sizeof(size_t)); debug_adjust = MEM_ALIGN(sizeof(size_t));
#endif #endif
if (after_last_alloc - last_alloc_size + debug_adjust == mem) { if (after_last_alloc - last_alloc_size + debug_adjust == mem) {
/* yeah, see if we have space to grow */ /* yeah, see if we have space to grow */
skipping to change at line 686 skipping to change at line 716
} }
size_t data_stack_get_alloc_size(void) size_t data_stack_get_alloc_size(void)
{ {
struct stack_block *block; struct stack_block *block;
size_t size = 0; size_t size = 0;
i_assert(current_block->next == NULL); i_assert(current_block->next == NULL);
for (block = current_block; block != NULL; block = block->prev) for (block = current_block; block != NULL; block = block->prev)
size += current_block->size; size += block->size;
return size; return size;
} }
size_t data_stack_get_used_size(void) size_t data_stack_get_used_size(void)
{ {
struct stack_block *block; struct stack_block *block;
size_t size = 0; size_t size = 0;
i_assert(current_block->next == NULL); i_assert(current_block->next == NULL);
for (block = current_block; block != NULL; block = block->prev) for (block = current_block; block != NULL; block = block->prev)
size += current_block->size - current_block->left; size += block->size - block->left;
return size; return size;
} }
void data_stack_free_unused(void) void data_stack_free_unused(void)
{ {
free(unused_block); free(unused_block);
unused_block = NULL; unused_block = NULL;
} }
void data_stack_init(void) void data_stack_init(void)
 End of changes. 10 change blocks. 
8 lines changed or deleted 40 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)