Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.7k
Description
Bug report
Bug description:
It was dealt with other issues before, but the contents are not intuitive, so I rearrange them.
TheSSL_write() andSSL_read() used in python 3.9 were modified from python 3.10 toSSL_write_ex() andSSL_read_ex(), and the return value was fixed to 0 on error. However, inPySSL_SetError, there is no update accordingly, so this part needs to be modified.
Related issue can be referred to the following link.
OpenSSL 1.1.1: use SSL_write_ex() and SSL_read_ex()
The difference betweenSSL_write() andSSL_write_ex() is as follows.
intSSL_write(SSL*s,constvoid*buf,intnum){intret;size_twritten;if (num<0) {ERR_raise(ERR_LIB_SSL,SSL_R_BAD_LENGTH);return-1; }ret=ssl_write_internal(s,buf, (size_t)num,0,&written);/* * The cast is safe here because ret should be <= INT_MAX because num is * <= INT_MAX */if (ret>0)ret= (int)written;returnret;}
SSL_write() has a return value of 0 or less when an error occurs.
intSSL_write_ex(SSL*s,constvoid*buf,size_tnum,size_t*written){returnSSL_write_ex2(s,buf,num,0,written);}intSSL_write_ex2(SSL*s,constvoid*buf,size_tnum,uint64_tflags,size_t*written){intret=ssl_write_internal(s,buf,num,flags,written);if (ret<0)ret=0;returnret;}
SSL_write_ex() is fixed to 0 when an error occurs. As the return value changes, the behavior of thePySSL_SetError function changes.
Line 648 inf9154f8
| if (ret==0|| (((PyObject*)s)==Py_None)) { |
caseSSL_ERROR_SYSCALL:{if (e==0) {PySocketSockObject*s=GET_SOCKET(sslsock);if (ret==0|| (((PyObject*)s)==Py_None)) {p=PY_SSL_ERROR_EOF;type=state->PySSLEOFErrorObject;errstr="EOF occurred in violation of protocol";}elseif (s&&ret==-1) {/* underlying BIO reported an I/O error */ERR_clear_error();#ifdefMS_WINDOWSif (err.ws) {returnPyErr_SetFromWindowsErr(err.ws);}#endifif (err.c) {errno=err.c;returnPyErr_SetFromErrno(PyExc_OSError);}else {p=PY_SSL_ERROR_EOF;type=state->PySSLEOFErrorObject;errstr="EOF occurred in violation of protocol";}}else {/* possible? */p=PY_SSL_ERROR_SYSCALL;type=state->PySSLSyscallErrorObject;errstr="Some I/O error occurred";}}else {if (ERR_GET_LIB(e)==ERR_LIB_SSL&&ERR_GET_REASON(e)==SSL_R_CERTIFICATE_VERIFY_FAILED) {type=state->PySSLCertVerificationErrorObject;}p=PY_SSL_ERROR_SYSCALL;}break;}
According to the partif (ret == 0 || ((PyObject *) == Py_None)), the retrun of the functionSSL_write_ex() is fixed to 0, resulting inSSLEOFError instead ofOSError.
I determined that the change to this error was not intended. If the connection is terminated by the other peer, it is better for the user to respond to it by returning it as an error such as BrokenPIPE rather than an error that is a protocol rule violation.
The modifications affected by the change have been identified as follows.
- The behavior of the SSL test server for OSError has changed. ConnectionError did not previously shut down the server, but now it does.
- I think this is because the change has not been tested as OSError does not occur at write or read.
- It is believed that an intermittent EOF error occurred instead of an OSError.
- OSError has disappeared, only EOF errors have been handled.
Related issues are as follows.
CPython versions tested on:
3.10, 3.11, 3.12, 3.13, CPython main branch
Operating systems tested on:
Linux, macOS