Subject: | core dump in DBD-mysql-4.009 |
Date: | Wed, 22 Oct 2008 14:18:59 -0700 |
To: | bug-DBD-mysql [...] rt.cpan.org |
From: | Neil Katin <cpan [...] askneil.com> |
Hi there. I found a core dump problem in DBD-mysql. It happens in 4.009, as
well as earlier versions.
The problem is an uninitialized variable in dbdimp.c/dbd_bind_ph().
The slen variable is uninitialized, and if the SQL type is specified
and translated as a MYSQL_TYPE_BLOB this uninitialized value is saved
in the buffer_length bind parameter variable.
I had trouble coming up with a small test case, since it depends on the
stack parameters, but you can see a random length being passed into
libmysqlclient (if you have debugging turned on and MYSQL_DEBUG set...)
I wasn't sure if the length had to be set on integer/double parameters,
so I set it anyway.
The key line is this one:
! if (buffer_type == MYSQL_TYPE_STRING || buffer_type == MYSQL_TYPE_BLOB)
Although, not debug printing the entire blob seemed reasonable a few lines below
that one (it is already printed at the start of the routine...)
Here's the patch I used to fix the problem:
*** DBD-mysql-4.009/dbdimp.c 2008-10-21 20:50:22.000000000 -0400
--- DBD-mysql-4.009-fixed/dbdimp.c 2008-10-22 16:25:24.000000000 -0400
***************
*** 4278,4283 ****
--- 4278,4284 ----
PerlIO_printf(DBILOGFP, "\t\tTRY TO BIND AN INT NUMBER\n");
buffer_type= MYSQL_TYPE_LONG;
+ buffer_length = sizeof imp_sth->fbind[idx].numeric_val.lval;
imp_sth->fbind[idx].numeric_val.lval= SvIV(imp_sth->params[idx].value);
buffer=(void*)&(imp_sth->fbind[idx].numeric_val.lval);
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
***************
*** 4294,4299 ****
--- 4295,4301 ----
PerlIO_printf(DBILOGFP, "\t\tTRY TO BIND A FLOAT NUMBER\n");
buffer_type= MYSQL_TYPE_DOUBLE;
+ buffer_length = sizeof imp_sth->fbind[idx].numeric_val.dval;
imp_sth->fbind[idx].numeric_val.dval= SvNV(imp_sth->params[idx].value);
buffer=(char*)&(imp_sth->fbind[idx].numeric_val.dval);
***************
*** 4320,4333 ****
break;
}
! if (buffer_type == MYSQL_TYPE_STRING)
{
buffer= SvPV(imp_sth->params[idx].value, slen);
buffer_length= slen;
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
PerlIO_printf(DBILOGFP,
! " SCALAR type %d ->%s<- IS A STRING\n",
! sql_type, buffer);
}
}
else
--- 4322,4335 ----
break;
}
! if (buffer_type == MYSQL_TYPE_STRING || buffer_type == MYSQL_TYPE_BLOB)
{
buffer= SvPV(imp_sth->params[idx].value, slen);
buffer_length= slen;
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
PerlIO_printf(DBILOGFP,
! " SCALAR type %d ->length %d<- IS A STRING or BLOB\n",
! sql_type, buffer_length);
}
}
else