Skip to content
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
5 changes: 4 additions & 1 deletion src/h2/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def _reject_empty_header_names(headers: Iterable[Header],
"""
for header in headers:
if len(header[0]) == 0:
msg = "Received header name with zero length."
msg = "Header name with zero length present."
raise ProtocolError(msg)
yield header

Expand Down Expand Up @@ -690,6 +690,9 @@ def validate_outbound_headers(headers: Iterable[Header],
:param headers: The HTTP header set.
:param hdr_validation_flags: An instance of HeaderValidationFlags.
"""
headers = _reject_empty_header_names(
headers, hdr_validation_flags,
)
headers = _reject_te(
headers, hdr_validation_flags,
)
Expand Down
33 changes: 32 additions & 1 deletion tests/test_invalid_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,37 @@ def test_inbound_header_name_length(self, hdr_validation_flags) -> None:
with pytest.raises(h2.exceptions.ProtocolError):
list(h2.utilities.validate_headers([(b"", b"foobar")], hdr_validation_flags))

@pytest.mark.parametrize("hdr_validation_flags", hdr_validation_combos)
def test_outbound_header_name_length(self, hdr_validation_flags) -> None:
# An empty outbound header name must raise ProtocolError, not IndexError
# from the `header[0][0]` lookup in _reject_pseudo_header_fields.
with pytest.raises(h2.exceptions.ProtocolError):
list(h2.utilities.validate_outbound_headers([(b"", b"foobar")], hdr_validation_flags))

def test_outbound_header_name_length_send_headers(self, frame_factory) -> None:
c = h2.connection.H2Connection()
c.initiate_connection()
c.clear_outbound_data_buffer()

headers = [
(b":authority", b"example.com"),
(b":path", b"/"),
(b":scheme", b"https"),
(b":method", b"GET"),
(b"", b"foobar"),
]
with pytest.raises(h2.exceptions.ProtocolError, match=r"Header name with zero length present\."):
c.send_headers(1, headers)

@pytest.mark.parametrize("hdr_validation_flags", [
flags for flags in hdr_validation_combos
if flags.is_trailer and not flags.is_response_header
])
def test_valid_header_name_accepted_both_directions(self, hdr_validation_flags) -> None:
headers = [(b"x-custom-header", b"foobar")]
assert list(h2.utilities.validate_headers(list(headers), hdr_validation_flags))
assert list(h2.utilities.validate_outbound_headers(list(headers), hdr_validation_flags))

def test_inbound_header_name_length_full_frame_decode(self, frame_factory) -> None:
f = frame_factory.build_headers_frame([])
f.data = b"\x00\x00\x01\x04"
Expand All @@ -682,7 +713,7 @@ def test_inbound_header_name_length_full_frame_decode(self, frame_factory) -> No
c.receive_data(frame_factory.preamble())
c.clear_outbound_data_buffer()

with pytest.raises(h2.exceptions.ProtocolError, match="Received header name with zero length."):
with pytest.raises(h2.exceptions.ProtocolError, match=r"Header name with zero length present\."):
c.receive_data(data)


Expand Down