classification
Title: NULL pointer deref on error path in _ssl debughelpers.c
Type: Stage:
Components: SSL Versions: Python 3.9
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: christian.heimes Nosy List: Alexander Riccio, christian.heimes
Priority: normal Keywords:

Created on 2020-03-26 21:56 by Alexander Riccio, last changed 2020-03-26 21:56 by Alexander Riccio.

Messages (1)
msg365114 - (view) Author: Alexander Riccio (Alexander Riccio) * Date: 2020-03-26 21:56
At line 138 in debughelpers.c, ssl_obj, which was set to NULL on line 122, is dereferenced. 

I think the original intent was to actually bubble the error up through the ssl object.



Full function:

static void
_PySSL_keylog_callback(const SSL *ssl, const char *line)
{
    PyGILState_STATE threadstate;
    PySSLSocket *ssl_obj = NULL;  /* ssl._SSLSocket, borrowed ref */
    int res, e;
    static PyThread_type_lock *lock = NULL;

    threadstate = PyGILState_Ensure();

    /* Allocate a static lock to synchronize writes to keylog file.
     * The lock is neither released on exit nor on fork(). The lock is
     * also shared between all SSLContexts although contexts may write to
     * their own files. IMHO that's good enough for a non-performance
     * critical debug helper.
     */
    if (lock == NULL) {
        lock = PyThread_allocate_lock();
        if (lock == NULL) {
            PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
            PyErr_Fetch(&ssl_obj->exc_type, &ssl_obj->exc_value,
                        &ssl_obj->exc_tb);
            return;
        }
    }

    ssl_obj = (PySSLSocket *)SSL_get_app_data(ssl);
    assert(PySSLSocket_Check(ssl_obj));
    if (ssl_obj->ctx->keylog_bio == NULL) {
        return;
    }

    PySSL_BEGIN_ALLOW_THREADS
    PyThread_acquire_lock(lock, 1);
    res = BIO_printf(ssl_obj->ctx->keylog_bio, "%s\n", line);
    e = errno;
    (void)BIO_flush(ssl_obj->ctx->keylog_bio);
    PyThread_release_lock(lock);
    PySSL_END_ALLOW_THREADS

    if (res == -1) {
        errno = e;
        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError,
                                             ssl_obj->ctx->keylog_filename);
        PyErr_Fetch(&ssl_obj->exc_type, &ssl_obj->exc_value, &ssl_obj->exc_tb);
    }
    PyGILState_Release(threadstate);
}
History
Date User Action Args
2020-03-26 21:56:53Alexander Ricciocreate