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;