New issue 2578: Behavioral discrepancy between CPython and PyPy ssl modules
https://bitbucket.org/pypy/pypy/issues/2578/behavioral-discrepancy-between-cpython-and
Nathaniel Smith:
Here's a weird edge case where the CPython and PyPy ssl modules behave
differently. I'm not entirely sure whether it's a bug or not, and it's easy
enough for me to work around, but I found the PyPy behavior surprising and who
knows it might point to some deeper issue, so I wanted to make a formal note.
Scenario:
* Client and server negotiate a TLS connection
* Client sends `close_notify` then immediately closes socket
* Server receives `close_notify` then attempts to send `close_notify` back
In this scenario, on CPython the server gets a `BrokenPipeError`, which makes
sense – this is the usual error for trying to send data on a socket that the
other side already closed. On PyPy, the server gets a `SSLEOFError: EOF
occurred in violation of protocol`. This is (a) different, and (b) the text is
not true, the EOF was totally legal.
(Quoth RFC 5246: "Unless some other fatal alert has been transmitted, each
party is required to send a close_notify alert before closing the write side of
the connection. The other party MUST respond with a close_notify alert of its
own and close down the connection immediately, discarding any pending writes.
It is not required for the initiator of the close to wait for the responding
close_notify alert before closing the read side of the connection.")
Weirdly, running under strace I can see PyPy getting `EPIPE` before raising
`SSLEOFError`, and then the next syscall it makes is to start looking up python
files so it can print the traceback:
```
[pid 17390] write(4,
"\25\3\3\0\32\211\327\250b\301+o\373$\363\32\t\r\231\261\256\322\f\230\362\205vr\224VD",
31) = -1 EPIPE (Broken pipe)
[pid 17390] --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=17387,
si_uid=1000} ---
[pid 17390]
stat("/home/njs/pypy/pypy3.5-5.8-beta-linux_x86_64-portable/lib-python/3/threading.py",
{st_mode=S_IFREG|0644, st_size=48919, ...}) = 0
```
And looking at the definition of `pyssl_error` in
lib_pypy/_cffi_ssl/_stdssl/error.py, it looks like the difference between
raising `SSLEOFError` and an `OSError` like `BrokenPipeError` is the setting of
a "did the BIO indicate an error" flag. If that flag is broken in general then
that's definitely worrisome.
Sample code here:
https://gist.github.com/njsmith/7cf06383adca0392c862cfa22cb70804
CC: @alex_gaynor
_______________________________________________
pypy-issue mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-issue