]> granicus.if.org Git - postgresql/commitdiff
Fix assorted memory leaks in pg_hba.conf parsing. Over a sufficiently
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 3 Oct 2009 20:04:45 +0000 (20:04 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 3 Oct 2009 20:04:45 +0000 (20:04 +0000)
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

index 27e0c431ca8ba3df4742558f7487a1efaa73cf50..d5f44bb49f61ec141c1f8e1221a4002d5140b8d3 100644 (file)
@@ -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;
 }