Fix PQsetvalue() to avoid possible crash when adding a new tuple.
authorTom Lane <[email protected]>
Thu, 21 Jul 2011 16:24:14 +0000 (12:24 -0400)
committerTom Lane <[email protected]>
Thu, 21 Jul 2011 16:25:14 +0000 (12:25 -0400)
PQsetvalue unnecessarily duplicated the logic in pqAddTuple, and didn't
duplicate it exactly either --- pqAddTuple does not care what is in the
tuple-pointer array positions beyond the last valid entry, whereas the
code in PQsetvalue assumed such positions would contain NULL.  This led
to possible crashes if PQsetvalue was applied to a PGresult that had
previously been enlarged with pqAddTuple, for instance one built from a
server query.  Fix by relying on pqAddTuple instead of duplicating logic,
and not assuming anything about the contents of res->tuples[res->ntups].

Back-patch to 8.4, where PQsetvalue was introduced.

Andrew Chernow

src/interfaces/libpq/fe-exec.c

index c00f5eae6ab1b005a737a05e5cda5abbe27604bc..30c2654827c4e29209d196688f2b16580a0f9f30 100644 (file)
@@ -422,28 +422,8 @@ PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len)
    if (tup_num < 0 || tup_num > res->ntups)
        return FALSE;
 
-   /* need to grow the tuple table? */
-   if (res->ntups >= res->tupArrSize)
-   {
-       int         n = res->tupArrSize ? res->tupArrSize * 2 : 128;
-       PGresAttValue **tups;
-
-       if (res->tuples)
-           tups = (PGresAttValue **) realloc(res->tuples, n * sizeof(PGresAttValue *));
-       else
-           tups = (PGresAttValue **) malloc(n * sizeof(PGresAttValue *));
-
-       if (!tups)
-           return FALSE;
-
-       memset(tups + res->tupArrSize, 0,
-              (n - res->tupArrSize) * sizeof(PGresAttValue *));
-       res->tuples = tups;
-       res->tupArrSize = n;
-   }
-
    /* need to allocate a new tuple? */
-   if (tup_num == res->ntups && !res->tuples[tup_num])
+   if (tup_num == res->ntups)
    {
        PGresAttValue *tup;
        int         i;
@@ -462,8 +442,9 @@ PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len)
            tup[i].value = res->null_field;
        }
 
-       res->tuples[tup_num] = tup;
-       res->ntups++;
+       /* add it to the array */
+       if (!pqAddTuple(res, tup))
+           return FALSE;
    }
 
    attval = &res->tuples[tup_num][field_num];