]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: buffers: fix unsafe use of buffer_ignore at some places
authorWilly Tarreau <w@1wt.eu>
Fri, 9 Mar 2012 14:03:30 +0000 (15:03 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2012 10:28:14 +0000 (12:28 +0200)
buffer_ignore may only be used when the output of a buffer is empty,
but it's not granted it is always the case when sending HTTP error
responses. Better use buffer_cut_tail() instead, and use buffer_ignore
only on non-wrapping data.

include/proto/buffers.h
src/proto_http.c

index a95e5a1f811387dec882a6e7fe4f529e45f4cac7..f35da6496a0165e5d62a8a11f4574e5cbfc7eb4e 100644 (file)
@@ -343,17 +343,16 @@ static inline void buffer_cut_tail(struct buffer *buf)
                buf->flags |= BF_FULL;
 }
 
-/* Cut the <n> next unsent bytes of the buffer. The caller must ensure that <n>
- * is smaller than the actual buffer's length. This is mainly used to remove
- * empty lines at the beginning of a request or a response.
+/* Cut the first <n> pending bytes in a contiguous buffer. It is illegal to
+ * call this function with remaining data waiting to be sent (o > 0). The
+ * caller must ensure that <n> is smaller than the actual buffer's length.
+ * This is mainly used to remove empty lines at the beginning of a request
+ * or a response.
  */
 static inline void buffer_ignore(struct buffer *buf, int n)
 {
        buf->i -= n;
-       buf->p = buffer_wrap_add(buf, buf->p + n);
-       buf->flags &= ~BF_FULL;
-       if (buffer_len(buf) >= buffer_max_len(buf))
-               buf->flags |= BF_FULL;
+       buf->p += n;
 }
 
 /* marks the buffer as "shutdown" ASAP for reads */
index f81e71e3d9ba6cd6fa248a192a05fc529de49f38..0dc2b51d62260dd5b22e27bdf4b7b199b028682c 100644 (file)
@@ -4067,7 +4067,7 @@ int http_sync_res_state(struct session *s)
        if (txn->rsp.msg_state == HTTP_MSG_CLOSED) {
        http_msg_closed:
                /* drop any pending data */
-               buffer_ignore(buf, buf->i);
+               buffer_cut_tail(buf);
                buffer_auto_close(buf);
                buffer_auto_read(buf);
                goto wait_other_side;
@@ -4133,7 +4133,7 @@ int http_resync_states(struct session *s)
                buffer_abort(s->req);
                buffer_auto_close(s->req);
                buffer_auto_read(s->req);
-               buffer_ignore(s->req, s->req->i);
+               buffer_cut_tail(s->req);
        }
        else if (txn->req.msg_state == HTTP_MSG_CLOSED &&
                 txn->rsp.msg_state == HTTP_MSG_DONE &&
@@ -4542,7 +4542,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit)
                        rep->analysers = 0;
                        txn->status = 502;
                        rep->prod->flags |= SI_FL_NOLINGER;
-                       buffer_ignore(rep, rep->i);
+                       buffer_cut_tail(rep);
                        stream_int_retnclose(rep->cons, error_message(s, HTTP_ERR_502));
 
                        if (!(s->flags & SN_ERR_MASK))
@@ -4575,7 +4575,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit)
                        rep->analysers = 0;
                        txn->status = 502;
                        rep->prod->flags |= SI_FL_NOLINGER;
-                       buffer_ignore(rep, rep->i);
+                       buffer_cut_tail(rep);
                        stream_int_retnclose(rep->cons, error_message(s, HTTP_ERR_502));
 
                        if (!(s->flags & SN_ERR_MASK))
@@ -4600,7 +4600,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit)
                        rep->analysers = 0;
                        txn->status = 504;
                        rep->prod->flags |= SI_FL_NOLINGER;
-                       buffer_ignore(rep, rep->i);
+                       buffer_cut_tail(rep);
                        stream_int_retnclose(rep->cons, error_message(s, HTTP_ERR_504));
 
                        if (!(s->flags & SN_ERR_MASK))
@@ -4625,7 +4625,7 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit)
                        rep->analysers = 0;
                        txn->status = 502;
                        rep->prod->flags |= SI_FL_NOLINGER;
-                       buffer_ignore(rep, rep->i);
+                       buffer_cut_tail(rep);
                        stream_int_retnclose(rep->cons, error_message(s, HTTP_ERR_502));
 
                        if (!(s->flags & SN_ERR_MASK))
@@ -4975,7 +4975,7 @@ int http_process_res_common(struct session *t, struct buffer *rep, int an_bit, s
                                        rep->analysers = 0;
                                        txn->status = 502;
                                        rep->prod->flags |= SI_FL_NOLINGER;
-                                       buffer_ignore(rep, rep->i);
+                                       buffer_cut_tail(rep);
                                        stream_int_retnclose(rep->cons, error_message(t, HTTP_ERR_502));
                                        if (!(t->flags & SN_ERR_MASK))
                                                t->flags |= SN_ERR_PRXCOND;