]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
buffer: Always keep +1 byte available for str_c()'s NUL.
authorTimo Sirainen <tss@iki.fi>
Tue, 15 Jan 2013 06:30:03 +0000 (08:30 +0200)
committerTimo Sirainen <tss@iki.fi>
Tue, 15 Jan 2013 06:30:03 +0000 (08:30 +0200)
src/lib/Makefile.am
src/lib/buffer.c
src/lib/str.c
src/lib/test-lib.c
src/lib/test-lib.h
src/lib/test-str.c [new file with mode: 0644]

index eeccfd86fd86fd4a71f7bf5260074960edda2ae0..ebb025f58b199c6ae65051776a88234761bb28e4 100644 (file)
@@ -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 \
index e056da9e8753a7b56df717a74c6079fe562fc2b0..c73bc0340b1acfe4dfa80fb7068f1547c0b3e182 100644 (file)
@@ -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 &&
index 0f9d6ce244b28739394edb7bcd7f3107bc0fdc46..719d8d0eda14d42300a888ea24dc6ac0721e696f 100644 (file)
@@ -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 */
index ca6f223f3d699992859110def15202c66b7639a8..21c3b84c839d44e9f6d051f2479ab5e07316ee9e 100644 (file)
@@ -25,6 +25,7 @@ int main(void)
                test_primes,
                test_priorityq,
                test_seq_range_array,
+               test_str,
                test_strescape,
                test_strfuncs,
                test_str_find,
index c7cc7b9e36afa04bfc5e9bc5c63c2ac264d63d8a..206ef4d5f5420bdeb8c804df6bb2559193ef631b 100644 (file)
@@ -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 (file)
index 0000000..deb4b74
--- /dev/null
@@ -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();
+}