1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-16 00:00:07 +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 5eaab80708
commit 9cac58a4c2
2 changed files with 52 additions and 21 deletions

View file

@ -341,11 +341,13 @@ lwsl_info("context created\n");
else
context->max_http_header_pool = context->max_fds;
if (info->fd_limit_per_thread)
context->fd_limit_per_thread = info->fd_limit_per_thread;
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

@ -39,10 +39,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;
@ -66,10 +69,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;
@ -147,7 +152,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, was_end = 0;
while (len--) {
@ -159,6 +164,7 @@ lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in,
was_end = s->pos;
s->pos = 0;
}
switch (s->state) {
/* states for url arg style */
@ -278,29 +284,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';