Mercurial > dovecot > core-2.2
changeset 12301:17957b5082cd
ostream-file: Fixed potential crash in write_at() and also fixed attempted optimization.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 18 Oct 2010 16:51:12 +0100 |
parents | 0dae63c1af96 |
children | 27289650ed4c |
files | src/lib/Makefile.am src/lib/ostream-file.c src/lib/test-lib.c src/lib/test-lib.h src/lib/test-ostream-file.c |
diffstat | 5 files changed, 79 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/Makefile.am Mon Oct 18 16:14:08 2010 +0100 +++ b/src/lib/Makefile.am Mon Oct 18 16:51:12 2010 +0100 @@ -237,6 +237,7 @@ test-llist.c \ test-mempool-alloconly.c \ test-network.c \ + test-ostream-file.c \ test-primes.c \ test-priorityq.c \ test-seq-range-array.c \
--- a/src/lib/ostream-file.c Mon Oct 18 16:14:08 2010 +0100 +++ b/src/lib/ostream-file.c Mon Oct 18 16:51:12 2010 +0100 @@ -621,7 +621,8 @@ /* update buffer if the write overlaps it */ used = file_buffer_get_used_size(fstream); - if (fstream->buffer_offset < offset + size && + if (used > 0 && + fstream->buffer_offset < offset + size && fstream->buffer_offset + used > offset) { if (fstream->buffer_offset <= offset) { /* updating from the beginning */ @@ -641,9 +642,11 @@ of it in one pwrite(). */ } else { /* write only the suffix */ - data = CONST_PTR_OFFSET(data, skip); - size -= skip; - offset += skip; + unsigned int update_count = size - left; + + data = CONST_PTR_OFFSET(data, update_count); + size -= update_count; + offset += update_count; } } else if (skip == 0) { /* everything done */ @@ -651,7 +654,6 @@ } else { /* still have to write prefix */ size = skip; - } }
--- a/src/lib/test-lib.c Mon Oct 18 16:14:08 2010 +0100 +++ b/src/lib/test-lib.c Mon Oct 18 16:51:12 2010 +0100 @@ -19,6 +19,7 @@ test_llist, test_mempool_alloconly, test_network, + test_ostream_file, test_primes, test_priorityq, test_seq_range_array,
--- a/src/lib/test-lib.h Mon Oct 18 16:14:08 2010 +0100 +++ b/src/lib/test-lib.h Mon Oct 18 16:51:12 2010 +0100 @@ -18,6 +18,7 @@ void test_llist(void); void test_mempool_alloconly(void); void test_network(void); +void test_ostream_file(void); void test_primes(void); void test_priorityq(void); void test_seq_range_array(void);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/test-ostream-file.c Mon Oct 18 16:51:12 2010 +0100 @@ -0,0 +1,69 @@ +/* Copyright (c) 2009-2010 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "str.h" +#include "safe-mkstemp.h" +#include "randgen.h" +#include "ostream.h" + +#include <stdlib.h> +#include <unistd.h> + +#define MAX_BUFSIZE 256 + +static void test_ostream_file_random(void) +{ + struct ostream *output; + string_t *path = t_str_new(128); + char buf[MAX_BUFSIZE*4], buf2[MAX_BUFSIZE*4], randbuf[MAX_BUFSIZE]; + unsigned int i, offset, size; + ssize_t ret; + int fd; + + memset(buf, 0, sizeof(buf)); + fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1); + if (fd == -1) + i_fatal("safe_mkstemp(%s) failed: %m", str_c(path)); + if (unlink(str_c(path)) < 0) + i_fatal("unlink(%s) failed: %m", str_c(path)); + output = o_stream_create_fd(fd, MAX_BUFSIZE, FALSE); + o_stream_cork(output); + + size = (rand() % MAX_BUFSIZE) + 1; + random_fill_weak(randbuf, size); + memcpy(buf, randbuf, size); + o_stream_send(output, buf, size); + + for (i = 0; i < 10; i++) { + offset = rand() % (MAX_BUFSIZE*3); + size = (rand() % MAX_BUFSIZE) + 1; + random_fill_weak(randbuf, size); + memcpy(buf + offset, randbuf, size); + o_stream_pwrite(output, randbuf, size, offset); + if (rand() % 10 == 0) + o_stream_flush(output); + } + + o_stream_flush(output); + o_stream_uncork(output); + ret = pread(fd, buf2, sizeof(buf2), 0); + if (ret < 0) + i_fatal("pread() failed: %m"); + else { + i_assert(ret > 0); + test_assert(memcmp(buf, buf2, ret) == 0); + } + o_stream_unref(&output); + (void)close(fd); +} + +void test_ostream_file(void) +{ + unsigned int i; + + test_begin("ostream pwrite random"); + for (i = 0; i < 100; i++) T_BEGIN { + test_ostream_file_random(); + } T_END; + test_end(); +}