MEDIUM: buffers: fix unsafe use of buffer_ignore at some places

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.
This commit is contained in:
Willy Tarreau 2012-03-09 15:03:30 +01:00
parent 8b1323e4cb
commit ec1bc82a1d
2 changed files with 13 additions and 14 deletions

View 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 */

View 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;