dovecot-2.2: iostreams: Set stream error string when it provides...

dovecot at dovecot.org dovecot at dovecot.org
Fri Sep 20 00:13:04 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/76d5e3c8cec3
changeset: 16773:76d5e3c8cec3
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Sep 20 00:12:45 2013 +0300
description:
iostreams: Set stream error string when it provides extra information.

diffstat:

 src/lib-compression/istream-bzlib.c           |  23 ++++++++---------
 src/lib-compression/istream-zlib.c            |  36 ++++++++++----------------
 src/lib-fs/istream-metawrap.c                 |   2 +
 src/lib-mail/istream-dot.c                    |   2 +
 src/lib-mail/istream-qp-decoder.c             |  11 +++++++-
 src/lib-ssl-iostream/iostream-openssl.c       |  23 +++++++++++++++--
 src/lib-ssl-iostream/iostream-openssl.h       |   1 +
 src/lib-ssl-iostream/istream-openssl.c        |   4 +++
 src/lib-ssl-iostream/ostream-openssl.c        |   4 +++
 src/lib-storage/index/istream-mail.c          |   4 ++-
 src/lib-storage/index/mbox/istream-raw-mbox.c |  19 +++++++++-----
 src/lib/istream-base64-decoder.c              |  11 +++++++-
 src/lib/istream-concat.c                      |  10 +++++--
 src/lib/istream-file.c                        |  13 ++++++---
 src/lib/istream-hash.c                        |   3 +-
 src/lib/istream-jsonstr.c                     |   2 +
 src/lib/istream-mmap.c                        |   2 +
 src/lib/istream-sized.c                       |  19 ++++++++++---
 src/lib/ostream-file.c                        |  10 ++++++-
 19 files changed, 138 insertions(+), 61 deletions(-)

diffs (truncated from 634 to 300 lines):

diff -r e35be66003e2 -r 76d5e3c8cec3 src/lib-compression/istream-bzlib.c
--- a/src/lib-compression/istream-bzlib.c	Fri Sep 20 00:00:49 2013 +0300
+++ b/src/lib-compression/istream-bzlib.c	Fri Sep 20 00:12:45 2013 +0300
@@ -38,10 +38,13 @@
 
 static void bzlib_read_error(struct bzlib_istream *zstream, const char *error)
 {
-	i_error("bzlib.read(%s): %s at %"PRIuUOFF_T,
-		i_stream_get_name(&zstream->istream.istream), error,
-		zstream->istream.abs_start_offset +
-		zstream->istream.istream.v_offset);
+	io_stream_set_error(&zstream->istream.iostream,
+			    "bzlib.read(%s): %s at %"PRIuUOFF_T,
+			    i_stream_get_name(&zstream->istream.istream), error,
+			    zstream->istream.abs_start_offset +
+			    zstream->istream.istream.v_offset);
+	if (zstream->log_errors)
+		i_error("%s", zstream->istream.iostream.error);
 }
 
 static ssize_t i_stream_bzlib_read(struct istream_private *stream)
@@ -104,8 +107,7 @@
 				stream->parent->stream_errno;
 		} else {
 			i_assert(stream->parent->eof);
-			if (zstream->log_errors)
-				bzlib_read_error(zstream, "unexpected EOF");
+			bzlib_read_error(zstream, "unexpected EOF");
 			stream->istream.stream_errno = EINVAL;
 		}
 		return -1;
@@ -135,15 +137,12 @@
 	case BZ_PARAM_ERROR:
 		i_unreached();
 	case BZ_DATA_ERROR:
-		if (zstream->log_errors)
-			bzlib_read_error(zstream, "corrupted data");
+		bzlib_read_error(zstream, "corrupted data");
 		stream->istream.stream_errno = EINVAL;
 		return -1;
 	case BZ_DATA_ERROR_MAGIC:
-		if (zstream->log_errors) {
-			bzlib_read_error(zstream,
-				"wrong magic in header (not bz2 file?)");
-		}
+		bzlib_read_error(zstream,
+			"wrong magic in header (not bz2 file?)");
 		stream->istream.stream_errno = EINVAL;
 		return -1;
 	case BZ_MEM_ERROR:
diff -r e35be66003e2 -r 76d5e3c8cec3 src/lib-compression/istream-zlib.c
--- a/src/lib-compression/istream-zlib.c	Fri Sep 20 00:00:49 2013 +0300
+++ b/src/lib-compression/istream-zlib.c	Fri Sep 20 00:12:45 2013 +0300
@@ -55,10 +55,13 @@
 
 static void zlib_read_error(struct zlib_istream *zstream, const char *error)
 {
-	i_error("zlib.read(%s): %s at %"PRIuUOFF_T,
-		i_stream_get_name(&zstream->istream.istream), error,
-		zstream->istream.abs_start_offset +
-		zstream->istream.istream.v_offset);
+	io_stream_set_error(&zstream->istream.iostream,
+			    "zlib.read(%s): %s at %"PRIuUOFF_T,
+			    i_stream_get_name(&zstream->istream.istream), error,
+			    zstream->istream.abs_start_offset +
+			    zstream->istream.istream.v_offset);
+	if (zstream->log_errors)
+		i_error("%s", zstream->istream.iostream.error);
 }
 
 static int i_stream_zlib_read_header(struct istream_private *stream)
@@ -73,8 +76,7 @@
 				 zstream->prev_size);
 	if (size == zstream->prev_size) {
 		if (ret == -1) {
-			if (zstream->log_errors)
-				zlib_read_error(zstream, "missing gz header");
+			zlib_read_error(zstream, "missing gz header");
 			stream->istream.stream_errno = EINVAL;
 		}
 		return ret;
@@ -87,10 +89,7 @@
 
 	if (data[0] != GZ_MAGIC1 || data[1] != GZ_MAGIC2) {
 		/* missing gzip magic header */
-		if (zstream->log_errors) {
-			zlib_read_error(zstream, "wrong magic in header "
-					"(not gz file?)");
-		}
+		zlib_read_error(zstream, "wrong magic in header (not gz file?)");
 		stream->istream.stream_errno = EINVAL;
 		return -1;
 	}
@@ -143,8 +142,7 @@
 				 GZ_TRAILER_SIZE-1);
 	if (size == zstream->prev_size) {
 		if (ret == -1) {
-			if (zstream->log_errors)
-				zlib_read_error(zstream, "missing gz trailer");
+			zlib_read_error(zstream, "missing gz trailer");
 			stream->istream.stream_errno = EINVAL;
 		}
 		return ret;
@@ -155,10 +153,7 @@
 		return 0;
 
 	if (data_get_uint32(data) != zstream->crc32) {
-		if (zstream->log_errors) {
-			zlib_read_error(zstream,
-					"gz trailer has wrong CRC value");
-		}
+		zlib_read_error(zstream, "gz trailer has wrong CRC value");
 		stream->istream.stream_errno = EINVAL;
 		return -1;
 	}
@@ -254,8 +249,7 @@
 				stream->parent->stream_errno;
 		} else {
 			i_assert(stream->parent->eof);
-			if (zstream->log_errors)
-				zlib_read_error(zstream, "unexpected EOF");
+			zlib_read_error(zstream, "unexpected EOF");
 			stream->istream.stream_errno = EPIPE;
 		}
 		return -1;
@@ -286,13 +280,11 @@
 	case Z_OK:
 		break;
 	case Z_NEED_DICT:
-		if (zstream->log_errors)
-			zlib_read_error(zstream, "can't read file without dict");
+		zlib_read_error(zstream, "can't read file without dict");
 		stream->istream.stream_errno = EINVAL;
 		return -1;
 	case Z_DATA_ERROR:
-		if (zstream->log_errors)
-			zlib_read_error(zstream, "corrupted data");
+		zlib_read_error(zstream, "corrupted data");
 		stream->istream.stream_errno = EINVAL;
 		return -1;
 	case Z_MEM_ERROR:
diff -r e35be66003e2 -r 76d5e3c8cec3 src/lib-fs/istream-metawrap.c
--- a/src/lib-fs/istream-metawrap.c	Fri Sep 20 00:00:49 2013 +0300
+++ b/src/lib-fs/istream-metawrap.c	Fri Sep 20 00:12:45 2013 +0300
@@ -24,6 +24,8 @@
 		}
 		p = strchr(line, ':');
 		if (p == NULL) {
+			io_stream_set_error(&mstream->istream.iostream,
+				"Metadata header line is missing ':'");
 			mstream->istream.istream.stream_errno = EINVAL;
 			return -1;
 		}
diff -r e35be66003e2 -r 76d5e3c8cec3 src/lib-mail/istream-dot.c
--- a/src/lib-mail/istream-dot.c	Fri Sep 20 00:00:49 2013 +0300
+++ b/src/lib-mail/istream-dot.c	Fri Sep 20 00:12:45 2013 +0300
@@ -36,6 +36,8 @@
 					stream->parent->stream_errno;
 			} else if (ret < 0 && stream->parent->eof) {
 				/* we didn't see "." line */
+				io_stream_set_error(&stream->iostream,
+					"dot-input stream ends without '.' line");
 				stream->istream.stream_errno = EPIPE;
 			}
 			return ret;
diff -r e35be66003e2 -r 76d5e3c8cec3 src/lib-mail/istream-qp-decoder.c
--- a/src/lib-mail/istream-qp-decoder.c	Fri Sep 20 00:00:49 2013 +0300
+++ b/src/lib-mail/istream-qp-decoder.c	Fri Sep 20 00:12:45 2013 +0300
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "buffer.h"
+#include "hex-binary.h"
 #include "istream-private.h"
 #include "quoted-printable.h"
 #include "istream-qp.h"
@@ -64,6 +65,9 @@
 	ret = !eof ? quoted_printable_decode(data, size, &pos, &buf) :
 		quoted_printable_decode_final(data, size, &pos, &buf);
 	if (ret < 0) {
+		io_stream_set_error(&stream->iostream,
+			"Invalid quoted-printable data: 0x%s",
+			binary_to_hex(data+pos, I_MAX(size-pos, 8)));
 		stream->istream.stream_errno = EINVAL;
 		return -1;
 	}
@@ -77,7 +81,8 @@
 {
 	struct qp_decoder_istream *bstream =
 		(struct qp_decoder_istream *)stream;
-	size_t pre_count, post_count;
+	const unsigned char *data;
+	size_t pre_count, post_count, size;
 	int ret;
 	size_t prev_size = 0;
 
@@ -95,6 +100,10 @@
 			}
 			/* partial qp input */
 			i_assert(ret < 0);
+			data = i_stream_get_data(stream->parent, &size);
+			io_stream_set_error(&stream->iostream,
+				"quoted-printable input ends with a partial block: 0x%s",
+				binary_to_hex(data, size));
 			stream->istream.stream_errno = EINVAL;
 			return -1;
 		}
diff -r e35be66003e2 -r 76d5e3c8cec3 src/lib-ssl-iostream/iostream-openssl.c
--- a/src/lib-ssl-iostream/iostream-openssl.c	Fri Sep 20 00:00:49 2013 +0300
+++ b/src/lib-ssl-iostream/iostream-openssl.c	Fri Sep 20 00:12:45 2013 +0300
@@ -270,6 +270,7 @@
 	o_stream_unref(&ssl_io->plain_output);
 	BIO_free(ssl_io->bio_ext);
 	SSL_free(ssl_io->ssl);
+	i_free(ssl_io->plain_stream_errstr);
 	i_free(ssl_io->last_error);
 	i_free(ssl_io->host);
 	i_free(ssl_io->log_prefix);
@@ -331,6 +332,9 @@
 		if (sent < 0) {
 			i_assert(ssl_io->plain_output->closed ||
 				 ssl_io->plain_output->stream_errno != 0);
+			i_free(ssl_io->plain_stream_errstr);
+			ssl_io->plain_stream_errstr =
+				i_strdup(o_stream_get_error(ssl_io->plain_output));
 			ssl_io->plain_stream_errno =
 				ssl_io->plain_output->stream_errno;
 			ssl_io->closed = TRUE;
@@ -376,6 +380,9 @@
 		ret = openssl_iostream_read_more(ssl_io, &data, &size);
 		ssl_io->plain_input->real_stream->try_alloc_limit = 0;
 		if (ret == -1 && size == 0 && !bytes_read) {
+			i_free(ssl_io->plain_stream_errstr);
+			ssl_io->plain_stream_errstr =
+				i_strdup(i_stream_get_error(ssl_io->plain_input));
 			ssl_io->plain_stream_errno =
 				ssl_io->plain_input->stream_errno;
 			ssl_io->closed = TRUE;
@@ -397,12 +404,18 @@
 	if (bytes == 0 && !bytes_read && ssl_io->want_read) {
 		/* shouldn't happen */
 		i_error("SSL BIO buffer size too small");
+		i_free(ssl_io->plain_stream_errstr);
+		ssl_io->plain_stream_errstr =
+			i_strdup("SSL BIO buffer size too small");
 		ssl_io->plain_stream_errno = EINVAL;
 		ssl_io->closed = TRUE;
 		return FALSE;
 	}
 	if (i_stream_get_data_size(ssl_io->plain_input) > 0) {
 		i_error("SSL: Too much data in buffered plain input buffer");
+		i_free(ssl_io->plain_stream_errstr);
+		ssl_io->plain_stream_errstr =
+			i_strdup("SSL: Too much data in buffered plain input buffer");
 		ssl_io->plain_stream_errno = EINVAL;
 		ssl_io->closed = TRUE;
 		return FALSE;
@@ -455,6 +468,8 @@
 			return 0;
 		}
 		if (ssl_io->closed) {
+			if (ssl_io->plain_stream_errstr != NULL)
+				openssl_iostream_set_error(ssl_io, ssl_io->plain_stream_errstr);
 			errno = ssl_io->plain_stream_errno != 0 ?
 				ssl_io->plain_stream_errno : EPIPE;
 			return -1;
@@ -464,6 +479,8 @@
 		ssl_io->want_read = TRUE;
 		(void)openssl_iostream_bio_sync(ssl_io);
 		if (ssl_io->closed) {
+			if (ssl_io->plain_stream_errstr != NULL)
+				openssl_iostream_set_error(ssl_io, ssl_io->plain_stream_errstr);
 			errno = ssl_io->plain_stream_errno != 0 ?
 				ssl_io->plain_stream_errno : EPIPE;
 			return -1;
@@ -489,7 +506,8 @@
 	case SSL_ERROR_ZERO_RETURN:
 		/* clean connection closing */
 		errno = ECONNRESET;
-		break;
+		i_free_and_null(ssl_io->last_error);
+		return -1;
 	case SSL_ERROR_SSL:
 		errstr = t_strdup_printf("%s failed: %s",
 					 func_name, openssl_iostream_error());
@@ -503,8 +521,7 @@
 		break;
 	}
 
-	if (errstr != NULL)
-		openssl_iostream_set_error(ssl_io, errstr);
+	openssl_iostream_set_error(ssl_io, errstr);
 	return -1;
 }
 
diff -r e35be66003e2 -r 76d5e3c8cec3 src/lib-ssl-iostream/iostream-openssl.h
--- a/src/lib-ssl-iostream/iostream-openssl.h	Fri Sep 20 00:00:49 2013 +0300
+++ b/src/lib-ssl-iostream/iostream-openssl.h	Fri Sep 20 00:12:45 2013 +0300
@@ -31,6 +31,7 @@
 	char *host;


More information about the dovecot-cvs mailing list