Skip to content

Commit 563ad6c

Browse files
authored
Fix for issue #47 - double free of COL_INFO object (#48)
* 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 <[email protected]> * Fix spelling mistake in comment. Signed-off-by: Alexandr Kuznetsov <[email protected]> --------- Signed-off-by: Alexandr Kuznetsov <[email protected]>
1 parent 0e4acc3 commit 563ad6c

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@ windows-local.mak
3636
/Makefile.in
3737
/aclocal.m4
3838
/autom4te.cache/
39+
/autom4te.cache/*
3940
/config/
4041
/config.h
4142
/config.h.in
4243
/config.log
4344
/config.status
4445
/configure
4546
/libtool
47+
/psqlodbca.la
4648
/psqlodbcw.la
4749
/stamp-h1
4850

@@ -107,6 +109,11 @@ bld/
107109
[Ll]og/
108110
[Ll]ogs/
109111

112+
# Eclipse project options
113+
/.project
114+
/.cproject
115+
/.settings
116+
110117
# Visual Studio 2015/2017 cache/options directory
111118
.vs/
112119
# Uncomment if you have tasks that create the project's static files in wwwroot

connection.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ CC_clear_col_info(ConnectionClass *self, BOOL destroy)
556556
/* Going through COL_INFO cache table and releasing coli objects. */
557557
if (coli = self->col_info[i], NULL != coli)
558558
{
559+
MYLOG(0, "!!!refcnt %p:%d -> %d\n", coli, coli->refcnt, coli->refcnt - 1);
559560
coli->refcnt--;
560561
if (coli->refcnt <= 0)
561562
{

parse.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,7 @@ getColumnsInfo(ConnectionClass *conn, TABLE_INFO *wti, OID greloid, StatementCla
829829
{
830830
BOOL coli_exist = FALSE;
831831
COL_INFO *coli = NULL, *ccoli = NULL, *tcoli;
832-
int k;
832+
int k, tmp_refcnt = 0;
833833
time_t acctime = 0;
834834

835835
MYLOG(0, " Success\n");
@@ -882,6 +882,8 @@ getColumnsInfo(ConnectionClass *conn, TABLE_INFO *wti, OID greloid, StatementCla
882882
if (coli_exist)
883883
{
884884
/* We have ready to use coli object. Cleaning it. */
885+
tmp_refcnt = coli->refcnt; /* If we found coli with greloid, then some TABLE_INFO objects may have references to it -> save refcnt for them. */
886+
tmp_refcnt--; /* Down the road we will increase refcnt again to account for the reference from ConnectionClass object to coli object. */
885887
free_col_info_contents(coli);
886888
}
887889
else
@@ -921,6 +923,7 @@ getColumnsInfo(ConnectionClass *conn, TABLE_INFO *wti, OID greloid, StatementCla
921923
}
922924
col_info_initialize(coli);
923925

926+
coli->refcnt = tmp_refcnt;
924927
coli->refcnt++; /* Counting one reference to coli object from connection COL_INFO cache table. */
925928
coli->result = res;
926929
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_
976979
MYLOG(0, "Created col_info table='%s', ntables=%d\n", PRINT_NAME(wti->table_name), conn->ntables);
977980
/* Associate a table from the statement with a SQLColumn info */
978981
found = TRUE;
982+
if (wti->col_info)
983+
{
984+
/* wti also has reference to COL_INFO object, so we must release it. */
985+
MYLOG(0, "!!!refcnt %p:%d -> %d\n", wti->col_info, wti->col_info->refcnt, wti->col_info->refcnt - 1);
986+
wti->col_info->refcnt--;
987+
if (wti->col_info->refcnt <= 0)
988+
{
989+
free_col_info_contents(wti->col_info);
990+
free(wti->col_info);
991+
}
992+
}
979993
coli->refcnt++; /* Counting another one reference to coli object from TABLE_INFO wti object. */
980994
wti->col_info = coli;
981995
}

0 commit comments

Comments
 (0)