HPACK: do not allow header block to end with table size update

This commit is contained in:
Dmitri Tikhonov 2018-04-27 14:36:21 -04:00
parent 130d542a00
commit bf6b47adbf
5 changed files with 57 additions and 43 deletions

View file

@ -1,3 +1,7 @@
2018-04-27
- HPACK: do not allow header block to end with table size update.
2018-04-25 2018-04-25
- [BUGFIX] Do not create gap in sent packnos when squeezing delayed - [BUGFIX] Do not create gap in sent packnos when squeezing delayed

View file

@ -938,19 +938,15 @@ decode_and_pass_payload (struct lsquic_frame_reader *fr)
s = lsquic_hdec_decode(fr->fr_hdec, &comp, end, s = lsquic_hdec_decode(fr->fr_hdec, &comp, end,
hwc.buf, hwc.buf + 16 * 1024, hwc.buf, hwc.buf + 16 * 1024,
&hwc.name_len, &hwc.val_len); &hwc.name_len, &hwc.val_len);
if (s > 0) if (s == 0)
{ {
err = add_header_to_uh(fr, &hwc); err = add_header_to_uh(fr, &hwc);
if (0 != err) if (err == 0)
goto stream_error; continue;
}
else if (s < 0)
{
err = FR_ERR_DECOMPRESS;
goto stream_error;
} }
else else
break; err = FR_ERR_DECOMPRESS;
goto stream_error;
} }
assert(comp == end); assert(comp == end);

View file

@ -290,7 +290,7 @@ lsquic_hdec_decode (struct lsquic_hdec *dec,
int indexed_type, len; int indexed_type, len;
if ((*src) == src_end) if ((*src) == src_end)
return 0; return -1;
while ((*(*src) & 0xe0) == 0x20) //001 xxxxx while ((*(*src) & 0xe0) == 0x20) //001 xxxxx
{ {
@ -300,7 +300,7 @@ lsquic_hdec_decode (struct lsquic_hdec *dec,
return -1; return -1;
hdec_update_max_capacity(dec, new_capacity); hdec_update_max_capacity(dec, new_capacity);
if (*src == src_end) if (*src == src_end)
return 0; return -1;
} }
/* lsquic_hdec_dec_int() sets `index' and advances `src'. If we do not call /* lsquic_hdec_dec_int() sets `index' and advances `src'. If we do not call
@ -373,7 +373,7 @@ lsquic_hdec_decode (struct lsquic_hdec *dec,
return -1; return -1;
*val_len = lsquic_hpack_stx_tab[index - 1].val_len; *val_len = lsquic_hpack_stx_tab[index - 1].val_len;
memcpy(name + *name_len, lsquic_hpack_stx_tab[index - 1].val, *val_len); memcpy(name + *name_len, lsquic_hpack_stx_tab[index - 1].val, *val_len);
return 1; return 0;
} }
} }
else else
@ -392,7 +392,7 @@ lsquic_hdec_decode (struct lsquic_hdec *dec,
return -1; return -1;
*val_len = entry->dte_val_len; *val_len = entry->dte_val_len;
memcpy(name + *name_len, DTE_VALUE(entry), *val_len); memcpy(name + *name_len, DTE_VALUE(entry), *val_len);
return 1; return 0;
} }
} }
} }
@ -421,7 +421,7 @@ lsquic_hdec_decode (struct lsquic_hdec *dec,
return -1; //error return -1; //error
} }
return 1; return 0;
} }

View file

@ -22,16 +22,11 @@ lsquic_hdec_init (struct lsquic_hdec *);
void void
lsquic_hdec_cleanup (struct lsquic_hdec *); lsquic_hdec_cleanup (struct lsquic_hdec *);
/** @lsquic_hdecode /*
* @brief HPACK decode one name/value item * Returns 0 on success, a negative value on failure.
* @param[in,out] dec - A pointer to a valid HPACK API struct *
* @param[in,out] src - Address of pointer to source buffer * If 0 is returned, `src' is advanced. Calling with a zero-length input
* @param[in] src_end - A pointer to end of source buffer * buffer results in an error.
* @param[out] dst - A pointer to destination buffer
* @param[out] dst_end - A pointer to end of destination buffer
* @param[out] name_len - The item name's length
* @param[out] value_len - The item value's length
* @return 1: OK, 0: end, -1: FAIL
*/ */
int int
lsquic_hdec_decode (struct lsquic_hdec *dec, lsquic_hdec_decode (struct lsquic_hdec *dec,

View file

@ -344,9 +344,11 @@ test_hpack_test_RFC_Example (void)
char out[2048]; char out[2048];
uint16_t name_len = 1024; uint16_t name_len = 1024;
uint16_t val_len = 1024; uint16_t val_len = 1024;
while ((rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len, while (pSrc < bufEnd)
&val_len)) > 0)
{ {
rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out),
&name_len, &val_len);
assert(rc == 0);
char *name = out; char *name = out;
char *val = name + name_len; char *val = name + name_len;
printf("%.*s: %.*s\n", name_len, name, val_len, val); printf("%.*s: %.*s\n", name_len, name, val_len, val);
@ -358,9 +360,11 @@ test_hpack_test_RFC_Example (void)
"\x82\x86\x84\xbe\x58\x86\xa8\xeb\x10\x64\x9c\xbf"; "\x82\x86\x84\xbe\x58\x86\xa8\xeb\x10\x64\x9c\xbf";
pSrc = bufSamp; pSrc = bufSamp;
bufEnd = bufSamp + strlen((const char *)bufSamp); bufEnd = bufSamp + strlen((const char *)bufSamp);
while ((rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len, while (pSrc < bufEnd)
&val_len)) > 0)
{ {
rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out),
&name_len, &val_len);
assert(rc == 0);
char *name = out; char *name = out;
char *val = name + name_len; char *val = name + name_len;
printf("%.*s: %.*s\n", name_len, name, val_len, val); printf("%.*s: %.*s\n", name_len, name, val_len, val);
@ -370,9 +374,11 @@ test_hpack_test_RFC_Example (void)
"\x82\x87\x85\xbf\x40\x88\x25\xa8\x49\xe9\x5b\xa9\x7d\x7f\x89\x25\xa8\x49\xe9\x5b\xb8\xe8\xb4\xbf"; "\x82\x87\x85\xbf\x40\x88\x25\xa8\x49\xe9\x5b\xa9\x7d\x7f\x89\x25\xa8\x49\xe9\x5b\xb8\xe8\xb4\xbf";
pSrc = bufSamp; pSrc = bufSamp;
bufEnd = bufSamp + strlen((const char *)bufSamp); bufEnd = bufSamp + strlen((const char *)bufSamp);
while ((rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len, while (pSrc < bufEnd)
&val_len)) > 0)
{ {
rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out),
&name_len, &val_len);
assert(rc == 0);
char *name = out; char *name = out;
char *val = name + name_len; char *val = name + name_len;
printf("%.*s: %.*s\n", name_len, name, val_len, val); printf("%.*s: %.*s\n", name_len, name, val_len, val);
@ -420,7 +426,7 @@ test_decode_limits (void)
src = comp; src = comp;
s = lsquic_hdec_decode(&hdec, &src, end, out, out + enough[n], s = lsquic_hdec_decode(&hdec, &src, end, out, out + enough[n],
&name_len, &val_len); &name_len, &val_len);
assert(1 == s); assert(0 == s);
assert(src == end); assert(src == end);
assert(16 == name_len); assert(16 == name_len);
assert(17 == val_len); assert(17 == val_len);
@ -481,7 +487,7 @@ test_hpack_self_enc_dec_test (void)
pSrc = respBuf; pSrc = respBuf;
bufEnd = pBuf; bufEnd = pBuf;
while ((rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len, while ((rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len,
&val_len)) > 0) &val_len)) == 0)
{ {
char *name = out; char *name = out;
char *val = name + name_len; char *val = name + name_len;
@ -515,7 +521,7 @@ test_hpack_self_enc_dec_test (void)
pSrc = respBuf; pSrc = respBuf;
bufEnd = pBuf; bufEnd = pBuf;
while ((rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len, while ((rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len,
&val_len)) > 0) &val_len)) == 0)
{ {
char *name = out; char *name = out;
char *val = name + name_len; char *val = name + name_len;
@ -561,7 +567,7 @@ test_hpack_self_enc_dec_test (void)
pSrc = respBuf; pSrc = respBuf;
bufEnd = pBuf; bufEnd = pBuf;
while ((rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len, while ((rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len,
&val_len)) > 0) &val_len)) == 0)
{ {
char *name = out; char *name = out;
char *val = name + name_len; char *val = name + name_len;
@ -602,7 +608,7 @@ test_hpack_self_enc_dec_test (void)
pSrc = respBuf; pSrc = respBuf;
bufEnd = pBuf; bufEnd = pBuf;
while ((rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len, while ((rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len,
&val_len)) > 0) &val_len)) == 0)
{ {
char *name = out; char *name = out;
char *val = name + name_len; char *val = name + name_len;
@ -640,7 +646,7 @@ test_hpack_encode_and_decode (void)
uint16_t name_len, val_len; uint16_t name_len, val_len;
int rc = lsquic_hdec_decode(&hdec, &dec, enc, out, out + sizeof(out), &name_len, int rc = lsquic_hdec_decode(&hdec, &dec, enc, out, out + sizeof(out), &name_len,
&val_len); &val_len);
assert(rc > 0); assert(rc == 0);
assert(name_len == 10); assert(name_len == 10);
assert(val_len == 15); assert(val_len == 15);
assert(dec == enc); assert(dec == enc);
@ -715,7 +721,7 @@ test_hpack_self_enc_dec_test_firefox_error (void)
while (pSrc < bufEnd) while (pSrc < bufEnd)
{ {
rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len, &val_len); rc = lsquic_hdec_decode(&hdec, &pSrc, bufEnd, out, out + sizeof(out), &name_len, &val_len);
assert(rc > 0); assert(rc == 0);
char *name = out; char *name = out;
char *val = name + name_len; char *val = name + name_len;
@ -748,7 +754,7 @@ test_hdec_table_size_updates (void)
* error. * error.
*/ */
{ {
unsigned const char buf[] = { 0x20 | 0x1E }; unsigned const char buf[] = { 0x20 | 0x1E, 0x88 };
src = buf; src = buf;
lsquic_hdec_init(&hdec); lsquic_hdec_init(&hdec);
lsquic_hdec_set_max_capacity(&hdec, 0x11); lsquic_hdec_set_max_capacity(&hdec, 0x11);
@ -762,7 +768,7 @@ test_hdec_table_size_updates (void)
/* Test 2: inline update of capacity smaller than max succeeds. /* Test 2: inline update of capacity smaller than max succeeds.
*/ */
{ {
unsigned const char buf[] = { 0x20 | 0x1E }; unsigned const char buf[] = { 0x20 | 0x1E, 0x88 };
src = buf; src = buf;
lsquic_hdec_init(&hdec); lsquic_hdec_init(&hdec);
s = lsquic_hdec_decode(&hdec, &src, src + sizeof(buf), outbuf, s = lsquic_hdec_decode(&hdec, &src, src + sizeof(buf), outbuf,
@ -784,6 +790,7 @@ test_hdec_table_size_updates (void)
unsigned const char buf[] = { unsigned const char buf[] = {
0x20 | 0x00, 0x20 | 0x00,
0x20 | 0x14, 0x20 | 0x14,
0x88,
}; };
src = buf; src = buf;
lsquic_hdec_init(&hdec); lsquic_hdec_init(&hdec);
@ -795,6 +802,18 @@ test_hdec_table_size_updates (void)
lsquic_hdec_cleanup(&hdec); lsquic_hdec_cleanup(&hdec);
} }
/* Test 4: header block with table update at the end fails.
*/
{
unsigned const char buf[] = { 0x20 | 0x1E, };
src = buf;
lsquic_hdec_init(&hdec);
s = lsquic_hdec_decode(&hdec, &src, src + sizeof(buf), outbuf,
outbuf + sizeof(outbuf), &name_len, &val_len);
assert(s < 0);
lsquic_hdec_cleanup(&hdec);
}
} }
@ -886,7 +905,7 @@ test_henc_nonascii (void)
src = comp; src = comp;
s = lsquic_hdec_decode(&hdec, &src, end, uncomp, uncomp + sizeof(uncomp), s = lsquic_hdec_decode(&hdec, &src, end, uncomp, uncomp + sizeof(uncomp),
&name_len, &val_len); &name_len, &val_len);
assert(s == 1); assert(s == 0);
assert(sizeof(value) == val_len); assert(sizeof(value) == val_len);
assert(0 == memcmp(value, uncomp + name_len, val_len)); assert(0 == memcmp(value, uncomp + name_len, val_len));
lsquic_hdec_cleanup(&hdec); lsquic_hdec_cleanup(&hdec);
@ -927,7 +946,7 @@ test_henc_long_compressable (void)
src = comp; src = comp;
s = lsquic_hdec_decode(&hdec, &src, end, uncomp, uncomp + sizeof(uncomp), s = lsquic_hdec_decode(&hdec, &src, end, uncomp, uncomp + sizeof(uncomp),
&name_len, &val_len); &name_len, &val_len);
assert(s == 1); assert(s == 0);
assert(sizeof(value) == val_len); assert(sizeof(value) == val_len);
assert(0 == memcmp(value, uncomp + name_len, val_len)); assert(0 == memcmp(value, uncomp + name_len, val_len));
lsquic_hdec_cleanup(&hdec); lsquic_hdec_cleanup(&hdec);
@ -975,7 +994,7 @@ test_henc_long_uncompressable (void)
src = comp; src = comp;
s = lsquic_hdec_decode(&hdec, &src, end, uncomp, uncomp + sizeof(uncomp), s = lsquic_hdec_decode(&hdec, &src, end, uncomp, uncomp + sizeof(uncomp),
&name_len, &val_len); &name_len, &val_len);
assert(s == 1); assert(s == 0);
assert(sizeof(value) == val_len); assert(sizeof(value) == val_len);
assert(0 == memcmp(value, uncomp + name_len, val_len)); assert(0 == memcmp(value, uncomp + name_len, val_len));
lsquic_hdec_cleanup(&hdec); lsquic_hdec_cleanup(&hdec);
@ -1210,7 +1229,7 @@ main (int argc, char **argv)
for (i = 0; comp < end; ++i) for (i = 0; comp < end; ++i)
{ {
s = lsquic_hdec_decode(&hdec, &comp, end, out, out + sizeof(out), &name_len, &val_len); s = lsquic_hdec_decode(&hdec, &comp, end, out, out + sizeof(out), &name_len, &val_len);
assert(s > 0); assert(s == 0);
assert(name_len == header_arr[i].name.iov_len); assert(name_len == header_arr[i].name.iov_len);
assert(0 == memcmp(header_arr[i].name.iov_base, out, name_len)); assert(0 == memcmp(header_arr[i].name.iov_base, out, name_len));
assert(val_len == header_arr[i].value.iov_len); assert(val_len == header_arr[i].value.iov_len);