From 492b45aedc4788337440f936e942e7e5219f9624 Mon Sep 17 00:00:00 2001 From: "Ali Firas (thesmartshadow)" Date: Wed, 25 Mar 2026 15:43:39 +0000 Subject: [PATCH] Wrap SystemStackError as ResponseParseError in ResponseParser --- lib/net/imap/response_parser.rb | 2 ++ test/net/imap/test_response_parser.rb | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/lib/net/imap/response_parser.rb b/lib/net/imap/response_parser.rb index 4a80fb64..ba6deaf4 100644 --- a/lib/net/imap/response_parser.rb +++ b/lib/net/imap/response_parser.rb @@ -691,6 +691,8 @@ def response CRLF! EOF! resp + rescue SystemStackError => error + raise exception(error.message), cause: error end # RFC3501 & RFC9051: diff --git a/test/net/imap/test_response_parser.rb b/test/net/imap/test_response_parser.rb index eaa6ff24..e7309ec7 100644 --- a/test/net/imap/test_response_parser.rb +++ b/test/net/imap/test_response_parser.rb @@ -201,6 +201,26 @@ def test_fetch_binary_and_binary_size end end + test "deeply nested BODYSTRUCTURE raises ResponseParseError instead of SystemStackError" do + parser = Net::IMAP::ResponseParser.new + + def parser.body + raise SystemStackError, "stack level too deep" + end unless ENV["TEST_RESPONSE_PARSER_STACK_LEVEL"] == "original" + + depth = 10_000 + leaf = '("TEXT" "PLAIN" NIL NIL NIL "7BIT" 1 1)' + bodystructure = depth.times.reduce(leaf) { |part, _| "(#{part} \"MIXED\")" } + response = "* 1 FETCH (BODYSTRUCTURE #{bodystructure})\r\n" + + err = assert_raise(Net::IMAP::ResponseParseError) do + parser.parse(response) + end + + assert_match(/stack level too deep/i, err.message) + assert_instance_of(SystemStackError, err.cause) + end + def assert_deprecated_appenduid_data_warning assert_warn(/#{__FILE__}.*warning.*parser_use_deprecated_uidplus_data is ignored/) do result = yield