/pidgin/main: 451ed08be0b9: Fix purple_xfer_write() during do_tr...

Jakub Adam jakub.adam at ktknet.cz
Mon Apr 18 22:54:56 EDT 2016


Changeset: 451ed08be0b9003154d1e0dd0e5305d17757efb8
Author:	 Jakub Adam <jakub.adam at ktknet.cz>
Date:	 2016-04-07 15:07 +0200
Branch:	 default
URL: https://hg.pidgin.im/pidgin/main/rev/451ed08be0b9

Description:

Fix purple_xfer_write() during do_transfer()

Consider sending a small (say 10 bytes) file in do_transfer().

First, the buffer is filled in purple_xfer_read_file(), which also calls
purple_xfer_set_bytes_sent(); because the file is small, bytes sent now
equals the file size. Later in purple_xfer_write(), the size of
the write buffer is adjusted so that it's not bigger than the remaining
portion of the file being sent - but at that point
purple_xfer_get_bytes_remaining() already returns 0, nothing is written
and the file transfer gets stuck.

As I understant it, the meaning of buffer size adjustment in
purple_xfer_write() is to ensure that external protocol plugin which
handles file transfer input and output on its own can't by accident send
more data than the size of the file. In do_transfer(), though, that
check is redundant and can be skipped.

diffstat:

 libpurple/xfer.c |  41 ++++++++++++++++++++++++++---------------
 1 files changed, 26 insertions(+), 15 deletions(-)

diffs (65 lines):

diff --git a/libpurple/xfer.c b/libpurple/xfer.c
--- a/libpurple/xfer.c
+++ b/libpurple/xfer.c
@@ -1205,27 +1205,38 @@ purple_xfer_read(PurpleXfer *xfer, gucha
 	return r;
 }
 
+static gssize
+do_write(PurpleXfer *xfer, const guchar *buffer, gsize size)
+{
+	PurpleXferPrivate *priv = PURPLE_XFER_GET_PRIVATE(xfer);
+	gssize r;
+
+	g_return_val_if_fail(priv   != NULL, 0);
+	g_return_val_if_fail(buffer != NULL, 0);
+	g_return_val_if_fail(size   != 0,    0);
+
+	if (priv->ops.write != NULL) {
+		r = (priv->ops.write)(buffer, size, xfer);
+	} else {
+		r = write(priv->fd, buffer, size);
+		if (r < 0 && errno == EAGAIN)
+			r = 0;
+	}
+
+	return r;
+}
+
 gssize
 purple_xfer_write(PurpleXfer *xfer, const guchar *buffer, gsize size)
 {
 	PurpleXferPrivate *priv = PURPLE_XFER_GET_PRIVATE(xfer);
-	gssize r, s;
-
-	g_return_val_if_fail(priv   != NULL, 0);
-	g_return_val_if_fail(buffer != NULL, 0);
-	g_return_val_if_fail(size   != 0,    0);
+	gssize s;
+
+	g_return_val_if_fail(priv != NULL, 0);
 
 	s = MIN((gssize)purple_xfer_get_bytes_remaining(xfer), (gssize)size);
 
-	if (priv->ops.write != NULL) {
-		r = (priv->ops.write)(buffer, s, xfer);
-	} else {
-		r = write(priv->fd, buffer, s);
-		if (r < 0 && errno == EAGAIN)
-			r = 0;
-	}
-
-	return r;
+	return do_write(xfer, buffer, s);
 }
 
 gboolean
@@ -1405,7 +1416,7 @@ do_transfer(PurpleXfer *xfer)
 			result = priv->buffer->len;
 		}
 
-		r = purple_xfer_write(xfer, buffer, result);
+		r = do_write(xfer, buffer, result);
 
 		if (r == -1) {
 			purple_xfer_cancel_remote(xfer);



More information about the Commits mailing list