[tpop3d-discuss] [PATCH] Corrupted TOP response with PIPELINING and tpop3d 1.5.3

Martin Blapp mb at imp.ch
Wed, 2 Feb 2005 18:09:22 +0100 (CET)


Hi Chris,

>um. The only places buffer_push_bytes is called,
>buffer_expand has been called immediately before it. I
>*think* -- I haven't had time to look in detail today --
>that the problem is in buffer_get_push_ptr -- it can cause
>too much data to be read in the case where the read
>pointer is still at the beginning of the buffer.

buffer_expand does not expand at all if readpos and writepos
are 0. You overwrite then the same buffer over and again without
reading anything.

Uhm, I forgot something. The previous patch was DOS'able. A upper
limit of 4MB should be enough to satisfy anyone. Of course one
could argue that we should output an error then and abort everything.

Martin

--- buffer.c.orig       Thu Nov  6 02:19:27 2003
+++ buffer.c    Wed Feb  2 18:01:41 2005
@@ -220,4 +220,20 @@
  * a location returned by buffer_get_push_ptr. */
 void buffer_push_bytes(buffer B, const size_t num) {
     B->put = (B->put + num) % B->len;
+    /* check if we reached the readpos and expand buffer if necessary*/
+    if(B->len*2 <= MAXEXPANDBUF && num && (B->put == B->get)) {
+       char* newbuf;
+       newbuf = xmalloc(B->len*2);
+       if(B->put)
+               bcopy(B->buf+B->put, newbuf, B->len - B->put);
+       if(B->put)
+               bcopy(B->buf, newbuf+B->put, B->put);
+       else
+               bcopy(B->buf, newbuf+B->put, B->len);
+       B->get = 0;
+       B->put = B->len;
+       B->len = B->len*2;
+               xfree(B->buf);
+       B->buf = newbuf;
+    }
 }
--- buffer.h.orig       Wed Feb  2 18:00:03 2005
+++ buffer.h    Wed Feb  2 18:00:06 2005
@@ -22,6 +22,7 @@
  * Return the number of bytes of data available to consume from BUFFER. This
  * is a macro which may evaluate BUFFER more than once. */
 #define buffer_available(B) ((size_t)(((B)->put + (B)->len - (B)->get) %
(B)->len))
+#define MAXEXPANDBUF 4194304

 /* buffer.c */
 buffer buffer_new(const size_t len);