diff --git a/lib/rb/lib/thrift/protocol/base_protocol.rb b/lib/rb/lib/thrift/protocol/base_protocol.rb index 62650e466e6..73624769ec4 100644 --- a/lib/rb/lib/thrift/protocol/base_protocol.rb +++ b/lib/rb/lib/thrift/protocol/base_protocol.rb @@ -342,7 +342,8 @@ def read_type(field_info) end end - def skip(type) + def skip(type, max_depth = 64) + raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, 'Maximum skip depth exceeded') if max_depth <= 0 case type when Types::BOOL read_bool @@ -365,27 +366,27 @@ def skip(type) while true name, type, id = read_field_begin break if type == Types::STOP - skip(type) + skip(type, max_depth - 1) read_field_end end read_struct_end when Types::MAP ktype, vtype, size = read_map_begin size.times do - skip(ktype) - skip(vtype) + skip(ktype, max_depth - 1) + skip(vtype, max_depth - 1) end read_map_end when Types::SET etype, size = read_set_begin size.times do - skip(etype) + skip(etype, max_depth - 1) end read_set_end when Types::LIST etype, size = read_list_begin size.times do - skip(etype) + skip(etype, max_depth - 1) end read_list_end else diff --git a/lib/rb/spec/base_protocol_spec.rb b/lib/rb/spec/base_protocol_spec.rb index 6afed8786a0..3e177889e68 100644 --- a/lib/rb/spec/base_protocol_spec.rb +++ b/lib/rb/spec/base_protocol_spec.rb @@ -210,6 +210,17 @@ expect(@prot).to receive(:read_list_end) real_skip.call(Thrift::Types::LIST) end + + it "should raise DEPTH_LIMIT when max_depth is exhausted" do + expect { @prot.skip(Thrift::Types::STRUCT, 0) }.to raise_error(Thrift::ProtocolException) do |e| + expect(e.type).to eq(Thrift::ProtocolException::DEPTH_LIMIT) + end + end + + it "should skip at max_depth=1 without raising" do + expect(@prot).to receive(:read_bool).once + expect { @prot.skip(Thrift::Types::BOOL, 1) }.not_to raise_error + end end describe Thrift::BaseProtocolFactory do