From 8d1f52ef24695d616b006c6b05c086c6d6209ba8 Mon Sep 17 00:00:00 2001 From: "Marc G. Fournier" Date: Fri, 6 Jun 1997 01:42:02 +0000 Subject: [PATCH] From: Igor Subject: [PATCHES] More psql and libpq patches Well..these would be the last patches until the release (I hope)... I ran the regression tests while watching psql under purify, and it did not leak even one byte. In this patch: * Plugged a major leak when PSQL reads files for input (either through \i options or through -f option) * Fixed the one remaining leak in PSQL in not clearing PGresult *results everywhere it is supposed to. (Thanks Tymm) * Fixed A small leak in PSQL not clearing all the PGsettings correctly. * A not-so-obvious (but small) leak in Libpq when PQsetdb fails for any reason. * Added \n to some Libpq error messages to make them easier to digest.. * Finally, added /* PURIFY */ comment to some of the code indicating the reason for why it was added/changed...for future developers. --- src/bin/psql/psql.c | 28 +++++++++++++++++----------- src/interfaces/libpq/fe-connect.c | 29 ++++++++++++++++++----------- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/bin/psql/psql.c b/src/bin/psql/psql.c index ccae6b30c5..cb0208a672 100644 --- a/src/bin/psql/psql.c +++ b/src/bin/psql/psql.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.70 1997/06/03 06:17:34 vadim Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.71 1997/06/06 01:41:24 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -184,7 +184,8 @@ slashUsage(PsqlSettings * ps) static PGresult * PSQLexec(PsqlSettings * ps, char *query) { - PGresult *res = PQexec(ps->db, query); + PGresult *res; + res = PQexec(ps->db, query); if (!res) fputs(PQerrorMessage(ps->db), stderr); else { @@ -259,7 +260,6 @@ tableList(PsqlSettings * ps, bool deep_tablelist, char table_index_both) strcat(listbuf, " ORDER BY relname "); if (!(res = PSQLexec(ps, listbuf))) return -1; - /* first, print out the attribute names */ nColumns = PQntuples(res); if (nColumns > 0) { @@ -278,7 +278,7 @@ tableList(PsqlSettings * ps, bool deep_tablelist, char table_index_both) strcpy(table[i], PQgetvalue(res, i, 1)); } - PQclear(res); + PQclear(res); /* PURIFY */ for (i = 0; i < nColumns; i++) { tableDesc(ps, table[i]); } @@ -309,6 +309,7 @@ tableList(PsqlSettings * ps, bool deep_tablelist, char table_index_both) return (0); } else { + PQclear(res); /* PURIFY */ switch (table_index_both) { case 't': fprintf(stderr, "Couldn't find any tables!\n"); break; @@ -507,7 +508,10 @@ gets_fromFile(char *prompt, FILE * source) /* read up to MAX_QUERY_BUFFER characters */ if (fgets(line, MAX_QUERY_BUFFER, source) == NULL) + { + free(line); return NULL; + } line[MAX_QUERY_BUFFER - 1] = '\0'; len = strlen(line); @@ -579,17 +583,14 @@ SendQuery(bool * success_p, PsqlSettings * settings, const char *query, &(settings->opt)); fflush(settings->queryFout); } - PQclear(results); break; case PGRES_EMPTY_QUERY: *success_p = true; - PQclear(results); break; case PGRES_COMMAND_OK: *success_p = true; if (!settings->quiet) fprintf(stdout, "%s\n", PQcmdStatus(results)); - PQclear(results); break; case PGRES_COPY_OUT: *success_p = true; @@ -601,7 +602,6 @@ SendQuery(bool * success_p, PsqlSettings * settings, const char *query, handleCopyOut(results, settings->quiet, stdout); } - PQclear(results); break; case PGRES_COPY_IN: *success_p = true; @@ -609,7 +609,6 @@ SendQuery(bool * success_p, PsqlSettings * settings, const char *query, handleCopyIn(results, false, copystream); else handleCopyIn(results, !settings->quiet, stdin); - PQclear(results); break; case PGRES_NONFATAL_ERROR: case PGRES_FATAL_ERROR: @@ -634,6 +633,7 @@ SendQuery(bool * success_p, PsqlSettings * settings, const char *query, notify->relname, notify->be_pid); free(notify); } + if(results) PQclear(results); } } @@ -1434,7 +1434,6 @@ MainLoop(PsqlSettings * settings, FILE * source) } query_start = line; - if (line == NULL) { /* No more input. Time to quit */ if (!settings->quiet) printf("EOF\n"); /* Goes on prompt line */ @@ -1544,8 +1543,10 @@ MainLoop(PsqlSettings * settings, FILE * source) fprintf(stderr, "query buffer max length of %d exceeded\n", MAX_QUERY_BUFFER); fprintf(stderr, "query line ignored\n"); + free (line); } else { if (query_start[0] != '\0') { + querySent = false; if (query[0] != '\0') { strcat(query, "\n"); @@ -1553,6 +1554,7 @@ MainLoop(PsqlSettings * settings, FILE * source) } else strcpy(query, query_start); } + free(line); /* PURIFY */ } if (slashCmdStatus == 0) { @@ -1560,7 +1562,6 @@ MainLoop(PsqlSettings * settings, FILE * source) successResult &= success; querySent = true; } - free(line); /* free storage malloc'd by GetNextLine */ } } /* while */ return successResult; @@ -1702,6 +1703,7 @@ main(int argc, char **argv) if (PQstatus(settings.db) == CONNECTION_BAD) { fprintf(stderr, "Connection to database '%s' failed.\n", dbname); fprintf(stderr, "%s", PQerrorMessage(settings.db)); + PQfinish(settings.db); exit(1); } if (listDatabases) { @@ -1731,6 +1733,8 @@ main(int argc, char **argv) sprintf(line, "\\i %s", qfilename); } HandleSlashCmds(&settings, line, ""); + if (!singleSlashCmd) free (line); /* PURIFY */ + } else { if (singleQuery) { bool success; /* The query succeeded at the backend */ @@ -1741,6 +1745,8 @@ main(int argc, char **argv) } PQfinish(settings.db); + free(settings.opt.fieldSep); /* PURIFY */ + if(settings.prompt) free(settings.prompt); /* PURIFY */ return !successResult; } diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 4cf8ef2aeb..3c5abd9c8f 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.36 1997/06/01 15:38:52 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.37 1997/06/06 01:42:02 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -569,6 +569,12 @@ connectDB(PGconn *conn) return CONNECTION_OK; connect_errReturn: + + /* Igor/6/3/97 - We need to free it here...otherwise the function + returns without setting conn->port to port. Because of that + any way of referencing this variable will be lost and it's allocated + memory will not be freed. */ + free(port); /* PURIFY */ return CONNECTION_BAD; } @@ -581,6 +587,7 @@ connect_errReturn: static void freePGconn(PGconn *conn) { + if (!conn) return; if (conn->pghost) free(conn->pghost); if (conn->pgtty) free(conn->pgtty); if (conn->pgoptions) free(conn->pgoptions); @@ -639,7 +646,7 @@ void PQfinish(PGconn *conn) { if (!conn) { - fprintf(stderr,"PQfinish() -- pointer to PGconn is null"); + fprintf(stderr,"PQfinish() -- pointer to PGconn is null\n"); } else { if (conn->status == CONNECTION_OK) closePGconn(conn); @@ -655,7 +662,7 @@ void PQreset(PGconn *conn) { if (!conn) { - fprintf(stderr,"PQreset() -- pointer to PGconn is null"); + fprintf(stderr,"PQreset() -- pointer to PGconn is null\n"); } else { closePGconn(conn); conn->status = connectDB(conn); @@ -957,7 +964,7 @@ char* PQdb(PGconn* conn) { if (!conn) { - fprintf(stderr,"PQdb() -- pointer to PGconn is null"); + fprintf(stderr,"PQdb() -- pointer to PGconn is null\n"); return (char *)NULL; } return conn->dbName; @@ -967,7 +974,7 @@ char* PQuser(PGconn* conn) { if (!conn) { - fprintf(stderr,"PQuser() -- pointer to PGconn is null"); + fprintf(stderr,"PQuser() -- pointer to PGconn is null\n"); return (char *)NULL; } return conn->pguser; @@ -977,7 +984,7 @@ char* PQhost(PGconn* conn) { if (!conn) { - fprintf(stderr,"PQhost() -- pointer to PGconn is null"); + fprintf(stderr,"PQhost() -- pointer to PGconn is null\n"); return (char *)NULL; } @@ -988,7 +995,7 @@ char* PQoptions(PGconn* conn) { if (!conn) { - fprintf(stderr,"PQoptions() -- pointer to PGconn is null"); + fprintf(stderr,"PQoptions() -- pointer to PGconn is null\n"); return (char *)NULL; } return conn->pgoptions; @@ -998,7 +1005,7 @@ char* PQtty(PGconn* conn) { if (!conn) { - fprintf(stderr,"PQtty() -- pointer to PGconn is null"); + fprintf(stderr,"PQtty() -- pointer to PGconn is null\n"); return (char *)NULL; } return conn->pgtty; @@ -1008,7 +1015,7 @@ char* PQport(PGconn* conn) { if (!conn) { - fprintf(stderr,"PQport() -- pointer to PGconn is null"); + fprintf(stderr,"PQport() -- pointer to PGconn is null\n"); return (char *)NULL; } return conn->pgport; @@ -1018,7 +1025,7 @@ ConnStatusType PQstatus(PGconn* conn) { if (!conn) { - fprintf(stderr,"PQstatus() -- pointer to PGconn is null"); + fprintf(stderr,"PQstatus() -- pointer to PGconn is null\n"); return CONNECTION_BAD; } return conn->status; @@ -1028,7 +1035,7 @@ char* PQerrorMessage(PGconn* conn) { if (!conn) { - fprintf(stderr,"PQerrorMessage() -- pointer to PGconn is null"); + fprintf(stderr,"PQerrorMessage() -- pointer to PGconn is null\n"); return (char *)NULL; } return conn->errorMessage;