Fix for issue #47 - double free of COL_INFO object (#48)
authorAlexandr Kuznetsov <progmachine@xenlab.one>
Fri, 27 Sep 2024 10:23:20 +0000 (13:23 +0300)
committerGitHub <noreply@github.com>
Fri, 27 Sep 2024 10:23:20 +0000 (06:23 -0400)
* Fix for issue #47 - double free of COL_INFO object due to refcount
breakage during reuse of directly found object in getColumnsInfo(...).
One more possible memory leak of COL_INFO objects in
getColumnsInfo(...).

Signed-off-by: Alexandr Kuznetsov <progmachine@xenlab.one>
* Fix spelling mistake in comment.

Signed-off-by: Alexandr Kuznetsov <progmachine@xenlab.one>
---------

Signed-off-by: Alexandr Kuznetsov <progmachine@xenlab.one>
.gitignore
connection.c
parse.c

index bd35adfdc95f8d0eeaf6c681735ecd275a13d23b..c7a61dfea926ddbad9266aa0a25dc44a589eefba 100644 (file)
@@ -36,6 +36,7 @@ windows-local.mak
 /Makefile.in
 /aclocal.m4
 /autom4te.cache/
+/autom4te.cache/*
 /config/
 /config.h
 /config.h.in
@@ -43,6 +44,7 @@ windows-local.mak
 /config.status
 /configure
 /libtool
+/psqlodbca.la
 /psqlodbcw.la
 /stamp-h1
 
@@ -107,6 +109,11 @@ bld/
 [Ll]og/
 [Ll]ogs/
 
+# Eclipse project options
+/.project
+/.cproject
+/.settings
+
 # Visual Studio 2015/2017 cache/options directory
 .vs/
 # Uncomment if you have tasks that create the project's static files in wwwroot
index d83e9acd5720f89e3c01aaf0f48dc09e7d81d7e4..7837dbb9f466406fce69746509eaf163d341f735 100644 (file)
@@ -556,6 +556,7 @@ CC_clear_col_info(ConnectionClass *self, BOOL destroy)
            /* Going through COL_INFO cache table and releasing coli objects. */
            if (coli = self->col_info[i], NULL != coli)
            {
+               MYLOG(0, "!!!refcnt %p:%d -> %d\n", coli, coli->refcnt, coli->refcnt - 1);
                coli->refcnt--;
                if (coli->refcnt <= 0)
                {
diff --git a/parse.c b/parse.c
index f63f3fc6fdf97d1eb65f814949ab4300b587c410..a8445afdaf556a4f12721c39dd9be862458903b6 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -829,7 +829,7 @@ getColumnsInfo(ConnectionClass *conn, TABLE_INFO *wti, OID greloid, StatementCla
    {
        BOOL        coli_exist = FALSE;
        COL_INFO    *coli = NULL, *ccoli = NULL, *tcoli;
-       int     k;
+       int      k, tmp_refcnt = 0;
        time_t      acctime = 0;
 
        MYLOG(0, "      Success\n");
@@ -882,6 +882,8 @@ getColumnsInfo(ConnectionClass *conn, TABLE_INFO *wti, OID greloid, StatementCla
        if (coli_exist)
        {
            /* We have ready to use coli object. Cleaning it. */
+           tmp_refcnt = coli->refcnt; /* If we found coli with greloid, then some TABLE_INFO objects may have references to it -> save refcnt for them. */
+           tmp_refcnt--; /* Down the road we will increase refcnt again to account for the reference from ConnectionClass object to coli object. */
            free_col_info_contents(coli);
        }
        else
@@ -921,6 +923,7 @@ getColumnsInfo(ConnectionClass *conn, TABLE_INFO *wti, OID greloid, StatementCla
        }
        col_info_initialize(coli);
 
+       coli->refcnt = tmp_refcnt;
        coli->refcnt++; /* Counting one reference to coli object from connection COL_INFO cache table. */
        coli->result = res;
        if (res && QR_get_num_cached_tuples(res) > 0)
@@ -976,6 +979,17 @@ MYLOG(DETAIL_LOG_LEVEL, "oid item == %s\n", (const char *) QR_get_value_backend_
        MYLOG(0, "Created col_info table='%s', ntables=%d\n", PRINT_NAME(wti->table_name), conn->ntables);
        /* Associate a table from the statement with a SQLColumn info */
        found = TRUE;
+       if (wti->col_info)
+       {
+           /* wti also has reference to COL_INFO object, so we must release it. */
+MYLOG(0, "!!!refcnt %p:%d -> %d\n", wti->col_info, wti->col_info->refcnt, wti->col_info->refcnt - 1);
+           wti->col_info->refcnt--;
+           if (wti->col_info->refcnt <= 0)
+           {
+               free_col_info_contents(wti->col_info);
+               free(wti->col_info);
+           }
+       }
        coli->refcnt++; /* Counting another one reference to coli object from TABLE_INFO wti object. */
        wti->col_info = coli;
    }