1. memory leak: ob_refcnt of new ref from (unknown) _mysql_Exception is 1 too high

    Report

    1
    static int
    _mysql_ConnectionObject_Initialize(
    _mysql_ConnectionObject *self,
    PyObject *args,
    PyObject *kwargs)
    {
    MYSQL *conn = NULL;
    PyObject *conv = NULL;
    PyObject *ssl = NULL;
    #if HAVE_OPENSSL
    char *key = NULL, *cert = NULL, *ca = NULL,
    *capath = NULL, *cipher = NULL;
    #endif
    char *host = NULL, *user = NULL, *passwd = NULL,
    *db = NULL, *unix_socket = NULL;
    unsigned int port = 0;
    unsigned int client_flag = 0;
    static char *kwlist[] = { "host", "user", "passwd", "db", "port",
    "unix_socket", "conv",
    "connect_timeout", "compress",
    "named_pipe", "init_command",
    "read_default_file", "read_default_group",
    "client_flag", "ssl",
    "local_infile",
    #ifdef HAVE_MYSQL_OPT_TIMEOUTS
    "read_timeout",
    "write_timeout",
    #endif
    NULL } ;
    int connect_timeout = 0;
    #ifdef HAVE_MYSQL_OPT_TIMEOUTS
    int read_timeout = 0;
    int write_timeout = 0;
    #endif
    int compress = -1, named_pipe = -1, local_infile = -1;
    char *init_command=NULL,
    *read_default_file=NULL,
    *read_default_group=NULL;
    self->converter = NULL;
    self->open = 0;
    check_server_init(-1);
    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
    #ifdef HAVE_MYSQL_OPT_TIMEOUTS
    "|ssssisOiiisssiOiii:connect",
    #else
    "|ssssisOiiisssiOi:connect",
    #endif
    kwlist,
    &host, &user, &passwd, &db,
    &port, &unix_socket, &conv,
    &connect_timeout,
    &compress, &named_pipe,
    &init_command, &read_default_file,
    &read_default_group,
    &client_flag, &ssl,
    &local_infile
    #ifdef HAVE_MYSQL_OPT_TIMEOUTS
    , &read_timeout
    , &write_timeout
    #endif
    ))
    return -1;
    #define _stringsuck(d,t,s) {t=PyMapping_GetItemString(s,#d);\
    if(t){d=get_string(t);Py_DECREF(t);}\
    PyErr_Clear();}
    if (ssl) {
    #if HAVE_OPENSSL
    PyObject *value = NULL;
    _stringsuck(ca, value, ssl);
    _stringsuck(capath, value, ssl);
    _stringsuck(cert, value, ssl);
    _stringsuck(key, value, ssl);
    _stringsuck(cipher, value, ssl);
    #else
    PyErr_SetString(_mysql_NotSupportedError,
    "client library does not have SSL support");
    return -1;
    #endif
    }
    Py_BEGIN_ALLOW_THREADS ;
    conn = mysql_init(&(self->connection));
    if (connect_timeout) {
    unsigned int timeout = connect_timeout;
    mysql_options(&(self->connection), MYSQL_OPT_CONNECT_TIMEOUT,
    (char *)&timeout);
    }
    #ifdef HAVE_MYSQL_OPT_TIMEOUTS
    if (read_timeout) {
    unsigned int timeout = read_timeout;
    mysql_options(&(self->connection), MYSQL_OPT_READ_TIMEOUT,
    (char *)&timeout);
    }
    if (write_timeout) {
    unsigned int timeout = write_timeout;
    mysql_options(&(self->connection), MYSQL_OPT_WRITE_TIMEOUT,
    (char *)&timeout);
    }
    #endif
    if (compress != -1) {
    mysql_options(&(self->connection), MYSQL_OPT_COMPRESS, 0);
    client_flag |= CLIENT_COMPRESS;
    }
    if (named_pipe != -1)
    mysql_options(&(self->connection), MYSQL_OPT_NAMED_PIPE, 0);
    if (init_command != NULL)
    mysql_options(&(self->connection), MYSQL_INIT_COMMAND, init_command);
    if (read_default_file != NULL)
    mysql_options(&(self->connection), MYSQL_READ_DEFAULT_FILE, read_default_file);
    if (read_default_group != NULL)
    mysql_options(&(self->connection), MYSQL_READ_DEFAULT_GROUP, read_default_group);
    if (local_infile != -1)
    mysql_options(&(self->connection), MYSQL_OPT_LOCAL_INFILE, (char *) &local_infile);
    #if HAVE_OPENSSL
    if (ssl)
    mysql_ssl_set(&(self->connection),
    key, cert, ca, capath, cipher);
    #endif
    conn = mysql_real_connect(&(self->connection), host, user, passwd, db,
    port, unix_socket, client_flag);
    Py_END_ALLOW_THREADS ;
    if (!conn) {
    _mysql_Exception(self);
    return -1;
    }
    /* Internal references to python-land objects */
    if (!conv)
    conv = PyDict_New();
    else
    Py_INCREF(conv);
    if (!conv)
    return -1;
    self->converter = conv;
    /*
    PyType_GenericAlloc() automatically sets up GC allocation and
    tracking for GC objects, at least in 2.2.1, so it does not need to
    be done here. tp_dealloc still needs to call PyObject_GC_UnTrack(),
    however.
    */
    self->open = 1;
    return 0;
    }
    1. was expecting final owned ob_refcnt of new ref from (unknown) _mysql_Exception to be 0 since nothing references it but final ob_refcnt is refs: 1 owned

      found 8 similar trace(s) to this

    2. when considering range: -0x80000000 <= value <= -1

      taking False path

    3. when PyArg_ParseTupleAndKeywords() succeeds

      taking False path

    4. taking True path

    5. when PyMapping_GetItemString() succeeds

      taking True path

      when taking True path

      calling PyErr_Clear()

    6. when PyMapping_GetItemString() succeeds

      taking True path

      when taking True path

      calling PyErr_Clear()

    7. when PyMapping_GetItemString() succeeds

      taking True path

      when taking True path

      calling PyErr_Clear()

    8. when PyMapping_GetItemString() succeeds

      taking True path

      when taking True path

      calling PyErr_Clear()

    9. when PyMapping_GetItemString() succeeds

      taking True path

      when taking True path

      calling PyErr_Clear()

    10. releasing the GIL by calling PyEval_SaveThread()

    11. when considering range: -0x80000000 <= value <= -1

      taking True path

    12. when considering range: -0x80000000 <= value <= -1

      taking True path

    13. when considering range: -0x80000000 <= value <= -1

      taking True path

    14. when considering range: -0x80000000 <= value <= -2

      taking True path

    15. when considering range: -0x80000000 <= value <= -2

      taking True path

    16. when treating unknown const char * from _mysql.c:571 as non-NULL

      taking True path

    17. when treating unknown const char * from _mysql.c:571 as NULL

      taking False path

    18. when treating unknown const char * from _mysql.c:571 as non-NULL

      taking True path

    19. when considering range: 0 <= value <= 0x7fffffff

      taking True path

    20. taking True path

    21. reacquiring the GIL by calling PyEval_RestoreThread()

    22. when treating unknown struct MYSQL * from _mysql.c:653 as NULL

      taking True path

    23. when _mysql_Exception() succeeds

      new ref from (unknown) _mysql_Exception was allocated at: _mysql_Exception(self);