]> granicus.if.org Git - postgresql/commitdiff
Fix PQsetvalue() to avoid possible crash when adding a new tuple.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 21 Jul 2011 16:24:14 +0000 (12:24 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 21 Jul 2011 16:24:48 +0000 (12:24 -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 83c5ea363fc8da5d659bb45203063309297aca38..605d242809298489dcee86700652d318ba027fa7 100644 (file)
@@ -424,28 +424,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;
@@ -464,8 +444,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];