From: Christopher Faulet Date: Thu, 25 Jun 2020 14:04:50 +0000 (+0200) Subject: BUG/MEDIUM: http-ana: Don't loop trying to generate a malformed 500 response X-Git-Tag: v2.2-dev11~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=40e6b550ce35ff164f71799d8378c4e2350d3640;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: http-ana: Don't loop trying to generate a malformed 500 response When HAProxy generates a 500 response, if the formatting failed, for instance because the message is larger than a buffer, it retries to format it in loop. To fix the bug, we must stop trying to send a response if it is a non-rewritable response (TX_CONST_REPLY flag is set on the HTTP transaction). Because this part is not trivial, some comments have been added. No backport is needed. --- diff --git a/src/http_ana.c b/src/http_ana.c index bd63343262..7c362933ec 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -4548,7 +4548,8 @@ static void http_end_response(struct stream *s) * function forwards all pending incoming data. If is set to 0, nothing * more is performed. It is used for 1xx informational messages. Otherwise, the * transaction is terminated and the request is emptied. On success 1 is - * returned. If an error occurred, 0 is returned. + * returned. If an error occurred, 0 is returned. If it fails, this function + * only exits. It is the caller responsibility to do the cleanup. */ int http_forward_proxy_resp(struct stream *s, int final) { @@ -4600,10 +4601,14 @@ void http_reply_and_close(struct stream *s, short status, struct http_reply *msg if (http_reply_message(s, msg) == -1) { /* On error, return a 500 error message, but don't rewrite it if - * it is already an internal error. + * it is already an internal error. If it was already a "const" + * 500 error, just fail. */ - if (s->txn->status == 500) + if (s->txn->status == 500) { + if (s->txn->flags & TX_CONST_REPLY) + goto end; s->txn->flags |= TX_CONST_REPLY; + } s->txn->status = 500; s->txn->http_reply = NULL; return http_reply_and_close(s, s->txn->status, http_error_message(s)); @@ -4636,9 +4641,10 @@ struct http_reply *http_error_message(struct stream *s) return &http_err_replies[msgnum]; } -/* Produces an HTX message from an http reply. Depending on the http reply type, a, - * errorfile, an raw file or a log-format string is used. On success, it returns - * 0. If an error occurs -1 is returned. +/* Produces an HTX message from an http reply. Depending on the http reply type, + * a, errorfile, an raw file or a log-format string is used. On success, it + * returns 0. If an error occurs -1 is returned. If it fails, this function only + * exits. It is the caller responsibility to do the cleanup. */ int http_reply_to_htx(struct stream *s, struct htx *htx, struct http_reply *reply) { @@ -4750,7 +4756,11 @@ int http_reply_to_htx(struct stream *s, struct htx *htx, struct http_reply *repl } /* Send an http reply to the client. On success, it returns 0. If an error - * occurs -1 is returned. + * occurs -1 is returned and the response channel is truncated, removing this + * way the faulty reply. This function may fail when the reply is formatted + * (http_reply_to_htx) or when the reply is forwarded + * (http_forward_proxy_resp). On the last case, it is because a + * http-after-response rule fails. */ int http_reply_message(struct stream *s, struct http_reply *reply) {