--- dovecot-2.0-pure/src/lib/istream-crlf.c	2010-08-08 10:05:33.000000000 +0200
+++ dovecot-2.0/src/lib/istream-crlf.c	2010-08-30 15:22:20.000000000 +0200
@@ -39,7 +39,8 @@
 {
 	struct crlf_istream *cstream = (struct crlf_istream *)stream;
 	const unsigned char *data;
-	size_t i, dest, size;
+	unsigned char *s_ptr, *s_end, *d_ptr, *d_end, *ptr;
+	size_t size, cpy_len;
 	ssize_t ret;

 	ret = i_stream_crlf_read_common(cstream);
@@ -49,27 +50,61 @@
 	data = i_stream_get_data(stream->parent, &size);

 	/* @UNSAFE: add missing CRs */
-	dest = stream->pos;
-	for (i = 0; i < size && dest < stream->buffer_size; i++) {
-		if (data[i] == '\n') {
-			if (i == 0) {
-				if (!cstream->last_cr)
-					stream->w_buffer[dest++] = '\r';
-			} else {
-				if (data[i-1] != '\r')
-					stream->w_buffer[dest++] = '\r';
-			}
-			if (dest == stream->buffer_size)
-				break;
+	d_ptr = stream->w_buffer + stream->pos;
+	d_end = stream->w_buffer + stream->buffer_size;
+	s_ptr = (unsigned char *)data;
+	s_end = (unsigned char *)data + size;
+
+	if (s_ptr < s_end && *s_ptr == '\n' && !cstream->last_cr && d_ptr < d_end) {
+		*(d_ptr++) = '\r';
+
+		if (d_ptr < d_end) {
+			*(d_ptr++) = '\n';
+			s_ptr++;
 		}
-		stream->w_buffer[dest++] = data[i];
 	}
-	cstream->last_cr = stream->w_buffer[dest-1] == '\r';
-	i_stream_skip(stream->parent, i);

-	ret = dest - stream->pos;
+	while (d_ptr < d_end) {
+		ptr = memchr(s_ptr, '\n', s_end - s_ptr);
+		if (ptr == NULL)
+			ptr = s_end;
+
+		cpy_len = ptr - s_ptr;
+		if (d_ptr + cpy_len > d_end)
+			cpy_len = d_end - d_ptr;
+
+		if (cpy_len > 0) {
+			memcpy(d_ptr, s_ptr, cpy_len);
+
+			d_ptr += cpy_len;
+			s_ptr += cpy_len;
+		}
+
+		i_assert(d_ptr <= d_end && s_ptr <= s_end);
+		if (d_ptr == d_end || s_ptr == s_end)
+			break;
+
+		if (*(s_ptr - 1) != '\r')
+			*(d_ptr++) = '\r';
+
+		if (d_ptr < d_end) {
+			*(d_ptr++) = '\n';
+			s_ptr++;
+		}
+
+		i_assert(s_ptr == ptr + 1);
+	}
+
+	cstream->last_cr = *(d_ptr - 1) == '\r';
+	i_stream_skip(stream->parent, s_ptr - data);
+
+	ret = (d_ptr - stream->w_buffer) - stream->pos;
 	i_assert(ret > 0);
-	stream->pos = dest;
+	stream->pos = d_ptr - stream->w_buffer;
 	return ret;
 }
