]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Avoid memory leak on error while parsing pg_stat_statements dump file
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 27 Mar 2026 10:20:38 +0000 (12:20 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 27 Mar 2026 10:21:38 +0000 (12:21 +0200)
By using palloc() instead of raw malloc().

Reported-by: Gaurav Singh <gaurav.singh@yugabyte.com>
Reviewed-by: Lukas Fittl <lukas@fittl.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://www.postgresql.org/message-id/CAEcQ1bYR9s4eQLFDjzzJHU8fj-MTbmRpW-9J-r2gsCn+HEsynw@mail.gmail.com
Backpatch-through: 14

contrib/pg_stat_statements/pg_stat_statements.c

index c5c4edce4236274865fde84b0a44579f0f37299d..2030cb12217b814da3cd90a4f42ac8bc062cf84f 100644 (file)
@@ -791,7 +791,7 @@ pgss_shmem_shutdown(int code, Datum arg)
        if (fwrite(&pgss->stats, sizeof(pgssGlobalStats), 1, file) != 1)
                goto error;
 
-       free(qbuffer);
+       pfree(qbuffer);
        qbuffer = NULL;
 
        if (FreeFile(file))
@@ -815,7 +815,8 @@ error:
                        (errcode_for_file_access(),
                         errmsg("could not write file \"%s\": %m",
                                        PGSS_DUMP_FILE ".tmp")));
-       free(qbuffer);
+       if (qbuffer)
+               pfree(qbuffer);
        if (file)
                FreeFile(file);
        unlink(PGSS_DUMP_FILE ".tmp");
@@ -1761,7 +1762,8 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
                        pgss->extent != extent ||
                        pgss->gc_count != gc_count)
                {
-                       free(qbuffer);
+                       if (qbuffer)
+                               pfree(qbuffer);
                        qbuffer = qtext_load_file(&qbuffer_size);
                }
        }
@@ -1962,7 +1964,8 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
 
        LWLockRelease(pgss->lock);
 
-       free(qbuffer);
+       if (qbuffer)
+               pfree(qbuffer);
 }
 
 /* Number of output arguments (columns) for pg_stat_statements_info */
@@ -2269,7 +2272,7 @@ error:
 }
 
 /*
- * Read the external query text file into a malloc'd buffer.
+ * Read the external query text file into a palloc'd buffer.
  *
  * Returns NULL (without throwing an error) if unable to read, eg
  * file not there or insufficient memory.
@@ -2311,7 +2314,7 @@ qtext_load_file(Size *buffer_size)
 
        /* Allocate buffer; beware that off_t might be wider than size_t */
        if (stat.st_size <= MaxAllocHugeSize)
-               buf = (char *) malloc(stat.st_size);
+               buf = (char *) palloc_extended(stat.st_size, MCXT_ALLOC_HUGE | MCXT_ALLOC_NO_OOM);
        else
                buf = NULL;
        if (buf == NULL)
@@ -2350,7 +2353,7 @@ qtext_load_file(Size *buffer_size)
                                                (errcode_for_file_access(),
                                                 errmsg("could not read file \"%s\": %m",
                                                                PGSS_TEXT_FILE)));
-                       free(buf);
+                       pfree(buf);
                        CloseTransientFile(fd);
                        return NULL;
                }
@@ -2565,7 +2568,7 @@ gc_qtexts(void)
        else
                pgss->mean_query_len = ASSUMED_LENGTH_INIT;
 
-       free(qbuffer);
+       pfree(qbuffer);
 
        /*
         * OK, count a garbage collection cycle.  (Note: even though we have
@@ -2582,7 +2585,8 @@ gc_fail:
        /* clean up resources */
        if (qfile)
                FreeFile(qfile);
-       free(qbuffer);
+       if (qbuffer)
+               pfree(qbuffer);
 
        /*
         * Since the contents of the external file are now uncertain, mark all