Issue #13379 has been updated by shugo (Shugo Maeda).

Assignee set to shugo (Shugo Maeda)

ahorek (Pavel Rosick) wrote:
> Hi,
> I found out that using the standard IMAP library isn't very safe. It can be forced to hang the whole application.
> 
> the problem is here
> ```
> s = @sock.gets(CRLF)
> ```
> -> the server accepted the connection but it didn't send any data. Now I need to reboot the server because my thread is blocked forever.
> 
> I have no other option but to use this
> ```
> Timeout.timeout(timeout, Net::OpenTimeout) { Net::IMAP.new(host, port, ssl) }
> ```
> 
> which basically works, but I really don't want to create a new thread for each IMAP call, so I did these changes:
> 1/ replaced TCPSocket with Socket.tcp
> 2/ replaced sock.read and sock.gets with sock.read_nonblock
> 
> now it works as expected.
> 
> Patch
> https://github.com/ruby/ruby/pull/1557

Thanks for the patch, but it doesn't seem enough because:

1. The :connect_timeout option of Socket.tcp doesn't work when DNS lookups by getaddrinfo block.
   A new thread by Timeout.timeout is needed to handle this case.
2. TLS handshakes in start_tls_session may also block.  Protocol#ssl_socket_connect can be used to
   handle this case.

And I'm not sure whether open_timeout should have the default value because a new thread is required.



----------------------------------------
Feature #13379: [PATCH] safe IMAP connections
https://bugs.ruby-lang.org/issues/13379#change-63933

* Author: ahorek (Pavel Rosick)
* Status: Open
* Priority: Normal
* Assignee: shugo (Shugo Maeda)
* Target version: 
----------------------------------------
Hi,
I found out that using the standard IMAP library isn't very safe. It can be forced to hang the whole application.

the problem is here
```
s = @sock.gets(CRLF)
```
-> the server accepted the connection but it didn't send any data. Now I need to reboot the server because my thread is blocked forever.

I have no other option but to use this
```
Timeout.timeout(timeout, Net::OpenTimeout) { Net::IMAP.new(host, port, ssl) }
```

which basically works, but I really don't want to create a new thread for each IMAP call, so I did these changes:
1/ replaced TCPSocket with Socket.tcp
2/ replaced sock.read and sock.gets with sock.read_nonblock

now it works as expected.

Patch
https://github.com/ruby/ruby/pull/1557

related issue, please consider merging this one as well
#12928

---Files--------------------------------
imap.patch (3.29 KB)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>