classification
Title: ssl.SSLSocket.send(b"") fails
Type: behavior Stage: patch review
Components: Documentation, SSL Versions: Python 3.8, Python 3.7, Python 3.6, Python 2.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: docs@python Nosy List: alex, christian.heimes, docs@python, dstufft, janssen, joernheissler, njs
Priority: normal Keywords: patch

Created on 2017-10-06 09:43 by joernheissler, last changed 2018-06-09 14:03 by python-dev.

Files
File name Uploaded Description Edit
client.py joernheissler, 2017-10-06 09:42
Pull Requests
URL Status Linked Edit
PR 7559 open python-dev, 2018-06-09 14:03
Messages (5)
msg303810 - (view) Author: Jörn Heissler (joernheissler) Date: 2017-10-06 09:42
Traceback (most recent call last):
  File "client.py", line 10, in <module>
    conn.send(b'')
  File "/usr/lib/python3.6/ssl.py", line 941, in send
    return self._sslobj.write(data)
  File "/usr/lib/python3.6/ssl.py", line 642, in write
    return self._sslobj.write(data)
ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:2074)

This error is not what I expected. I expected a noop instead.

My guess is, that python calls SSL_write (3.6 branch, _ssl.c:2038) with that empty buffer.
The manpage states: "When calling SSL_write() with num=0 bytes to be sent the behaviour is undefined."

This undefined behaviour should either be documented in python, or defined to either raise an exception (ValueError?) or defined as a noop. I'd prefer the latter.
msg312898 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2018-02-26 09:06
It's a bit too late to change the behavior of send(). Let's document the issue instead.
msg312903 - (view) Author: Nathaniel Smith (njs) * (Python committer) Date: 2018-02-26 09:42
If openssl says the behavior is undefined, then don't we have to first make it defined before we can document it?

And if we're going to detect this case and guarantee some behavior, making it a no-op like it is on regular sockets seems the way to go...
msg312908 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2018-02-26 09:57
The message "EOF occurred in violation of protocol" is set by Python. Python maps SSL_ERROR_SYSCALL with SSL error code == 0 and len == 0 to that error message. 

https://github.com/python/cpython/blob/master/Modules/_ssl.c#L682-L689
https://github.com/python/cpython/blob/master/Modules/_ssl.c#L2263

I don't know why the code was implemented that way.
msg312956 - (view) Author: Nathaniel Smith (njs) * (Python committer) Date: 2018-02-26 20:54
My point is that SSL_write(3ssl) says "WARNING: When calling SSL_write() with num=0 bytes to be sent the behaviour is undefined."

Apparently on the particular openssl you're looking at, it gives SSL_ERROR_SYSCALL with error code == 0 and len == 0, but the openssl devs claim this is some arbitrary thing that shouldn't be depended on.

Just as a general principle it would be nice if performing ordinary operations on an SSLSocket from Python did not invoke undefined behavior :-)
History
Date User Action Args
2018-06-09 14:03:22python-devsetkeywords: + patch
stage: needs patch -> patch review
pull_requests: + pull_request7191
2018-02-26 20:54:16njssetmessages: + msg312956
2018-02-26 09:57:24christian.heimessetmessages: + msg312908
2018-02-26 09:42:33njssetmessages: + msg312903
2018-02-26 09:06:41christian.heimessetassignee: christian.heimes -> docs@python
components: + Documentation
versions: + Python 2.7, Python 3.7, Python 3.8
nosy: + alex, janssen, dstufft, docs@python, njs

messages: + msg312898
stage: needs patch
2017-10-06 09:43:00joernheisslercreate