Browse Source

Fixed bug #50323 (Allow use of ; in values via ;; in PDO DSN even in the middle of a string).

PHP-5.2.1RC1
Pierrick Charron 17 years ago
parent
commit
fcf959ad3e
  1. 3
      NEWS
  2. 40
      ext/pdo/pdo.c
  3. 61
      ext/pdo_mysql/tests/bug_50323.phpt

3
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)

40
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;

61
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!
Loading…
Cancel
Save