dovecot-2.0: ostream-file: Fixed potential crash in write_at() a...

dovecot at dovecot.org dovecot at dovecot.org
Mon Oct 18 18:51:48 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/17957b5082cd
changeset: 12301:17957b5082cd
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Oct 18 16:51:12 2010 +0100
description:
ostream-file: Fixed potential crash in write_at() and also fixed attempted optimization.

diffstat:

 src/lib/Makefile.am         |   1 +
 src/lib/ostream-file.c      |  12 +++--
 src/lib/test-lib.c          |   1 +
 src/lib/test-lib.h          |   1 +
 src/lib/test-ostream-file.c |  69 ++++++++++++++++++++++++++++++++++
 5 files changed, 79 insertions(+), 5 deletions(-)

diffs (142 lines):

diff -r 0dae63c1af96 -r 17957b5082cd src/lib/Makefile.am
--- 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 \
diff -r 0dae63c1af96 -r 17957b5082cd src/lib/ostream-file.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;
-
 		}
 	}
 
diff -r 0dae63c1af96 -r 17957b5082cd src/lib/test-lib.c
--- 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,
diff -r 0dae63c1af96 -r 17957b5082cd src/lib/test-lib.h
--- 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);
diff -r 0dae63c1af96 -r 17957b5082cd src/lib/test-ostream-file.c
--- /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();
+}


More information about the dovecot-cvs mailing list