Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a ZeroLengthHeaderError raised if header name is 0-length #169

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Release History

**API Changes (Backward Compatible)**

- Added a new ``ZeroLengthHeaderNameError`` that indicates that an
invalid header has been received. This places the HPACK decoder into
a broken state: it must not be used after this exception is thrown.

**Bugfixes**

- Performance improvement of static header search. Use dict search instead
Expand Down
5 changes: 3 additions & 2 deletions hpack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
from .hpack import Encoder, Decoder
from .struct import HeaderTuple, NeverIndexedHeaderTuple
from .exceptions import (
HPACKError, HPACKDecodingError, InvalidTableIndex, OversizedHeaderListError
HPACKError, HPACKDecodingError, InvalidTableIndex,
OversizedHeaderListError, ZeroLengthHeaderNameError,
)

__all__ = [
'Encoder', 'Decoder', 'HPACKError', 'HPACKDecodingError',
'InvalidTableIndex', 'HeaderTuple', 'NeverIndexedHeaderTuple',
'OversizedHeaderListError'
'OversizedHeaderListError', 'ZeroLengthHeaderNameError',
]

__version__ = '3.1.0dev0'
9 changes: 9 additions & 0 deletions hpack/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,12 @@ class InvalidTableSizeError(HPACKDecodingError):
.. versionadded:: 3.0.0
"""
pass


class ZeroLengthHeaderNameError(HPACKDecodingError):
"""
An invalid header with a zero length name has been received.

.. versionadded:: 3.1.0
"""
pass
11 changes: 10 additions & 1 deletion hpack/hpack.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
from .table import HeaderTable, table_entry_size
from .compat import to_byte, to_bytes
from .exceptions import (
HPACKDecodingError, OversizedHeaderListError, InvalidTableSizeError
HPACKDecodingError, OversizedHeaderListError, InvalidTableSizeError,
ZeroLengthHeaderNameError,
)
from .huffman import HuffmanEncoder
from .huffman_constants import (
Expand Down Expand Up @@ -496,6 +497,7 @@ def decode(self, data, raw=False):

if header:
headers.append(header)
self._assert_valid_header_name_size(header)
inflated_size += table_entry_size(*header)

if inflated_size > self.max_header_list_size:
Expand All @@ -516,6 +518,13 @@ def decode(self, data, raw=False):
except UnicodeDecodeError:
raise HPACKDecodingError("Unable to decode headers as UTF-8.")

def _assert_valid_header_name_size(self, header):
"""
Check that the header name size is valid, i.e. non-zero.
"""
if len(header[0]) == 0:
raise ZeroLengthHeaderNameError()

def _assert_valid_table_size(self):
"""
Check that the table size set by the encoder is lower than the maximum
Expand Down
12 changes: 11 additions & 1 deletion test/test_hpack.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from hpack.hpack import Encoder, Decoder, _dict_to_iterable, _to_bytes
from hpack.exceptions import (
HPACKDecodingError, InvalidTableIndex, OversizedHeaderListError,
InvalidTableSizeError
InvalidTableSizeError, ZeroLengthHeaderNameError,
)
from hpack.struct import HeaderTuple, NeverIndexedHeaderTuple
import itertools
Expand Down Expand Up @@ -638,6 +638,16 @@ def test_max_header_list_size(self):
with pytest.raises(OversizedHeaderListError):
d.decode(data)

def test_zero_length_header(self):
"""
If a header has a name of zero length it is invalid and the HPACK
decoder raises a ZeroLengthHeaderNameError.
"""
d = Decoder(max_header_list_size=44)
data = b"@\x80\x80"
with pytest.raises(ZeroLengthHeaderNameError):
d.decode(data)

def test_can_decode_multiple_header_table_size_changes(self):
"""
If multiple header table size changes are sent in at once, they are
Expand Down