[DBD::Pg 3/6] Per report, fix problem with undefined elements in an array being passed as arguments. Lesson here: av_fetch cannot be trusted, always test it first! Also added a failing (but now passing) test.
dbdpg-commits-gENoVmVU/[email protected] Sat, 10 Mar 2012 22:25:23 -0500
| Newsgroups | gmane.comp.db.postgresql.dbdpg.cvs |
|---|---|
| Message-ID | <[email protected]> |
Committed by Greg Sabino Mullane <greg-O9fzpki4YnJWk0Htik3J/[email protected]> Subject: [DBD::Pg 3/6] Per report, fix problem with undefined elements in an array being passed as arguments. Lesson here: av_fetch cannot be trusted, always test it first! Also added a failing (but now passing) test. --- dbdimp.c | 56 +++++++++++++++++++++++++++++++++++--------------------- t/03dbmethod.t | 18 ++++++++++++++++-- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/dbdimp.c b/dbdimp.c index 1931f25..175ed97 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -2463,7 +2463,16 @@ SV * pg_stringify_array(SV *input, const char * array_delim, int server_version) done = 0; currarr = lastarr = toparr; + + /* We want to walk through to find out the depth */ while (!done) { + + /* If we come across a null, we are done */ + if (! av_exists(currarr, 0)) { + done = 1; + break; + } + /* Grab the first item of the current array */ svitem = *av_fetch(currarr, 0, 0); @@ -2509,30 +2518,35 @@ SV * pg_stringify_array(SV *input, const char * array_delim, int server_version) sv_catpv(value, "{"); } for (yz=0; yz < array_items; yz++) { - svitem = *av_fetch(currarr, yz, 0); - - if (SvROK(svitem)) - croak("Arrays must contain only scalars and other arrays"); - - if (!SvOK(svitem)) { /* Insert NULL if we can */ - /* Only version 8.2 and up can handle NULLs in arrays */ - if (server_version < 80200) - croak("Cannot use NULLs in arrays until version 8.2"); - sv_catpv(value, "NULL"); /* Beware of array_nulls config param! */ + if (! av_exists(currarr, yz)) { + sv_catpv(value, "NULL"); } else { - sv_catpv(value, "\""); - if (SvUTF8(svitem)) - SvUTF8_on(value); - string = SvPV(svitem, stringlength); - while (stringlength--) { - /* Escape backslashes and double-quotes. */ - if ('\"' == *string || '\\' == *string) - sv_catpvn(value, "\\", 1); - sv_catpvn(value, string, 1); - string++; + svitem = *av_fetch(currarr, yz, 0); + + if (SvROK(svitem)) + croak("Arrays must contain only scalars and other arrays"); + + if (!SvOK(svitem)) { /* Insert NULL if we can */ + /* Only version 8.2 and up can handle NULLs in arrays */ + if (server_version < 80200) + croak("Cannot use NULLs in arrays until version 8.2"); + sv_catpv(value, "NULL"); /* Beware of array_nulls config param! */ + } + else { + sv_catpv(value, "\""); + if (SvUTF8(svitem)) + SvUTF8_on(value); + string = SvPV(svitem, stringlength); + while (stringlength--) { + /* Escape backslashes and double-quotes. */ + if ('\"' == *string || '\\' == *string) + sv_catpvn(value, "\\", 1); + sv_catpvn(value, string, 1); + string++; + } + sv_catpv(value, "\""); } - sv_catpv(value, "\""); } if (yz < array_items-1) diff --git a/t/03dbmethod.t b/t/03dbmethod.t index 6f35e1b..9bcb2ba 100644 --- a/t/03dbmethod.t +++ b/t/03dbmethod.t @@ -26,7 +26,7 @@ my $dbh = connect_database(); if (! $dbh) { plan skip_all => 'Connection to database failed, cannot continue testing'; } -plan tests => 532; +plan tests => 534; isnt ($dbh, undef, 'Connect to database for database handle method testing'); @@ -103,12 +103,26 @@ eval { }; like ($@, qr{last_insert_id}, $t); -$t='DB handle method "do()" returns correct count with CREATE AS SELECT'; +$t='DB handle method "do" returns correct count with CREATE AS SELECT'; $dbh->rollback(); $result = $dbh->do('CREATE TEMP TABLE foobar AS SELECT * FROM pg_class LIMIT 3'); $expected = $pgversion >= 90000 ? 3 : '0E0'; is ($result, $expected, $t); +$t='DB handle method "do" works properly with passed-in array with undefined entries'; +$dbh->rollback(); +$dbh->do('CREATE TEMP TABLE foobar (id INT, p TEXT[])'); +my @aa; +$aa[2] = 'asasa'; +eval { + $dbh->do('INSERT INTO foobar (p) VALUES (?)', undef, \@aa); +}; +is ($@, q{}, $t); + +$SQL = 'SELECT * FROM foobar'; +$result = $dbh->selectall_arrayref($SQL)->[0]; +is_deeply ($result, [undef,[undef,undef,'asasa']], $t); + $t='DB handle method "last_insert_id" works when given a valid sequence and an invalid table'; $dbh->rollback(); eval { -- 1.7.1