| # -*- coding: utf-8 -*- |
| """ |
| test_invalid_content_lengths.py |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| This module contains tests that use invalid content lengths, and validates that |
| they fail appropriately. |
| """ |
| import pytest |
| |
| import h2.config |
| import h2.connection |
| import h2.errors |
| import h2.events |
| import h2.exceptions |
| |
| |
| class TestInvalidContentLengths(object): |
| """ |
| Hyper-h2 raises Protocol Errors when the content-length sent by a remote |
| peer is not valid. |
| """ |
| example_request_headers = [ |
| (':authority', 'example.com'), |
| (':path', '/'), |
| (':scheme', 'https'), |
| (':method', 'POST'), |
| ('content-length', '15'), |
| ] |
| example_response_headers = [ |
| (':status', '200'), |
| ('server', 'fake-serv/0.1.0') |
| ] |
| server_config = h2.config.H2Configuration(client_side=False) |
| |
| def test_too_much_data(self, frame_factory): |
| """ |
| Remote peers sending data in excess of content-length causes Protocol |
| Errors. |
| """ |
| c = h2.connection.H2Connection(config=self.server_config) |
| c.initiate_connection() |
| c.receive_data(frame_factory.preamble()) |
| |
| headers = frame_factory.build_headers_frame( |
| headers=self.example_request_headers |
| ) |
| first_data = frame_factory.build_data_frame(data=b'\x01'*15) |
| c.receive_data(headers.serialize() + first_data.serialize()) |
| c.clear_outbound_data_buffer() |
| |
| second_data = frame_factory.build_data_frame(data=b'\x01') |
| with pytest.raises(h2.exceptions.InvalidBodyLengthError) as exp: |
| c.receive_data(second_data.serialize()) |
| |
| assert exp.value.expected_length == 15 |
| assert exp.value.actual_length == 16 |
| assert str(exp.value) == ( |
| "InvalidBodyLengthError: Expected 15 bytes, received 16" |
| ) |
| |
| expected_frame = frame_factory.build_goaway_frame( |
| last_stream_id=1, |
| error_code=h2.errors.ErrorCodes.PROTOCOL_ERROR, |
| ) |
| assert c.data_to_send() == expected_frame.serialize() |
| |
| def test_insufficient_data(self, frame_factory): |
| """ |
| Remote peers sending less data than content-length causes Protocol |
| Errors. |
| """ |
| c = h2.connection.H2Connection(config=self.server_config) |
| c.initiate_connection() |
| c.receive_data(frame_factory.preamble()) |
| |
| headers = frame_factory.build_headers_frame( |
| headers=self.example_request_headers |
| ) |
| first_data = frame_factory.build_data_frame(data=b'\x01'*13) |
| c.receive_data(headers.serialize() + first_data.serialize()) |
| c.clear_outbound_data_buffer() |
| |
| second_data = frame_factory.build_data_frame( |
| data=b'\x01', |
| flags=['END_STREAM'], |
| ) |
| with pytest.raises(h2.exceptions.InvalidBodyLengthError) as exp: |
| c.receive_data(second_data.serialize()) |
| |
| assert exp.value.expected_length == 15 |
| assert exp.value.actual_length == 14 |
| assert str(exp.value) == ( |
| "InvalidBodyLengthError: Expected 15 bytes, received 14" |
| ) |
| |
| expected_frame = frame_factory.build_goaway_frame( |
| last_stream_id=1, |
| error_code=h2.errors.ErrorCodes.PROTOCOL_ERROR, |
| ) |
| assert c.data_to_send() == expected_frame.serialize() |
| |
| def test_insufficient_data_empty_frame(self, frame_factory): |
| """ |
| Remote peers sending less data than content-length where the last data |
| frame is empty causes Protocol Errors. |
| """ |
| c = h2.connection.H2Connection(config=self.server_config) |
| c.initiate_connection() |
| c.receive_data(frame_factory.preamble()) |
| |
| headers = frame_factory.build_headers_frame( |
| headers=self.example_request_headers |
| ) |
| first_data = frame_factory.build_data_frame(data=b'\x01'*14) |
| c.receive_data(headers.serialize() + first_data.serialize()) |
| c.clear_outbound_data_buffer() |
| |
| second_data = frame_factory.build_data_frame( |
| data=b'', |
| flags=['END_STREAM'], |
| ) |
| with pytest.raises(h2.exceptions.InvalidBodyLengthError) as exp: |
| c.receive_data(second_data.serialize()) |
| |
| assert exp.value.expected_length == 15 |
| assert exp.value.actual_length == 14 |
| assert str(exp.value) == ( |
| "InvalidBodyLengthError: Expected 15 bytes, received 14" |
| ) |
| |
| expected_frame = frame_factory.build_goaway_frame( |
| last_stream_id=1, |
| error_code=h2.errors.ErrorCodes.PROTOCOL_ERROR, |
| ) |
| assert c.data_to_send() == expected_frame.serialize() |