diff --git a/src/hpack-dec.c b/src/hpack-dec.c index dfbcaff27..7c3605b68 100644 --- a/src/hpack-dec.c +++ b/src/hpack-dec.c @@ -30,10 +30,12 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -41,8 +43,10 @@ #if defined(DEBUG_HPACK) #define hpack_debug_printf printf +#define hpack_debug_hexdump debug_hexdump #else #define hpack_debug_printf(...) do { } while (0) +#define hpack_debug_hexdump(...) do { } while (0) #endif /* reads a varint from 's lowest bits and bytes max (raw included). @@ -155,6 +159,8 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, int must_index; int ret; + hpack_debug_hexdump(stderr, "[HPACK-DEC] ", (const char *)raw, 0, len); + chunk_reset(tmp); ret = 0; while (len) { @@ -173,17 +179,22 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, idx = get_var_int(&raw, &len, 7); if (len == (uint32_t)-1) { // truncated + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TRUNCATED; goto leave; } + hpack_debug_printf(" idx=%u ", idx); + if (!hpack_valid_idx(dht, idx)) { + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TOO_LARGE; goto leave; } value = hpack_alloc_string(tmp, idx, hpack_idx_to_value(dht, idx)); if (!value.ptr) { + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TOO_LARGE; goto leave; } @@ -194,6 +205,7 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, if (!name.len) { name = hpack_alloc_string(tmp, idx, hpack_idx_to_name(dht, idx)); if (!name.ptr) { + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TOO_LARGE; goto leave; } @@ -202,17 +214,22 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, } else if (*raw >= 0x20 && *raw <= 0x3f) { /* max dyn table size change */ + hpack_debug_printf("%02x: p18: dynamic table size update : ", code); + if (ret) { /* 7541#4.2.1 : DHT size update must only be at the beginning */ + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TOO_LARGE; goto leave; } idx = get_var_int(&raw, &len, 5); if (len == (uint32_t)-1) { // truncated + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TRUNCATED; goto leave; } + hpack_debug_printf(" new len=%u\n", idx); continue; } else if (!(*raw & (*raw - 0x10))) { @@ -233,6 +250,7 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, /* retrieve name */ if (!len) { // truncated + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TRUNCATED; goto leave; } @@ -240,6 +258,8 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, huff = *raw & 0x80; nlen = get_var_int(&raw, &len, 7); if (len == (uint32_t)-1 || len < nlen) { // truncated + hpack_debug_printf("##ERR@%d## (truncated): nlen=%d len=%d\n", + __LINE__, (int)nlen, (int)len); ret = -HPACK_ERR_TRUNCATED; goto leave; } @@ -252,6 +272,7 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, if (huff) { char *ntrash = chunk_newstr(tmp); if (!ntrash) { + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TOO_LARGE; goto leave; } @@ -262,12 +283,15 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, ret = -HPACK_ERR_HUFFMAN; goto leave; } + hpack_debug_printf(" [name huff %d->%d] ", (int)name.len, (int)nlen); + tmp->len += nlen; // make room for the value name = ist2(ntrash, nlen); } /* retrieve value */ if (!len) { // truncated + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TRUNCATED; goto leave; } @@ -275,6 +299,8 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, huff = *raw & 0x80; vlen = get_var_int(&raw, &len, 7); if (len == (uint32_t)-1 || len < vlen) { // truncated + hpack_debug_printf("##ERR@%d## : vlen=%d len=%d\n", + __LINE__, (int)vlen, (int)len); ret = -HPACK_ERR_TRUNCATED; goto leave; } @@ -286,6 +312,7 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, if (huff) { char *vtrash = chunk_newstr(tmp); if (!vtrash) { + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TOO_LARGE; goto leave; } @@ -296,6 +323,8 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, ret = -HPACK_ERR_HUFFMAN; goto leave; } + hpack_debug_printf(" [value huff %d->%d] ", (int)value.len, (int)vlen); + tmp->len += vlen; // make room for the value value = ist2(vtrash, vlen); } @@ -322,12 +351,16 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, else idx = get_var_int(&raw, &len, 4); + hpack_debug_printf(" idx=%u ", idx); + if (len == (uint32_t)-1 || !len) { // truncated + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TRUNCATED; goto leave; } if (!hpack_valid_idx(dht, idx)) { + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TOO_LARGE; goto leave; } @@ -336,6 +369,7 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, huff = *raw & 0x80; vlen = get_var_int(&raw, &len, 7); if (len == (uint32_t)-1 || len < vlen) { // truncated + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TRUNCATED; goto leave; } @@ -347,13 +381,16 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, if (huff) { char *vtrash = chunk_newstr(tmp); if (!vtrash) { + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TOO_LARGE; goto leave; } vlen = huff_dec((const uint8_t *)value.ptr, value.len, vtrash, tmp->size - tmp->len); if (vlen == (uint32_t)-1) { - hpack_debug_printf("1: can't decode huffman.\n"); + hpack_debug_printf("##ERR@%d## can't decode huffman : ilen=%d osize=%d\n", + __LINE__, (int)value.len, (int)(tmp->size - tmp->len)); + hpack_debug_hexdump(stderr, "[HUFFMAN] ", value.ptr, 0, value.len); ret = -HPACK_ERR_HUFFMAN; goto leave; } @@ -368,6 +405,7 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, if (!name.len) { name = hpack_alloc_string(tmp, idx, hpack_idx_to_name(dht, idx)); if (!name.ptr) { + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TOO_LARGE; goto leave; } @@ -382,6 +420,7 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, * - name.ptr != NULL || must_index : general header, unknown pseudo-header or index needed */ if (ret >= list_size) { + hpack_debug_printf("##ERR@%d##\n", __LINE__); ret = -HPACK_ERR_TOO_LARGE; goto leave; } @@ -397,11 +436,11 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, } hpack_debug_printf("\e[1;34m%s\e[0m: ", - istpad(trash.str, name.ptr ? name : hpack_idx_to_name(dht, idx)).ptr); + name.ptr ? istpad(trash.str, name).ptr : h2_phdr_to_str(name.len)); - hpack_debug_printf("\e[1;35m%s\e[0m [idx=%d, used=%d]\n", - istpad(trash.str, value).ptr, - must_index, dht->used); + hpack_debug_printf("\e[1;35m%s\e[0m [mustidx=%d, used=%d] [n=(%p,%d) v=(%p,%d)]\n", + istpad(trash.str, value).ptr, must_index, dht->used, + name.ptr, (int)name.len, value.ptr, (int)value.len); } if (ret >= list_size) { @@ -414,5 +453,6 @@ int hpack_decode_frame(struct hpack_dht *dht, const uint8_t *raw, uint32_t len, ret++; leave: + hpack_debug_printf("-- done: ret=%d list_size=%d --\n", (int)ret, (int)list_size); return ret; }