From 83a673808dc3a47363eae6388bea8571e2bc07a3 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 3 Oct 2009 20:04:45 +0000 Subject: [PATCH] Fix assorted memory leaks in pg_hba.conf parsing. Over a sufficiently large number of SIGHUP cycles, these would have run the postmaster out of memory. Noted while testing memory-leak scenario in postgresql.conf configuration-change-printing patch. --- src/backend/libpq/hba.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 27e0c431ca..d5f44bb49f 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.188 2009/06/24 13:39:42 mha Exp $ + * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.188.2.1 2009/10/03 20:04:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -710,6 +710,8 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline) line_num, HbaFileName))); return false; } + + /* need a modifiable copy of token */ token = pstrdup(lfirst(line_item)); /* Check if it has a CIDR suffix and if so isolate it */ @@ -736,16 +738,12 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline) token, gai_strerror(ret)), errcontext("line %d of configuration file \"%s\"", line_num, HbaFileName))); - if (cidr_slash) - *cidr_slash = '/'; if (gai_result) pg_freeaddrinfo_all(hints.ai_family, gai_result); + pfree(token); return false; } - if (cidr_slash) - *cidr_slash = '/'; - memcpy(&parsedline->addr, gai_result->ai_addr, gai_result->ai_addrlen); pg_freeaddrinfo_all(hints.ai_family, gai_result); @@ -755,18 +753,22 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline) if (pg_sockaddr_cidr_mask(&parsedline->mask, cidr_slash + 1, parsedline->addr.ss_family) < 0) { + *cidr_slash = '/'; /* restore token for message */ ereport(LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("invalid CIDR mask in address \"%s\"", token), errcontext("line %d of configuration file \"%s\"", line_num, HbaFileName))); + pfree(token); return false; } + pfree(token); } else { /* Read the mask field. */ + pfree(token); line_item = lnext(line_item); if (!line_item) { @@ -1253,7 +1255,7 @@ load_role(void) } /* - * Free the contents of a hba record + * Free an HbaLine structure */ static void free_hba_record(HbaLine *record) @@ -1262,6 +1264,8 @@ free_hba_record(HbaLine *record) pfree(record->database); if (record->role) pfree(record->role); + if (record->usermap) + pfree(record->usermap); if (record->pamservice) pfree(record->pamservice); if (record->ldapserver) @@ -1274,6 +1278,7 @@ free_hba_record(HbaLine *record) pfree(record->krb_server_hostname); if (record->krb_realm) pfree(record->krb_realm); + pfree(record); } /* @@ -1342,20 +1347,22 @@ load_hba(void) { /* Parse error in the file, so indicate there's a problem */ free_hba_record(newline); - pfree(newline); + ok = false; /* * Keep parsing the rest of the file so we can report errors on * more than the first row. Error has already been reported in the * parsing function, so no need to log it here. */ - ok = false; continue; } new_parsed_lines = lappend(new_parsed_lines, newline); } + /* Free the temporary lists */ + free_lines(&hba_lines, &hba_line_nums); + if (!ok) { /* Parsing failed at one or more rows, so bail out */ @@ -1367,9 +1374,6 @@ load_hba(void) clean_hba_list(parsed_hba_lines); parsed_hba_lines = new_parsed_lines; - /* Free the temporary lists */ - free_lines(&hba_lines, &hba_line_nums); - return true; }