develooper Front page | perl.dbd.pg.changes | Postings from March 2012

[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.

Thread Previous | Thread Next
From:
dbdpg-commits
Date:
March 12, 2012 04:33
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.
Message ID:
1331436326-15937-3-git-send-email-dbdpg-commits@bucardo.org
Committed by Greg Sabino Mullane <greg@endpoint.com>

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


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About