Skip to content

Commit 28d59c3

Browse files
kpumukcodex
andauthored
THRIFT-6158: Classify malformed request arguments as protocol errors (#3748)
Client: rb Co-authored-by: OpenAI Codex (GPT-5.6) <codex@openai.com>
1 parent 936bbf1 commit 28d59c3

2 files changed

Lines changed: 53 additions & 0 deletions

File tree

lib/rb/lib/thrift/processor.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,14 @@
1919
#
2020

2121
require "logger"
22+
require "thrift/protocol/base_protocol"
2223

2324
module Thrift
2425
module Processor
26+
class ArgumentProtocolException < ProtocolException
27+
end
28+
private_constant :ArgumentProtocolException
29+
2530
def initialize(handler, logger = nil)
2631
@handler = handler
2732
if logger.nil?
@@ -48,6 +53,9 @@ def process(iprot, oprot)
4853
if respond_to?("process_#{name}")
4954
begin
5055
send("process_#{name}", seqid, iprot, oprot)
56+
rescue ArgumentProtocolException => e
57+
x = ApplicationException.new(ApplicationException::PROTOCOL_ERROR, e.message)
58+
write_error(x, oprot, name, seqid)
5159
rescue => e
5260
x = ApplicationException.new(ApplicationException::INTERNAL_ERROR, "Internal error")
5361
@logger.debug "Internal error : #{e.message}\n#{e.backtrace.join("\n")}"
@@ -68,6 +76,8 @@ def read_args(iprot, args_class)
6876
args.read(iprot)
6977
iprot.read_message_end
7078
args
79+
rescue ProtocolException => e
80+
raise ArgumentProtocolException.new(e.type, e.message)
7181
end
7282

7383
def write_result(result, oprot, name, seqid)

lib/rb/spec/processor_spec.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,49 @@ def output_protocol
167167
end
168168
end
169169

170+
it "returns protocol errors for malformed request arguments" do
171+
handler = double("Handler")
172+
expect(handler).not_to receive(:sleep)
173+
processor = SpecNamespace::NonblockingService::Processor.new(handler)
174+
input = Thrift::JsonProtocol.new(
175+
Thrift::MemoryBufferTransport.new('[1,"sleep",1,17,{"1":{"dbl":x}}]'),
176+
)
177+
output_transport = Thrift::MemoryBufferTransport.new
178+
179+
expect(processor.process(input, Thrift::JsonProtocol.new(output_transport))).to be true
180+
181+
response = Thrift::JsonProtocol.new(output_transport)
182+
expect(response.read_message_begin).to eq(["sleep", Thrift::MessageTypes::EXCEPTION, 17])
183+
exception = Thrift::ApplicationException.new
184+
exception.read(response)
185+
response.read_message_end
186+
187+
expect(exception.type).to eq(Thrift::ApplicationException::PROTOCOL_ERROR)
188+
expect(exception.message).to eq('Expected numeric value; got ""')
189+
end
190+
191+
it "keeps protocol exceptions raised by handlers as internal errors" do
192+
handler = double("Handler")
193+
expect(handler).to receive(:sleep).with(3.0).and_raise(
194+
Thrift::ProtocolException.new(Thrift::ProtocolException::INVALID_DATA, "handler failed"),
195+
)
196+
processor = SpecNamespace::NonblockingService::Processor.new(handler)
197+
args = SpecNamespace::NonblockingService::Sleep_args.new(seconds: 3.0)
198+
input = input_protocol("sleep", Thrift::MessageTypes::CALL, 18, args)
199+
output_transport, output = output_protocol
200+
201+
expect(processor.process(input, output)).to be true
202+
203+
response = Thrift::BinaryProtocol.new(output_transport)
204+
expect(response.read_message_begin).to eq(["sleep", Thrift::MessageTypes::EXCEPTION, 18])
205+
exception = Thrift::ApplicationException.new
206+
exception.read(response)
207+
response.read_message_end
208+
209+
expect(exception.type).to eq(Thrift::ApplicationException::INTERNAL_ERROR)
210+
expect(exception.message).to eq("Internal error")
211+
end
212+
170213
it "should write out a reply when asked" do
171214
expect(@prot).to receive(:write_message_begin).with("testMessage", Thrift::MessageTypes::REPLY, 23).ordered
172215
result = double("MockResult")

0 commit comments

Comments
 (0)