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
7 changes: 5 additions & 2 deletions lib/http/2/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -690,11 +690,14 @@ def connection_settings(frame)
# Setting header table size might cause some headers evicted
case side
when :local
@compressor.table_size = v
@decompressor.table_size_limit = v
when :remote
@decompressor.table_size = v
@compressor.table_size = v
end

when :settings_max_header_list_size
@decompressor.max_header_list_size = v if side == :local

when :settings_enable_push
# nothing to do

Expand Down
16 changes: 15 additions & 1 deletion lib/http/2/header/decompressor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,16 @@ class Decompressor
include BufferUtils

FORBIDDEN_HEADERS = %w[connection te].freeze
DEFAULT_MAX_HEADER_LIST_SIZE = (2 << 30) - 1
attr_writer :max_header_list_size

# @param options [Hash] decoding options. Only :table_size is effective.
# @param options [Hash] decoding options.
def initialize(options = {})
@cc = EncodingContext.new(options)
@max_header_list_size = options.fetch(
:settings_max_header_list_size,
DEFAULT_MAX_HEADER_LIST_SIZE

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you need this default and to enforce it, considering that the value is always set in the connection defaults? which case would require this?

)
end

# Set dynamic table size in EncodingContext
Expand All @@ -26,6 +32,10 @@ def table_size=(size)
@cc.table_size = size
end

def table_size_limit=(size)
@cc.table_size_limit = size
end

# Decodes integer value from provided buffer.
#
# @param buf [String]
Expand Down Expand Up @@ -116,6 +126,7 @@ def header(buf)
# @return [Array] +[[name, value], ...]
def decode(buf, frame = nil)
list = []
header_list_size = 0
decoding_pseudo_headers = true
@cc.listen_on_table do
until buf.empty?
Expand All @@ -130,6 +141,9 @@ def decode(buf, frame = nil)
decoding_pseudo_headers = is_pseudo_header
raise ProtocolError, "invalid header received: #{field}" if FORBIDDEN_HEADERS.include?(field)

header_list_size += field.bytesize + value.bytesize + 32
raise ProtocolError, "header list exceeds configured maximum" if header_list_size > @max_header_list_size

if frame
case field
when ":status"
Expand Down
13 changes: 8 additions & 5 deletions lib/http/2/header/encoding_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,9 @@ def process(cmd)
when :changetablesize
raise CompressionError, "tried to change table size after adding elements to table" if @_table_updated

# we can receive multiple table size change commands inside a header frame. However,
# we should blow up if we receive another frame where the new table size is bigger.
table_size_updated = @limit != @options[:table_size]

raise CompressionError, "dynamic table size update exceed limit" if !table_size_updated && value > @limit
# Multiple updates may begin a header block, but none may exceed
# the most recently advertised maximum.
raise CompressionError, "dynamic table size update exceeds limit" if value > @options[:table_size]

self.table_size = value

Expand Down Expand Up @@ -313,6 +311,11 @@ def table_size=(size)
resize_table(0)
end

def table_size_limit=(size)
@options[:table_size] = size
self.table_size = size if @limit > size
end

def listen_on_table
yield
ensure
Expand Down
4 changes: 4 additions & 0 deletions sig/header/decompressor.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ module HTTP2
include BufferUtils

FORBIDDEN_HEADERS: Array[String]
DEFAULT_MAX_HEADER_LIST_SIZE: Integer

@cc: EncodingContext
@max_header_list_size: Integer

def table_size=: (Integer) -> void
def table_size_limit=: (Integer) -> void
def max_header_list_size=: (Integer) -> void

def integer: (String, Integer) -> Integer

Expand Down
1 change: 1 addition & 0 deletions sig/header/encoding_context.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ module HTTP2
def addcmd: (String name, String value) -> header_command

def table_size=: (Integer) -> void
def table_size_limit=: (Integer) -> void

def listen_on_table: { () -> void } -> void

Expand Down
Loading