/src/wireshark/epan/tvbuff_hpackhuff.c
Line | Count | Source |
1 | | /* @file |
2 | | * Decompression of the Huffman encoding used for HTTP fields in HPACK (HTTP/2) |
3 | | * and QPACK (HTTP/3) |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | #include "config.h" |
13 | | |
14 | | #include <epan/tvbuff.h> |
15 | | #include <epan/nghttp2_hd_huffman.h> |
16 | | |
17 | | static wmem_strbuf_t * |
18 | | get_hpack_huffman_strbuf(wmem_allocator_t *scope, const uint8_t *ptr, size_t len) |
19 | 0 | { |
20 | 0 | wmem_strbuf_t *strbuf; |
21 | 0 | strbuf = wmem_strbuf_new_sized(scope, len + 1); |
22 | |
|
23 | 0 | nghttp2_huff_decode node = {0, 0}; |
24 | 0 | const nghttp2_huff_decode *nodep = &node; |
25 | |
|
26 | 0 | while (len > 0) { |
27 | 0 | uint8_t ch = *ptr++; |
28 | |
|
29 | 0 | nodep = &huff_decode_table[nodep->fstate & 0x1ff][ch >> 4]; |
30 | 0 | if (nodep->fstate & NGHTTP2_HUFF_SYM) { |
31 | 0 | wmem_strbuf_append_c(strbuf, nodep->sym); |
32 | 0 | } |
33 | |
|
34 | 0 | nodep = &huff_decode_table[nodep->fstate & 0x1ff][ch & 0xf]; |
35 | 0 | if (nodep->fstate & NGHTTP2_HUFF_SYM) { |
36 | 0 | wmem_strbuf_append_c(strbuf, nodep->sym); |
37 | 0 | } |
38 | |
|
39 | 0 | len--; |
40 | 0 | } |
41 | |
|
42 | 0 | if (!(nodep->fstate & NGHTTP2_HUFF_ACCEPTED)) { |
43 | 0 | wmem_strbuf_destroy(strbuf); |
44 | 0 | return NULL; |
45 | 0 | } |
46 | | |
47 | 0 | return strbuf; |
48 | 0 | } |
49 | | |
50 | | wmem_strbuf_t * |
51 | | tvb_get_hpack_huffman_strbuf(wmem_allocator_t *scope, tvbuff_t *tvb, const unsigned offset, const unsigned len) |
52 | 0 | { |
53 | 0 | return get_hpack_huffman_strbuf(scope, tvb_get_ptr(tvb, offset, len), len); |
54 | 0 | } |
55 | | |
56 | | tvbuff_t* |
57 | | tvb_child_uncompress_hpack_huff(tvbuff_t* parent, unsigned offset, unsigned length) |
58 | 0 | { |
59 | 0 | tvbuff_t* tvb = NULL; |
60 | 0 | wmem_strbuf_t *strbuf; |
61 | 0 | char* data; |
62 | 0 | size_t len; |
63 | |
|
64 | 0 | strbuf = tvb_get_hpack_huffman_strbuf(NULL, parent, offset, length); |
65 | |
|
66 | 0 | if (strbuf) { |
67 | 0 | len = wmem_strbuf_get_len(strbuf); |
68 | 0 | data = wmem_strbuf_finalize(strbuf); |
69 | |
|
70 | 0 | tvb = tvb_new_child_real_data(parent, (const uint8_t*)data, (unsigned)len, (unsigned)len); |
71 | |
|
72 | 0 | tvb_set_free_cb(tvb, g_free); |
73 | 0 | } |
74 | |
|
75 | 0 | return tvb; |
76 | 0 | } |