I wrote:
Looking at the code I see this in dbdimp.c:

           strncpy(buffer, tempbuf, strlen(tempbuf)+1);
           buffer[strlen(tempbuf)] = '\0';
However, there is no check that buffer has enough space - the code just seems to assume it, which seems like a bug - that code is probably clobbering something important. I don't quite understand why we don't simply make an SV straight from tmpbuf, rather than copying to a fixed buffer anyway. PQgetCopyData() doesn't require a length param (unlike the now deprecated PQgetline()), and it seems very un-perlish for us to require it of the user at all.




Here is an untested patch that will grow the buffer as needed, I hope. It doesn't make the length param go away, but it makes it mostly irrelevant :-)

cheers

andrew
--- dbdimp.c.orig       2006-12-28 11:05:08.000000000 -0500
+++ dbdimp.c    2006-12-28 11:18:17.000000000 -0500
@@ -2794,14 +2794,15 @@
 
 /* ================================================================== */
 int
-pg_db_getline (dbh, buffer, length)
+pg_db_getline (dbh, svbuf, length)
                SV * dbh;
-               char * buffer;
+               SV * svbuf;
                int length;
 {
                D_imp_dbh(dbh);
                int copystatus;
                char * tempbuf;
+               char * buffer = SvPV_nolen(svbuf);
 
                if (dbis->debug >= 4)
                        (void)PerlIO_printf(DBILOGFP, "dbdpg: pg_db_getline\n");
@@ -2838,6 +2839,7 @@
                        pg_error(dbh, PGRES_FATAL_ERROR, 
PQerrorMessage(imp_dbh->conn));
                }
                else {
+                   buffer = SvGROW(svbuf, strlen(tempbuf)+1);
                        strncpy(buffer, tempbuf, strlen(tempbuf)+1);
                        buffer[strlen(tempbuf)] = '\0';
                        PQfreemem(tempbuf);
--- dbdimp.h.orig       2006-04-26 23:34:51.000000000 -0400
+++ dbdimp.h    2006-12-28 11:19:39.000000000 -0500
@@ -102,7 +102,7 @@
 int dbd_db_getfd (SV *dbh, imp_dbh_t *imp_dbh);
 SV * dbd_db_pg_notifies (SV *dbh, imp_dbh_t *imp_dbh);
 int pg_db_putline (SV *dbh, const char *buffer);
-int pg_db_getline (SV *dbh, char *buffer, int length);
+int pg_db_getline (SV *dbh, SV *svbuf, int length);
 int pg_db_endcopy (SV * dbh);
 void pg_db_pg_server_trace (SV *dbh, FILE *fh);
 void pg_db_pg_server_untrace (SV *dbh);
--- Pg.xs.orig  2006-12-28 11:04:55.000000000 -0500
+++ Pg.xs       2006-12-28 11:13:31.000000000 -0500
@@ -406,7 +406,7 @@
                buf = SvGROW(bufsv, 3);
                if (len > 3)
                        buf = SvGROW(bufsv, len);
-               ret = pg_db_getline(dbh, buf, (int)len);
+               ret = pg_db_getline(dbh, bufsv, (int)len);
                sv_setpv((SV*)ST(1), buf);
                SvSETMAGIC(ST(1));
                ST(0) = (-1 != ret) ? &sv_yes : &sv_no;

Reply via email to