1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

lws_spa: avoid reading past table

Didn't check the lenghts of the NUL-terminated header
table properly.

https://github.com/warmcat/libwebsockets/issues/1859
This commit is contained in:
Andy Green 2020-03-14 07:04:14 +00:00
parent 65a3d40d74
commit 8adcdbb189
2 changed files with 51 additions and 21 deletions

View file

@ -538,11 +538,13 @@ lws_create_context(const struct lws_context_creation_info *info)
else
context->max_http_header_pool = context->max_fds;
if (info->fd_limit_per_thread)
context->fd_limit_per_thread = lpf;
else
context->fd_limit_per_thread = context->max_fds /
context->count_threads;
if (context->count_threads)
context->fd_limit_per_thread = context->max_fds /
context->count_threads;
#if defined(LWS_WITH_NETWORK)

View file

@ -42,10 +42,13 @@ enum urldecode_stateful {
MT_COMPLETED,
};
static const char * const mp_hdr[] = {
"content-disposition: ",
"content-type: ",
"\x0d\x0a"
static struct mp_hdr {
const char * const hdr;
uint8_t hdr_len;
} mp_hdrs[] = {
{ "content-disposition: ", 21 },
{ "content-type: ", 14 },
{ "\x0d\x0a", 2 }
};
struct lws_spa;
@ -69,10 +72,12 @@ struct lws_urldecode_stateful {
int mp;
int sum;
unsigned int multipart_form_data:1;
unsigned int inside_quote:1;
unsigned int subname:1;
unsigned int boundary_real_crlf:1;
uint8_t matchable;
uint8_t multipart_form_data:1;
uint8_t inside_quote:1;
uint8_t subname:1;
uint8_t boundary_real_crlf:1;
enum urldecode_stateful state;
@ -150,7 +155,7 @@ static int
lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in,
int len)
{
int n, m, hit = 0;
int n, hit;
char c;
while (len--) {
@ -281,29 +286,52 @@ retry_as_first:
break;
case MT_HNAME:
m = 0;
c =*in;
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
for (n = 0; n < (int)LWS_ARRAY_SIZE(mp_hdr); n++)
if (c == mp_hdr[n][s->mp]) {
m++;
hit = n;
if (!s->mp)
/* initially, any of them might match */
s->matchable = (1 << LWS_ARRAY_SIZE(mp_hdrs)) - 1;
hit = -1;
for (n = 0; n < (int)LWS_ARRAY_SIZE(mp_hdrs); n++) {
if (!(s->matchable & (1 << n)))
continue;
/* this guy is still in contention... */
if (s->mp >= mp_hdrs[n].hdr_len) {
/* he went past the end of it */
s->matchable &= ~(1 << n);
continue;
}
if (c != mp_hdrs[n].hdr[s->mp]) {
/* mismatched a char */
s->matchable &= ~(1 << n);
continue;
}
if (s->mp + 1 == mp_hdrs[n].hdr_len) {
/* we have a winner... */
hit = n;
break;
}
}
in++;
if (!m) {
/* Unknown header - ignore it */
if (hit == -1 && !s->matchable) {
/* We ruled them all out */
s->state = MT_IGNORE1;
s->mp = 0;
continue;
}
s->mp++;
if (m != 1)
if (hit < 0)
continue;
if (mp_hdr[hit][s->mp])
continue;
/* we matched the one in hit */
s->mp = 0;
s->temp[0] = '\0';