From 8e4a702a1f96f118976da6eb9ece344df625eabb Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 15 Jan 2013 08:30:03 +0200 Subject: [PATCH] buffer: Always keep +1 byte available for str_c()'s NUL. --- src/lib/Makefile.am | 1 + src/lib/buffer.c | 11 +++++++++-- src/lib/str.c | 3 --- src/lib/test-lib.c | 1 + src/lib/test-lib.h | 1 + src/lib/test-str.c | 26 ++++++++++++++++++++++++++ 6 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 src/lib/test-str.c diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index eeccfd86fd..ebb025f58b 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -268,6 +268,7 @@ test_lib_SOURCES = \ test-primes.c \ test-priorityq.c \ test-seq-range-array.c \ + test-str.c \ test-strescape.c \ test-strfuncs.c \ test-str-find.c \ diff --git a/src/lib/buffer.c b/src/lib/buffer.c index e056da9e87..c73bc0340b 100644 --- a/src/lib/buffer.c +++ b/src/lib/buffer.c @@ -39,6 +39,7 @@ static void buffer_alloc(struct real_buffer *buf, size_t size) static inline void buffer_check_limits(struct real_buffer *buf, size_t pos, size_t data_size) { + unsigned int extra; size_t new_size; if (unlikely((size_t)-1 - pos < data_size)) { @@ -53,7 +54,13 @@ buffer_check_limits(struct real_buffer *buf, size_t pos, size_t data_size) memset(buf->w_buffer + buf->used, 0, max - buf->used); } - if (new_size > buf->alloc) { + + /* always keep +1 byte allocated available in case str_c() is called + for this buffer. this is mainly for cases where the buffer is + allocated from data stack, and str_c() is called in a separate stack + frame. */ + extra = buf->dynamic ? 1 : 0; + if (new_size + extra > buf->alloc) { if (unlikely(!buf->dynamic)) { i_panic("Buffer full (%"PRIuSIZE_T" > %"PRIuSIZE_T", " "pool %s)", pos + data_size, buf->alloc, @@ -62,7 +69,7 @@ buffer_check_limits(struct real_buffer *buf, size_t pos, size_t data_size) } buffer_alloc(buf, pool_get_exp_grown_size(buf->pool, buf->alloc, - new_size)); + new_size + extra)); } #if 0 else if (new_size > buf->used && buf->alloced && diff --git a/src/lib/str.c b/src/lib/str.c index 0f9d6ce244..719d8d0eda 100644 --- a/src/lib/str.c +++ b/src/lib/str.c @@ -45,9 +45,6 @@ static void str_add_nul(string_t *str) size_t len = str_len(str); size_t alloc = buffer_get_size(str); -#ifdef DEBUG - buffer_verify_pool(str); -#endif if (len == alloc || data[len] != '\0') { buffer_write(str, len, "", 1); /* remove the \0 - we don't want to keep it */ diff --git a/src/lib/test-lib.c b/src/lib/test-lib.c index ca6f223f3d..21c3b84c83 100644 --- a/src/lib/test-lib.c +++ b/src/lib/test-lib.c @@ -25,6 +25,7 @@ int main(void) test_primes, test_priorityq, test_seq_range_array, + test_str, test_strescape, test_strfuncs, test_str_find, diff --git a/src/lib/test-lib.h b/src/lib/test-lib.h index c7cc7b9e36..206ef4d5f5 100644 --- a/src/lib/test-lib.h +++ b/src/lib/test-lib.h @@ -24,6 +24,7 @@ void test_ostream_file(void); void test_primes(void); void test_priorityq(void); void test_seq_range_array(void); +void test_str(void); void test_strescape(void); void test_strfuncs(void); void test_str_find(void); diff --git a/src/lib/test-str.c b/src/lib/test-str.c new file mode 100644 index 0000000000..deb4b7470d --- /dev/null +++ b/src/lib/test-str.c @@ -0,0 +1,26 @@ +/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "str.h" + +static void test_str_c(void) +{ + string_t *str; + unsigned int i, j; + + test_begin("str_c()"); + for (i = 0; i < 32; i++) T_BEGIN { + str = t_str_new(15); + for (j = 0; j < i; j++) + str_append_c(str, 'x'); + T_BEGIN { + (void)str_c(str); + } T_END; + } T_END; + test_end(); +} + +void test_str(void) +{ + test_str_c(); +} -- 2.47.3