Fix ancient bug of pool_push() and friends.
authorTatsuo Ishii <ishii@postgresql.org>
Thu, 3 Sep 2015 01:28:29 +0000 (10:28 +0900)
committerTatsuo Ishii <ishii@postgresql.org>
Thu, 3 Sep 2015 01:59:08 +0000 (10:59 +0900)
It allocates buffer using realloc and uses the pointer
returned. However it does the pointer calculation *before* realloc
gets called. So the calculation uses the old pointer value, which
causes various problems including segfault later. It is surprising
that this bug was not found earlier because the bug was there since
the function was added. This is probably due to the fact that actual
pointer moving does not happen until certain amount of memory.

Also there were other problems with it. The buffer pointer and buffer
size variable is not initialized. The buffer is not freed by
pool_close. Typo in debugging message (3.4 or later only). They are
fixed as well.

pool_stream.c

index 91c5d932964b4918aae26d5f7b23d58999cc1e97..ef291713a841a765b12ba2360f4133d5ca47747f 100644 (file)
@@ -5,7 +5,7 @@
 * pgpool: a language independent connection pool server for PostgreSQL
 * written by Tatsuo Ishii
 *
-* Copyright (c) 2003-2013      PgPool Global Development Group
+* Copyright (c) 2003-2015      PgPool Global Development Group
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby
@@ -89,6 +89,8 @@ POOL_CONNECTION *pool_open(int fd)
        cp->sbufsz = 0;
        cp->buf2 = NULL;
        cp->bufsz2 = 0;
+       cp->buf3 = NULL;
+       cp->bufsz3 = 0;
 
        cp->fd = fd;
        return cp;
@@ -112,6 +114,8 @@ void pool_close(POOL_CONNECTION *cp)
                free(cp->sbuf);
        if (cp->buf2)
                free(cp->buf2);
+       if (cp->buf3)
+               free(cp->buf3);
        pool_discard_params(&cp->params);
 
        pool_ssl_close(cp);
@@ -879,8 +883,8 @@ int pool_push(POOL_CONNECTION *cp, void *data, int len)
        }
        else
        {
-               p = cp->buf3 + cp->bufsz3;
                cp->buf3 = realloc(cp->buf3, cp->bufsz3 + len);
+               p = cp->buf3 + cp->bufsz3;
        }
 
        memcpy(p, data, len);