Skip to content

Commit 98907a9

Browse files
committed
Merge branch 'PHP-5.4' into PHP-5.5
* PHP-5.4: Fix #62479: Some chars not parsed in passwords
2 parents 767e6d2 + da83b51 commit 98907a9

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

ext/pdo_pgsql/pgsql_driver.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,7 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_
10391039
pdo_pgsql_db_handle *H;
10401040
int ret = 0;
10411041
char *conn_str, *p, *e;
1042+
char *tmp_pass;
10421043
long connect_timeout = 30;
10431044

10441045
H = pecalloc(1, sizeof(pdo_pgsql_db_handle), dbh->is_persistent);
@@ -1060,18 +1061,44 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_
10601061
connect_timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, 30 TSRMLS_CC);
10611062
}
10621063

1064+
if (dbh->password) {
1065+
if (dbh->password[0] != '\'' && dbh->password[strlen(dbh->password) - 1] != '\'') {
1066+
char *pwd = dbh->password;
1067+
int pos = 1;
1068+
1069+
tmp_pass = safe_emalloc(2, strlen(dbh->password), 3);
1070+
tmp_pass[0] = '\'';
1071+
1072+
while (*pwd != '\0') {
1073+
if (*pwd == '\\' || *pwd == '\'') {
1074+
tmp_pass[pos++] = '\\';
1075+
}
1076+
1077+
tmp_pass[pos++] = *pwd++;
1078+
}
1079+
1080+
tmp_pass[pos++] = '\'';
1081+
tmp_pass[pos] = '\0';
1082+
} else {
1083+
tmp_pass = dbh->password;
1084+
}
1085+
}
1086+
10631087
/* support both full connection string & connection string + login and/or password */
10641088
if (dbh->username && dbh->password) {
1065-
spprintf(&conn_str, 0, "%s user=%s password=%s connect_timeout=%ld", dbh->data_source, dbh->username, dbh->password, connect_timeout);
1089+
spprintf(&conn_str, 0, "%s user=%s password=%s connect_timeout=%ld", dbh->data_source, dbh->username, tmp_pass, connect_timeout);
10661090
} else if (dbh->username) {
10671091
spprintf(&conn_str, 0, "%s user=%s connect_timeout=%ld", dbh->data_source, dbh->username, connect_timeout);
10681092
} else if (dbh->password) {
1069-
spprintf(&conn_str, 0, "%s password=%s connect_timeout=%ld", dbh->data_source, dbh->password, connect_timeout);
1093+
spprintf(&conn_str, 0, "%s password=%s connect_timeout=%ld", dbh->data_source, tmp_pass, connect_timeout);
10701094
} else {
10711095
spprintf(&conn_str, 0, "%s connect_timeout=%ld", (char *) dbh->data_source, connect_timeout);
10721096
}
10731097

10741098
H->server = PQconnectdb(conn_str);
1099+
if (dbh->password && tmp_pass != dbh->password) {
1100+
efree(tmp_pass);
1101+
}
10751102

10761103
efree(conn_str);
10771104

ext/pdo_pgsql/tests/bug62479.phpt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
--TEST--
2+
PDO PgSQL Bug #62479 (PDO-psql cannot connect if password contains spaces)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
6+
require dirname(__FILE__) . '/config.inc';
7+
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
8+
PDOTest::skip();
9+
if (!isset($conf['ENV']['PDOTEST_DSN'])) die('no dsn found in env');
10+
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
11+
$rand = rand(5, 5);
12+
13+
// Assume that if we can't create a user, this test needs to be skipped
14+
$testQuery = "CREATE USER pdo_$rand WITH PASSWORD 'testpass'";
15+
$db->query($testQuery);
16+
$testQuery = "DROP USER pdo_$rand";
17+
$db->query($testQuery);
18+
?>
19+
--FILE--
20+
<?php
21+
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
22+
$pdo = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
23+
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
24+
$rand = rand(5, 400);
25+
$user = "pdo_$rand";
26+
$template = "CREATE USER $user WITH PASSWORD '%s'";
27+
$dropUser = "DROP USER $user";
28+
$testQuery = 'SELECT 1 as verification';
29+
30+
// Create temp user with space in password
31+
$sql = sprintf($template, 'my password');
32+
$pdo->query($sql);
33+
$testConn = new PDO($_ENV['PDOTEST_DSN'], $user, "my password");
34+
$result = $testConn->query($testQuery)->fetch();
35+
$check = $result[0];
36+
var_dump($check);
37+
38+
// Remove the user
39+
$pdo->query($dropUser);
40+
41+
// Create a user with a space and single quote
42+
$sql = sprintf($template, "my pass''word");
43+
$pdo->query($sql);
44+
45+
$testConn = new PDO($_ENV['PDOTEST_DSN'], $user, "my pass'word");
46+
$result = $testConn->query($testQuery)->fetch();
47+
$check = $result[0];
48+
var_dump($check);
49+
50+
// Remove the user
51+
$pdo->query($dropUser);
52+
?>
53+
--EXPECT--
54+
int(1)
55+
int(1)
56+

0 commit comments

Comments
 (0)