Hi all,

attached is a patch which fixes accessing MBox files > 2 GByte.  See [1] for a 
description of the symptoms.  The patch should be usable for both the Gtk-2 and 
Gtk-3 branches.

The bug is caused by blindly mixing various integer types with different sizes in the 
Balsa code, in particular int/gint, off_t, ssize_t/size_t and gint64, when using 
g_mime_stream_* functions.  On a POSIX system, run 'getconf -a | grep 
"_POSIX_V7_.*1$"' to see which definition from [2] applies.

In any case, on POSIX int/gint is *always* 32 bits, which explains the bug.  
Otoh, off_t /should/ always be 64 bits if glibc is used(at least if 
_FILE_OFFSET_BITS is defined as 64), so it /may/ be mixed with gint64 (which is 
*guaranteed* to be 64 bits in any case).  Both size_t and ssize_t will 
typically be 32 bits on a 32 bit system, and 64 on a 64 bit system.

On other systems, results may be completely different, as ISO9899 does not 
define sizes.

I guess there are more "fishy" data type mixtures than the few I found to fix 
the particular bug.  Maybe time to run a good static analyser like FlexeLint against the 
Balsa code to find these issues (which would be a huge task, though)...

Opinions?

Best,
Albrecht.


[1] <https://mail.gnome.org/archives/balsa-list/2016-May/msg00003.html>
[2] <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html>
diff --git a/libbalsa/mailbox_mbox.c b/libbalsa/mailbox_mbox.c
index b59b98d..fc946e0 100644
--- a/libbalsa/mailbox_mbox.c
+++ b/libbalsa/mailbox_mbox.c
@@ -112,7 +112,7 @@ struct _LibBalsaMailboxMbox {
 
     GPtrArray *msgno_2_msg_info;
     GMimeStream *gmime_stream;
-    gint size;
+    off_t size;
     gboolean messages_info_changed;
 };
 
@@ -919,10 +919,10 @@ lbm_mbox_check_file(LibBalsaMailboxMbox * mbox,
 
         if (content_length) {
             /* Seek past the content. */
-            ssize_t remaining;
+            off_t remaining;
 
             buffer->start += content_length;
-            remaining = buffer->end - buffer->start;
+            remaining = (off_t) buffer->end - (off_t) buffer->start;
             if (remaining < 0) {
                 g_mime_stream_seek(buffer->stream, -remaining,
                                    GMIME_STREAM_SEEK_CUR);
@@ -1165,15 +1165,19 @@ static gint
 lbm_mbox_newline(GMimeStream * stream)
 {
     gint retval;
-    gchar buf[1];
-    static gchar newlines[] = "\n\n";
+    static const gchar newlines[] = "\n\n";
 
-    retval = g_mime_stream_seek(stream, -1, GMIME_STREAM_SEEK_CUR);
-    if (retval >= 0)
-	retval = g_mime_stream_read(stream, buf, 1);
-    if (retval == 1)
-	retval =
-	    g_mime_stream_write(stream, newlines, buf[0] == '\n' ? 1 : 2);
+    if (g_mime_stream_seek(stream, -1, GMIME_STREAM_SEEK_CUR) < 0) {
+    	retval = -1;
+    } else {
+        gchar buf;
+
+    	retval = g_mime_stream_read(stream, &buf, 1);
+    	if (retval == 1) {
+    		retval =
+    			g_mime_stream_write(stream, newlines, buf == '\n' ? 1 : 2);
+    	}
+    }
 
     return retval;
 }
@@ -1949,7 +1953,7 @@ lbm_mbox_add_message(LibBalsaMailboxLocal * local,
     GMimeObject *armored_object;
     GMimeStream *armored_dest;
     GMimeStream *dest;
-    gint retval;
+    off_t retval;
     off_t orig_length;
 
     message = libbalsa_message_new();
diff --git a/libbalsa/send.c b/libbalsa/send.c
index 2122035..e4e47eb 100644
--- a/libbalsa/send.c
+++ b/libbalsa/send.c
@@ -593,6 +593,8 @@ libbalsa_message_cb (void **buf, int *len, void *arg)
 	return NULL;
     }
 
+    /* note: the following calculation works *only* for messages < 2 GB
+     * due to the limited range of int, but this should be safe... */
     *len = g_mime_stream_length(current_message->stream)
 	    - g_mime_stream_tell(current_message->stream);
     ptr = (char *) mem_stream->buffer->data

Attachment: pgp1bJ5xTpmjQ.pgp
Description: PGP signature

_______________________________________________
balsa-list mailing list
[email protected]
https://mail.gnome.org/mailman/listinfo/balsa-list

Reply via email to