Hi,

I've tracked down a segfault in DBD::Pg 2.6.1, and I've got a patch.

Version: DBD-Pg-2.6.1 (also had problem with DBD-Pg-2.1.3)
Other versions: Perl-5.8.8, DBI-1.602
System: CentOS release 5 (Final), Linux centos5.drh.net 2.6.18-8.el5

With this perl code:

>>>
$dbh->do(q[ COPY ( SELECT * FROM table_with_no_rows ) TO STDOUT WITH DELIMITER ',' ]);
        my $data;
        my $last = 0;
        while ( ! $last )
        {
            $last = $dbh->pg_getcopydata($data) == -1;

            # do stuff.
        }
<<<

I got a segfault from pg_getcopydata when the query returned no rows. It worked fine when the query did return rows.

Here's the info from gdb on the segfault:

>>>
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1208076608 (LWP 24340)]
0x00f8bb56 in pg_db_getcopydata (dbh=0x8ca9534, dataline=0x8de7320, async=0) at dbdimp.c:3672
3672                    SvCUR_set(dataline, 0);
(gdb) p dataline
$1 = (SV *) 0x8de7320
(gdb) p *dataline
$2 = {sv_any = 0x0, sv_refcnt = 1, sv_flags = 1280}
<<<

Here's the patch:

>>>
--- DBD-Pg-2.6.1.orig/dbdimp.c  2008-04-22 12:56:32.000000000 -0500
+++ DBD-Pg-2.6.1/dbdimp.c       2008-04-30 05:03:22.000000000 -0500
@@ -3664,7 +3664,7 @@
        else if (-1 == copystatus) {
                PGresult * result;
                ExecStatusType status;
-               SvCUR_set(dataline, 0);
+               sv_setpv(dataline, "");
                imp_dbh->copystate=0;
                TRACE_PQGETRESULT;
                result = PQgetResult(imp_dbh->conn);
<<<

If pg_getcopydata is called and the buffer variable is a freshly defined variable and copystatus == -1, then the SvCUR_set call segfaults because there is no string component allocated for this SV, so the length of the string component can't be set to zero. I changed to using the sv_setpv() call to just set it to a zero length string. This fixes the segfault in my case.

I'm not a perl internals expert, so you might want to double check this.

Thanks!

David


Reply via email to