Skip to content

Commit 9781b5c

Browse files
committed
Handle deep response recursion as ResponseParseError
1 parent 6229814 commit 9781b5c

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

lib/net/imap/response_parser.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,8 @@ def response
691691
CRLF!
692692
EOF!
693693
resp
694+
rescue SystemStackError
695+
parse_error("response recursion too deep")
694696
end
695697

696698
# RFC3501 & RFC9051:

test/net/imap/test_response_parser.rb

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,4 +356,53 @@ def assert_deprecated_copyuid_data_warning(check: true)
356356
assert_instance_of Net::IMAP::CopyUIDData, response.data.code.data
357357
end
358358

359+
def deeply_nested_bodystructure(depth)
360+
leaf = '("TEXT" "PLAIN" NIL NIL NIL "7BIT" 1 1)'
361+
depth.times.reduce(leaf) { |part, _| "(#{part} \"MIXED\")" }
362+
end
363+
364+
def deeply_nested_thread(depth)
365+
depth.times.reduce("(1)") { |thread, _| "(#{thread}(1))" }
366+
end
367+
368+
def deeply_nested_extension_value(depth)
369+
depth.times.reduce("1") { |value, _| "(#{value})" }
370+
end
371+
372+
test "deeply nested BODYSTRUCTURE raises ResponseParseError instead of SystemStackError" do
373+
parser = Net::IMAP::ResponseParser.new
374+
response = "* 1 FETCH (BODYSTRUCTURE #{deeply_nested_bodystructure(6000)})\r\n"
375+
376+
error = assert_raise(Net::IMAP::ResponseParseError) do
377+
parser.parse(response)
378+
end
379+
380+
assert_equal "response recursion too deep", error.message
381+
assert_instance_of SystemStackError, error.cause
382+
end
383+
384+
test "deeply nested THREAD raises ResponseParseError instead of SystemStackError" do
385+
parser = Net::IMAP::ResponseParser.new
386+
response = "* THREAD #{deeply_nested_thread(6000)}\r\n"
387+
388+
error = assert_raise(Net::IMAP::ResponseParseError) do
389+
parser.parse(response)
390+
end
391+
392+
assert_equal "response recursion too deep", error.message
393+
assert_instance_of SystemStackError, error.cause
394+
end
395+
396+
test "deeply nested STATUS extension raises ResponseParseError instead of SystemStackError" do
397+
parser = Net::IMAP::ResponseParser.new
398+
response = "* STATUS INBOX (X #{deeply_nested_extension_value(11_000)})\r\n"
399+
400+
error = assert_raise(Net::IMAP::ResponseParseError) do
401+
parser.parse(response)
402+
end
403+
404+
assert_equal "response recursion too deep", error.message
405+
assert_instance_of SystemStackError, error.cause
406+
end
407+
359408
end

0 commit comments

Comments
 (0)