summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierrick Charron <pierrick@php.net>2009-12-06 21:32:58 +0000
committerPierrick Charron <pierrick@php.net>2009-12-06 21:32:58 +0000
commitfcf959ad3e1afee61b1a0cb4a0bec13e69a8f259 (patch)
tree631f65066890774e98a37623cbe13f59dda86630
parentc21c2da229a96a0b260a191a77a827026c5f8a5c (diff)
downloadphp-git-fcf959ad3e1afee61b1a0cb4a0bec13e69a8f259.tar.gz
Fixed bug #50323 (Allow use of ; in values via ;; in PDO DSN even in the middle of a string).
-rw-r--r--NEWS3
-rwxr-xr-xext/pdo/pdo.c40
-rw-r--r--ext/pdo_mysql/tests/bug_50323.phpt61
3 files changed, 99 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index 2a502d7295..3493af4b29 100644
--- a/NEWS
+++ b/NEWS
@@ -10,7 +10,8 @@ PHP NEWS
- Fixed bug #50345 (nanosleep not detected properly on some solaris versions).
(Jani)
-- Fixed bug #50323 (Allow use of ; in values via ;; in PDO DSN). (Ilia)
+- Fixed bug #50323 (Allow use of ; in values via ;; in PDO DSN).
+ (Ilia, Pierrick)
- Fixed bug #50266 (conflicting types for llabs). (Jani)
- Fixed bug #50168 (FastCGI fails with wrong error on HEAD request to
non-existent file). (Dmitry)
diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c
index 3187543187..f9fd689d3c 100755
--- a/ext/pdo/pdo.c
+++ b/ext/pdo/pdo.c
@@ -217,6 +217,7 @@ PDO_API int php_pdo_parse_data_source(const char *data_source,
int optstart = 0;
int nlen;
int n_matches = 0;
+ int n_semicolumns = 0;
i = 0;
while (i < data_source_len) {
@@ -235,14 +236,21 @@ PDO_API int php_pdo_parse_data_source(const char *data_source,
/* now we're looking for VALUE; or just VALUE<NUL> */
semi = -1;
+ n_semicolumns = 0;
while (i < data_source_len) {
if (data_source[i] == '\0') {
semi = i++;
break;
}
- if (data_source[i] == ';' && ((i + 1 >= data_source_len) || data_source[i+1] != ';')) {
- semi = i++;
- break;
+ if (data_source[i] == ';') {
+ if ((i + 1 >= data_source_len) || data_source[i+1] != ';') {
+ semi = i++;
+ break;
+ } else {
+ n_semicolumns++;
+ i += 2;
+ continue;
+ }
}
++i;
}
@@ -259,7 +267,31 @@ PDO_API int php_pdo_parse_data_source(const char *data_source,
if (parsed[j].freeme) {
efree(parsed[j].optval);
}
- parsed[j].optval = estrndup(data_source + valstart, semi - valstart);
+
+ if (n_semicolumns == 0) {
+ parsed[j].optval = estrndup(data_source + valstart, semi - valstart - n_semicolumns);
+ } else {
+ int vlen = semi - valstart;
+ char *orig_val = data_source + valstart;
+ char *new_val = (char *) emalloc(vlen - n_semicolumns + 1);
+
+ parsed[j].optval = new_val;
+
+ while (vlen && *orig_val) {
+ *new_val = *orig_val;
+ new_val++;
+
+ if (*orig_val == ';') {
+ orig_val+=2;
+ vlen-=2;
+ } else {
+ orig_val++;
+ vlen--;
+ }
+ }
+ *new_val = '\0';
+ }
+
parsed[j].freeme = 1;
++n_matches;
break;
diff --git a/ext/pdo_mysql/tests/bug_50323.phpt b/ext/pdo_mysql/tests/bug_50323.phpt
new file mode 100644
index 0000000000..02050fac5d
--- /dev/null
+++ b/ext/pdo_mysql/tests/bug_50323.phpt
@@ -0,0 +1,61 @@
+--TEST--
+Bug #50323 (No ability to connect to database named 't;', no chance to escape semicolon)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_mysql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+ function changeDSN($original, $new_options) {
+ $old_options = array();
+ $dsn = substr($original,
+ strpos($original, ':') + 1,
+ strlen($original));
+
+ // no real parser - any excotic setting can fool us
+ $parts = explode(';', $dsn);
+ foreach ($parts as $k => $v) {
+ $tmp = explode('=', $v);
+ if (count($tmp) == 2)
+ $old_options[$tmp[0]] = $tmp[1];
+ }
+
+ $options = $old_options;
+ foreach ($new_options as $k => $v)
+ $options[$k] = $v;
+
+ $dsn = 'mysql:';
+ foreach ($options as $k => $v)
+ $dsn .= sprintf('%s=%s;', $k, $v);
+
+ $dsn = substr($dsn, 0, strlen($dsn) -1);
+
+ return $dsn;
+ }
+
+
+if (1 === @$db->exec('CREATE DATABASE `crazy;dbname`')) {
+ $dsn = changeDSN(getenv('PDOTEST_DSN'), array('dbname' => 'crazy;;dbname'));
+ $user = getenv('PDOTEST_USER');
+ $pass = getenv('PDOTEST_PASS');
+
+ new PDO($dsn, $user, $pass);
+}
+echo 'done!';
+?>
+--CLEAN--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+@$db->exec('DROP DATABASE IF EXISTS `crazy;dbname`');
+?>
+--EXPECTF--
+done!
+