Merge pull request #2509 from cesanta/te

Fix #2460 - sanity check of the Transfer-Encoding: chunked header
This commit is contained in:
Sergey Lyubka 2023-12-01 13:48:35 +00:00 committed by GitHub
commit dbc7b5e70b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 14 deletions

View File

@ -2809,12 +2809,6 @@ static int skip_chunk(const char *buf, int len, int *pl, int *dl) {
return i + 2 + n + 2; return i + 2 + n + 2;
} }
static bool is_chunked(struct mg_http_message *hm) {
const char *needle = "chunked";
struct mg_str *te = mg_http_get_header(hm, "Transfer-Encoding");
return te != NULL && mg_vcasecmp(te, needle) == 0;
}
static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) { static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
if (ev == MG_EV_READ || ev == MG_EV_CLOSE) { if (ev == MG_EV_READ || ev == MG_EV_CLOSE) {
struct mg_http_message hm; struct mg_http_message hm;
@ -2823,6 +2817,8 @@ static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
while (c->is_resp == 0 && ofs < c->recv.len) { while (c->is_resp == 0 && ofs < c->recv.len) {
const char *buf = (char *) c->recv.buf + ofs; const char *buf = (char *) c->recv.buf + ofs;
int n = mg_http_parse(buf, c->recv.len - ofs, &hm); int n = mg_http_parse(buf, c->recv.len - ofs, &hm);
struct mg_str *te; // Transfer - encoding header
bool is_chunked = false;
if (n < 0) { if (n < 0) {
mg_error(c, "HTTP parse"); mg_error(c, "HTTP parse");
return; return;
@ -2832,8 +2828,16 @@ static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
hm.message.len = c->recv.len - ofs; // and closes now, deliver MSG hm.message.len = c->recv.len - ofs; // and closes now, deliver MSG
hm.body.len = hm.message.len - (size_t) (hm.body.ptr - hm.message.ptr); hm.body.len = hm.message.len - (size_t) (hm.body.ptr - hm.message.ptr);
} }
if ((te = mg_http_get_header(&hm, "Transfer-Encoding")) != NULL) {
if (mg_vcasecmp(te, "chunked") == 0) {
is_chunked = true;
} else {
mg_error(c, "Invalid Transfer-Encoding"); // See #2460
return;
}
}
if (is_chunked(&hm)) { if (is_chunked) {
// For chunked data, strip off prefixes and suffixes from chunks // For chunked data, strip off prefixes and suffixes from chunks
// and relocate them right after the headers, then report a message // and relocate them right after the headers, then report a message
char *s = (char *) c->recv.buf + ofs + n; char *s = (char *) c->recv.buf + ofs + n;

View File

@ -972,12 +972,6 @@ static int skip_chunk(const char *buf, int len, int *pl, int *dl) {
return i + 2 + n + 2; return i + 2 + n + 2;
} }
static bool is_chunked(struct mg_http_message *hm) {
const char *needle = "chunked";
struct mg_str *te = mg_http_get_header(hm, "Transfer-Encoding");
return te != NULL && mg_vcasecmp(te, needle) == 0;
}
static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) { static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
if (ev == MG_EV_READ || ev == MG_EV_CLOSE) { if (ev == MG_EV_READ || ev == MG_EV_CLOSE) {
struct mg_http_message hm; struct mg_http_message hm;
@ -986,6 +980,8 @@ static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
while (c->is_resp == 0 && ofs < c->recv.len) { while (c->is_resp == 0 && ofs < c->recv.len) {
const char *buf = (char *) c->recv.buf + ofs; const char *buf = (char *) c->recv.buf + ofs;
int n = mg_http_parse(buf, c->recv.len - ofs, &hm); int n = mg_http_parse(buf, c->recv.len - ofs, &hm);
struct mg_str *te; // Transfer - encoding header
bool is_chunked = false;
if (n < 0) { if (n < 0) {
mg_error(c, "HTTP parse"); mg_error(c, "HTTP parse");
return; return;
@ -995,8 +991,16 @@ static void http_cb(struct mg_connection *c, int ev, void *evd, void *fnd) {
hm.message.len = c->recv.len - ofs; // and closes now, deliver MSG hm.message.len = c->recv.len - ofs; // and closes now, deliver MSG
hm.body.len = hm.message.len - (size_t) (hm.body.ptr - hm.message.ptr); hm.body.len = hm.message.len - (size_t) (hm.body.ptr - hm.message.ptr);
} }
if ((te = mg_http_get_header(&hm, "Transfer-Encoding")) != NULL) {
if (mg_vcasecmp(te, "chunked") == 0) {
is_chunked = true;
} else {
mg_error(c, "Invalid Transfer-Encoding"); // See #2460
return;
}
}
if (is_chunked(&hm)) { if (is_chunked) {
// For chunked data, strip off prefixes and suffixes from chunks // For chunked data, strip off prefixes and suffixes from chunks
// and relocate them right after the headers, then report a message // and relocate them right after the headers, then report a message
char *s = (char *) c->recv.buf + ofs + n; char *s = (char *) c->recv.buf + ofs + n;