dovecot-1.0: Don't crash if duplicate database contains broken e...

dovecot at dovecot.org dovecot at dovecot.org
Sun Sep 16 13:51:54 EEST 2007


details:   http://hg.dovecot.org/dovecot-1.0/rev/9d4e89fa62d0
changeset: 5406:9d4e89fa62d0
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Sep 16 13:51:50 2007 +0300
description:
Don't crash if duplicate database contains broken entries.

diffstat:

1 file changed, 17 insertions(+), 1 deletion(-)
src/deliver/duplicate.c |   18 +++++++++++++++++-

diffs (59 lines):

diff -r 53d5fd13470d -r 9d4e89fa62d0 src/deliver/duplicate.c
--- a/src/deliver/duplicate.c	Sun Sep 16 10:56:33 2007 +0300
+++ b/src/deliver/duplicate.c	Sun Sep 16 13:51:50 2007 +0300
@@ -15,6 +15,7 @@
 
 #define DUPLICATE_PATH "~/.dovecot.lda-dupes"
 #define COMPRESS_PERCENTAGE 10
+#define DUPLICATE_BUFSIZE 4096
 
 struct duplicate {
 	const void *id;
@@ -84,6 +85,7 @@ static int duplicate_read(struct duplica
 	size_t size;
 	time_t stamp;
 	unsigned int offset, id_size, user_size, change_count;
+	bool broken = FALSE;
 
 	fd = open(file->path, O_RDONLY);
 	if (fd == -1) {
@@ -94,7 +96,8 @@ static int duplicate_read(struct duplica
 	}
 
 	/* <timestamp> <id_size> <user_size> <id> <user> */
-	input = i_stream_create_file(fd, default_pool, 4096, FALSE);
+	input = i_stream_create_file(fd, default_pool,
+				     DUPLICATE_BUFSIZE, FALSE);
 
 	change_count = 0;
 	while (i_stream_read_data(input, &data, &size, sizeof(stamp) +
@@ -109,9 +112,18 @@ static int duplicate_read(struct duplica
 
 		i_stream_skip(input, offset);
 
+		if (id_size == 0 || user_size == 0 ||
+		    id_size > DUPLICATE_BUFSIZE ||
+		    user_size > DUPLICATE_BUFSIZE) {
+			i_error("broken duplicate file %s", file->path);
+			broken = TRUE;
+			break;
+		}
+
 		if (i_stream_read_data(input, &data, &size,
 				       id_size + user_size - 1) <= 0) {
 			i_error("unexpected end of file in %s", file->path);
+			broken = TRUE;
 			break;
 		}
 
@@ -142,6 +154,10 @@ static int duplicate_read(struct duplica
 	i_stream_unref(&input);
 	if (close(fd) < 0)
 		i_error("close(%s) failed: %m", file->path);
+	if (broken) {
+		if (unlink(file->path) < 0 && errno != ENOENT)
+			i_error("unlink(%s) failed: %m", file->path);
+	}
 	return 0;
 }
 


More information about the dovecot-cvs mailing list