Skip to content
Closed
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 @@ -670,11 +670,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
10 changes: 10 additions & 0 deletions lib/http/2/header/decompressor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,22 @@ class Decompressor
include BufferUtils

FORBIDDEN_HEADERS = %w[connection te].freeze
attr_writer :max_header_list_size

def initialize(settings = Settings.new)
@cc = EncodingContext.new(settings)
@max_header_list_size = settings.settings_max_header_list_size
end

# Set dynamic table +size+ in EncodingContext
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+.
def integer(buf, n)
limit = (1 << n) - 1
Expand Down Expand Up @@ -97,6 +103,7 @@ def header(buf)
# Decodes and processes header commands within provided +buf+.
def decode(buf, frame = nil)
list = [] #: Array[header_pair]
header_list_size = 0
decoding_pseudo_headers = true
@cc.listen_on_table do
until buf.empty?
Expand All @@ -111,6 +118,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
16 changes: 11 additions & 5 deletions lib/http/2/header/encoding_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def initialize(settings = Settings.new)
@unshifts = 0
@settings = settings
@limit = settings.table_size
@table_size_limit = settings.table_size
@_table_updated = false
@current_table_size = 0
end
Expand All @@ -118,11 +119,13 @@ def dup
tbf = @table_by_field.transform_values(&:dup)
unshifts = @unshifts
l = @limit
table_size_limit = @table_size_limit
other.instance_eval do
@table = t.dup # shallow copy
@table_by_field = tbf
@unshifts = unshifts
@limit = l
@table_size_limit = table_size_limit
end
other
end
Expand Down Expand Up @@ -156,11 +159,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 != @settings.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 > @table_size_limit

self.table_size = value

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

def table_size_limit=(size)
@table_size_limit = size
self.table_size = size if @limit > size
end

def listen_on_table
yield
ensure
Expand Down
3 changes: 3 additions & 0 deletions sig/header/decompressor.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ module HTTP2
FORBIDDEN_HEADERS: Array[String]

@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
2 changes: 2 additions & 0 deletions sig/header/encoding_context.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module HTTP2
@unshifts: Integer

@limit: Integer
@table_size_limit: Integer

@_table_updated: bool

Expand All @@ -39,6 +40,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