1# -*- coding: utf-8 -*- 2""" 3test_invalid_content_lengths.py 4~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 6This module contains tests that use invalid content lengths, and validates that 7they fail appropriately. 8""" 9import pytest 10 11import h2.config 12import h2.connection 13import h2.errors 14import h2.events 15import h2.exceptions 16 17 18class TestInvalidContentLengths(object): 19 """ 20 Hyper-h2 raises Protocol Errors when the content-length sent by a remote 21 peer is not valid. 22 """ 23 example_request_headers = [ 24 (':authority', 'example.com'), 25 (':path', '/'), 26 (':scheme', 'https'), 27 (':method', 'POST'), 28 ('content-length', '15'), 29 ] 30 example_response_headers = [ 31 (':status', '200'), 32 ('server', 'fake-serv/0.1.0') 33 ] 34 server_config = h2.config.H2Configuration(client_side=False) 35 36 def test_too_much_data(self, frame_factory): 37 """ 38 Remote peers sending data in excess of content-length causes Protocol 39 Errors. 40 """ 41 c = h2.connection.H2Connection(config=self.server_config) 42 c.initiate_connection() 43 c.receive_data(frame_factory.preamble()) 44 45 headers = frame_factory.build_headers_frame( 46 headers=self.example_request_headers 47 ) 48 first_data = frame_factory.build_data_frame(data=b'\x01'*15) 49 c.receive_data(headers.serialize() + first_data.serialize()) 50 c.clear_outbound_data_buffer() 51 52 second_data = frame_factory.build_data_frame(data=b'\x01') 53 with pytest.raises(h2.exceptions.InvalidBodyLengthError) as exp: 54 c.receive_data(second_data.serialize()) 55 56 assert exp.value.expected_length == 15 57 assert exp.value.actual_length == 16 58 assert str(exp.value) == ( 59 "InvalidBodyLengthError: Expected 15 bytes, received 16" 60 ) 61 62 expected_frame = frame_factory.build_goaway_frame( 63 last_stream_id=1, 64 error_code=h2.errors.ErrorCodes.PROTOCOL_ERROR, 65 ) 66 assert c.data_to_send() == expected_frame.serialize() 67 68 def test_insufficient_data(self, frame_factory): 69 """ 70 Remote peers sending less data than content-length causes Protocol 71 Errors. 72 """ 73 c = h2.connection.H2Connection(config=self.server_config) 74 c.initiate_connection() 75 c.receive_data(frame_factory.preamble()) 76 77 headers = frame_factory.build_headers_frame( 78 headers=self.example_request_headers 79 ) 80 first_data = frame_factory.build_data_frame(data=b'\x01'*13) 81 c.receive_data(headers.serialize() + first_data.serialize()) 82 c.clear_outbound_data_buffer() 83 84 second_data = frame_factory.build_data_frame( 85 data=b'\x01', 86 flags=['END_STREAM'], 87 ) 88 with pytest.raises(h2.exceptions.InvalidBodyLengthError) as exp: 89 c.receive_data(second_data.serialize()) 90 91 assert exp.value.expected_length == 15 92 assert exp.value.actual_length == 14 93 assert str(exp.value) == ( 94 "InvalidBodyLengthError: Expected 15 bytes, received 14" 95 ) 96 97 expected_frame = frame_factory.build_goaway_frame( 98 last_stream_id=1, 99 error_code=h2.errors.ErrorCodes.PROTOCOL_ERROR, 100 ) 101 assert c.data_to_send() == expected_frame.serialize() 102 103 def test_insufficient_data_empty_frame(self, frame_factory): 104 """ 105 Remote peers sending less data than content-length where the last data 106 frame is empty causes Protocol Errors. 107 """ 108 c = h2.connection.H2Connection(config=self.server_config) 109 c.initiate_connection() 110 c.receive_data(frame_factory.preamble()) 111 112 headers = frame_factory.build_headers_frame( 113 headers=self.example_request_headers 114 ) 115 first_data = frame_factory.build_data_frame(data=b'\x01'*14) 116 c.receive_data(headers.serialize() + first_data.serialize()) 117 c.clear_outbound_data_buffer() 118 119 second_data = frame_factory.build_data_frame( 120 data=b'', 121 flags=['END_STREAM'], 122 ) 123 with pytest.raises(h2.exceptions.InvalidBodyLengthError) as exp: 124 c.receive_data(second_data.serialize()) 125 126 assert exp.value.expected_length == 15 127 assert exp.value.actual_length == 14 128 assert str(exp.value) == ( 129 "InvalidBodyLengthError: Expected 15 bytes, received 14" 130 ) 131 132 expected_frame = frame_factory.build_goaway_frame( 133 last_stream_id=1, 134 error_code=h2.errors.ErrorCodes.PROTOCOL_ERROR, 135 ) 136 assert c.data_to_send() == expected_frame.serialize() 137