Commit 8a564bb5 authored by Dag Haavi Finstad's avatar Dag Haavi Finstad Committed by Dridi Boukelmoune

Fix a buffer overflow situation in h2_deliver

This still lacks error handling and thus is not a fix for #2589, but at
least we're not writing past the end of the workspace any more.
parent 28b48b3c
...@@ -160,34 +160,35 @@ h2_minimal_response(struct req *req, uint16_t status) ...@@ -160,34 +160,35 @@ h2_minimal_response(struct req *req, uint16_t status)
return (0); return (0);
} }
static uint8_t * static int
h2_enc_len(uint8_t *p, unsigned bits, unsigned val) h2_enc_len(struct vsb *vsb, unsigned bits, unsigned val, uint8_t b0)
{ {
assert(bits < 8); assert(bits < 8);
unsigned mask = (1U << bits) - 1U; unsigned mask = (1U << bits) - 1U;
if (val >= mask) { if (val >= mask) {
*p++ |= (uint8_t)mask; AZ(VSB_putc(vsb, b0 | (uint8_t)mask));
val -= mask; val -= mask;
while (val >= 128) { while (val >= 128) {
*p++ = 0x80 | ((uint8_t)val & 0x7f); AZ(VSB_putc(vsb, 0x80 | ((uint8_t)val & 0x7f)));
val >>= 7; val >>= 7;
} }
} }
*p++ = (uint8_t)val; AZ(VSB_putc(vsb, (uint8_t)val));
return (p); return (0);
} }
void v_matchproto_(vtr_deliver_f) void v_matchproto_(vtr_deliver_f)
h2_deliver(struct req *req, struct boc *boc, int sendbody) h2_deliver(struct req *req, struct boc *boc, int sendbody)
{ {
ssize_t sz, sz1; ssize_t sz, sz1;
uint8_t *p; unsigned u, l;
unsigned u; uint8_t buf[6];
const char *r; const char *r;
struct http *hp; struct http *hp;
struct sess *sp; struct sess *sp;
struct h2_req *r2; struct h2_req *r2;
struct vsb resp;
int i, err; int i, err;
const struct hpack_static *hps; const struct hpack_static *hps;
...@@ -198,15 +199,14 @@ h2_deliver(struct req *req, struct boc *boc, int sendbody) ...@@ -198,15 +199,14 @@ h2_deliver(struct req *req, struct boc *boc, int sendbody)
sp = req->sp; sp = req->sp;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
(void)WS_Reserve(req->ws, 0); l = WS_Reserve(req->ws, 0);
p = (void*)req->ws->f; AN(VSB_new(&resp, req->ws->f, l, VSB_FIXEDLEN));
p += h2_status(p, req->resp->status); l = h2_status(buf, req->resp->status);
AZ(VSB_bcat(&resp, buf, l));
hp = req->resp; hp = req->resp;
for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) { for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
assert(WS_Inside(req->ws, p, NULL));
r = strchr(hp->hd[u].b, ':'); r = strchr(hp->hd[u].b, ':');
AN(r); AN(r);
...@@ -227,27 +227,24 @@ h2_deliver(struct req *req, struct boc *boc, int sendbody) ...@@ -227,27 +227,24 @@ h2_deliver(struct req *req, struct boc *boc, int sendbody)
VSLb(req->vsl, SLT_Debug, VSLb(req->vsl, SLT_Debug,
"HP {%d, \"%s\", \"%s\"} <%s>", "HP {%d, \"%s\", \"%s\"} <%s>",
hps->idx, hps->name, hps->val, hp->hd[u].b); hps->idx, hps->name, hps->val, hp->hd[u].b);
*p = 0x10; AZ(h2_enc_len(&resp, 4, hps->idx, 0x10));
p = h2_enc_len(p, 4, hps->idx);
} else { } else {
AZ(VSB_putc(&resp, 0x10));
*p++ = 0x10;
sz--; sz--;
p = h2_enc_len(p, 7, sz); AZ(h2_enc_len(&resp, 7, sz, 0));
for (sz1 = 0; sz1 < sz; sz1++) for (sz1 = 0; sz1 < sz; sz1++)
*p++ = (uint8_t)tolower(hp->hd[u].b[sz1]); AZ(VSB_putc(&resp, tolower(hp->hd[u].b[sz1])));
} }
while (vct_islws(*++r)) while (vct_islws(*++r))
continue; continue;
sz = hp->hd[u].e - r; sz = hp->hd[u].e - r;
p = h2_enc_len(p, 7, sz); AZ(h2_enc_len(&resp, 7, sz, 0));
memcpy(p, r, sz); AZ(VSB_bcat(&resp, r, sz));
p += sz;
assert(WS_Inside(req->ws, p, NULL));
} }
sz = (char*)p - req->ws->f; VSB_finish(&resp);
sz = VSB_len(&resp);
AZ(req->wrk->v1l); AZ(req->wrk->v1l);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment