aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-11-12 23:31:57 +0100
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-11-12 23:31:57 +0100
commitb71a6174e12b4709acaf8bc151938ba12d2a54f6 (patch)
treedc8fbe48681f318c272513b7a8d68982fdc47973
parent7d02b225fe11fb0c7233cd2ea576485ee920f203 (diff)
http.c: Fix more issues with partial boundaries
- http_memmem must not check strlen(a) > n because, in case of a partial boundary, it would wrongfully return NULL. - If one or more characters from a partial boundary are found at the end of a buffer, but the next buffer does not start with the rest of the boundary, the accumulated boundary must be reset, and then look for a new boundary.
-rw-r--r--http.c55
1 files changed, 36 insertions, 19 deletions
diff --git a/http.c b/http.c
index 7440944..48a5ab0 100644
--- a/http.c
+++ b/http.c
@@ -1491,25 +1491,30 @@ static int read_mf_body_to_file(struct http_ctx *const h, const void *const buf,
return 0;
}
-static int reset_boundary(struct http_ctx *const h, const void *const buf,
- const size_t n)
+static int reset_boundary(struct http_ctx *const h)
{
struct multiform *const m = &h->ctx.u.mf;
struct form *const f = &m->forms[m->nforms - 1];
int (*const read_mf)(struct http_ctx *, const void *, size_t) =
f->filename ? read_mf_body_to_file : read_mf_body_to_mem;
+ const size_t len = strlen(m->boundary);
+ const int res = read_mf(h, m->boundary, len);
- if (n)
- {
- const size_t len = strlen(m->boundary);
- const int res = read_mf(h, m->boundary, len);
+ if (res)
+ return res;
- if (res)
- return res;
+ memset(m->boundary, '\0', len);
+ m->blen = 0;
+ return 0;
+}
- memset(m->boundary, '\0', len);
- m->blen = 0;
- }
+static int dump_body(struct http_ctx *const h, const void *const buf,
+ const size_t n)
+{
+ struct multiform *const m = &h->ctx.u.mf;
+ struct form *const f = &m->forms[m->nforms - 1];
+ int (*const read_mf)(struct http_ctx *, const void *, size_t) =
+ f->filename ? read_mf_body_to_file : read_mf_body_to_mem;
return read_mf(h, buf, n);
}
@@ -1624,6 +1629,12 @@ static int read_mf_body_boundary_byte(struct http_ctx *const h, const char b,
return ret;
}
}
+ else
+ {
+ fprintf(stderr, "%s: expected %hhx, got %hhx\n", __func__,
+ c->boundary[m->blen], b);
+ return 1;
+ }
return 0;
}
@@ -1632,11 +1643,6 @@ static int read_mf_body_boundary_byte(struct http_ctx *const h, const char b,
static const char *http_memmem(const char *const a, const void *const b,
const size_t n)
{
- const size_t len = strlen(a);
-
- if (len > n)
- return NULL;
-
const char *s = a, *st = NULL;
for (size_t i = 0; i < n; i++)
@@ -1669,14 +1675,23 @@ static const char *http_memmem(const char *const a, const void *const b,
static int read_mf_body_boundary(struct http_ctx *const h,
const char **const buf, size_t *const n)
{
+ const char *orig_buf = *buf;
+ const size_t orig_n = *n;
struct ctx *const c = &h->ctx;
struct multiform *const m = &c->u.mf;
- const char *const boundary = http_memmem(&c->boundary[m->blen], *buf, *n);
int res;
+ if (m->blen
+ && **buf != c->boundary[m->blen]
+ && (res = reset_boundary(h)))
+ return res;
+
+ const char *const boundary = http_memmem(&c->boundary[m->blen], *buf, *n);
+
if (!boundary)
{
- if ((res = reset_boundary(h, *buf, *n)))
+ if ((res = reset_boundary(h))
+ || (res = dump_body(h, *buf, *n)))
return res;
*n = 0;
@@ -1685,7 +1700,9 @@ static int read_mf_body_boundary(struct http_ctx *const h,
const size_t prev = boundary - *buf;
- if ((res = reset_boundary(h, *buf, prev)))
+ if (prev && (res = reset_boundary(h)))
+ return res;
+ else if ((res = dump_body(h, *buf, prev)))
return res;
*buf += prev;