BUG: http: do not print garbage on invalid requests in debug mode

Cyril Bont reported a mangled debug output when an invalid request
was sent with a faulty request line. The reason was the use of the
msg->sl.rq.l offset which was not yet initialized in this case. So
we change the way to report such an error so that first we initialize
it to zero before parsing a message, then we use that to know whether
we can trust it or not. If it's still zero, then we display the whole
buffer, truncated by debug_hdr() to the first CR or LF character, which
results in the first line only.

The same operation was performed for the response, which was wrong too.
This commit is contained in:
Willy Tarreau 2012-09-24 21:13:39 +02:00
parent 3aaba440a2
commit e92693af26

View File

@ -1319,6 +1319,7 @@ void http_msg_analyzer(struct http_msg *msg, struct hdr_idx *idx)
bi_fast_delete(&buf->buf, ptr - buf->buf.p);
}
msg->sol = 0;
msg->sl.st.l = 0; /* used in debug mode */
hdr_idx_init(idx);
state = HTTP_MSG_RPVER;
goto http_msg_rpver;
@ -1384,9 +1385,7 @@ void http_msg_analyzer(struct http_msg *msg, struct hdr_idx *idx)
bi_fast_delete(&buf->buf, ptr - buf->buf.p);
}
msg->sol = 0;
/* we will need this when keep-alive will be supported
hdr_idx_init(idx);
*/
msg->sl.rq.l = 0; /* used in debug mode */
state = HTTP_MSG_RQMETH;
goto http_msg_rqmeth;
}
@ -2068,7 +2067,11 @@ int http_wait_for_request(struct session *s, struct channel *req, int an_bit)
char *eol, *sol;
sol = req->buf.p;
eol = sol + msg->sl.rq.l;
/* this is a bit complex : in case of error on the request line,
* we know that rq.l is still zero, so we display only the part
* up to the end of the line (truncated by debug_hdr).
*/
eol = sol + (msg->sl.rq.l ? msg->sl.rq.l : req->buf.i);
debug_hdr("clireq", s, sol, eol);
sol += hdr_idx_first_pos(&txn->hdr_idx);
@ -4598,7 +4601,7 @@ int http_wait_for_response(struct session *s, struct channel *rep, int an_bit)
char *eol, *sol;
sol = rep->buf.p;
eol = sol + msg->sl.st.l;
eol = sol + (msg->sl.st.l ? msg->sl.st.l : rep->buf.i);
debug_hdr("srvrep", s, sol, eol);
sol += hdr_idx_first_pos(&txn->hdr_idx);
@ -7421,15 +7424,21 @@ unsigned int http_get_hdr(const struct http_msg *msg, const char *hname, int hle
}
/*
* Print a debug line with a header
* Print a debug line with a header. Always stop at the first CR or LF char,
* so it is safe to pass it a full buffer if needed. If <err> is not NULL, an
* arrow is printed after the line which contains the pointer.
*/
void debug_hdr(const char *dir, struct session *t, const char *start, const char *end)
{
int len, max;
len = sprintf(trash, "%08x:%s.%s[%04x:%04x]: ", t->uniq_id, t->be->id,
dir, (unsigned short)si_fd(t->req->prod), (unsigned short)si_fd(t->req->cons));
max = end - start;
UBOUND(max, trashlen - len - 1);
for (max = 0; start + max < end; max++)
if (start[max] == '\r' || start[max] == '\n')
break;
UBOUND(max, trashlen - len - 3);
len += strlcpy2(trash + len, start, max + 1);
trash[len++] = '\n';
if (write(1, trash, len) < 0) /* shut gcc warning */;