]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] report error on buffer writes larger than buffer size
authorWilly Tarreau <w@1wt.eu>
Tue, 18 Aug 2009 05:19:39 +0000 (07:19 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 18 Aug 2009 05:19:39 +0000 (07:19 +0200)
Since it's now possible to change the buffer size by configuration,
we have to take special measures against writes that are larger than
the buffer size. Before this patch, the writers would indefinitely
block, waiting for some space to free up.

With this patch, the functions simply reject the data with an
appropriate code so that the writers can either detect and process
the error or go on, but never remain blocked.

This has been tested on the stats page which does no longer hang
with buffer sizes smaller than 2.5 kB (256 bytes is even OK for
the CSV version).

src/buffers.c

index a20f3f499b814c65076e1b6d1a779c62e68b95e6..ed2aa1e525cb103daf78352815bd632c3161b59d 100644 (file)
@@ -31,9 +31,9 @@ int init_buffer()
 
 
 /* writes <len> bytes from message <msg> to buffer <buf>. Returns -1 in case of
- * success, or the number of bytes available otherwise. The send limit is
- * automatically adjusted with the amount of data written.
- * FIXME-20060521: handle unaligned data.
+ * success, -2 if the message is larger than the buffer size, or the number of
+ * bytes available otherwise. The send limit is automatically adjusted with the
+ * amount of data written. FIXME-20060521: handle unaligned data.
  */
 int buffer_write(struct buffer *buf, const char *msg, int len)
 {
@@ -41,6 +41,15 @@ int buffer_write(struct buffer *buf, const char *msg, int len)
 
        max = buffer_realign(buf);
 
+       if (len > buf->size) {
+               /* we can't write this chunk and will never be able to, because
+                * it is larger than the buffer. This must be reported as an
+                * error. Then we return -2 so that writers that don't care can
+                * ignore it and go on, and others can check for this value.
+                */
+               return -2;
+       }
+
        if (len > max)
                return max;
 
@@ -61,10 +70,11 @@ int buffer_write(struct buffer *buf, const char *msg, int len)
        return -1;
 }
 
-/* writes the chunk <chunk> to buffer <buf>. Returns -1 in case of
- * success, or the number of bytes available otherwise. If the chunk
- * has been written, its size is automatically reset to zero. The send limit is
- * automatically adjusted with the amount of data written.
+/* writes the chunk <chunk> to buffer <buf>. Returns -1 in case of success,
+ * -2 if it is larger than the buffer size, or the number of bytes available
+ * otherwise. If the chunk has been written, its size is automatically reset
+ * to zero. The send limit is automatically adjusted with the amount of data
+ * written.
  */
 int buffer_write_chunk(struct buffer *buf, struct chunk *chunk)
 {
@@ -73,6 +83,15 @@ int buffer_write_chunk(struct buffer *buf, struct chunk *chunk)
        if (chunk->len == 0)
                return -1;
 
+       if (chunk->len > buf->size) {
+               /* we can't write this chunk and will never be able to, because
+                * it is larger than the buffer. This must be reported as an
+                * error. Then we return -2 so that writers that don't care can
+                * ignore it and go on, and others can check for this value.
+                */
+               return -2;
+       }
+
        max = buffer_realign(buf);
 
        if (chunk->len > max)