-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Fix GH-12296: [odbc] [pdo_odbc] Optimized odbc connection string creating #12306
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f5a990d
797ceec
7bb69d0
96faed4
ad06797
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2095,32 +2095,56 @@ int odbc_sqlconnect(odbc_connection **conn, char *db, char *uid, char *pwd, int | |
/* a connection string may have = but not ; - i.e. "DSN=PHP" */ | ||
if (strstr((char*)db, "=")) { | ||
direct = 1; | ||
|
||
/* This should be identical to the code in the PDO driver and vice versa. */ | ||
size_t db_len = strlen(db); | ||
char *db_end = db + db_len; | ||
bool use_uid_arg = uid != NULL && !php_memnistr(db, "uid=", strlen("uid="), db_end); | ||
bool use_pwd_arg = pwd != NULL && !php_memnistr(db, "pwd=", strlen("pwd="), db_end); | ||
|
||
/* Force UID and PWD to be set in the DSN */ | ||
bool is_uid_set = uid && *uid | ||
&& !strstr(db, "uid=") | ||
&& !strstr(db, "UID="); | ||
bool is_pwd_set = pwd && *pwd | ||
&& !strstr(db, "pwd=") | ||
&& !strstr(db, "PWD="); | ||
if (is_uid_set && is_pwd_set) { | ||
if (use_uid_arg || use_pwd_arg) { | ||
db_end--; | ||
if ((unsigned char)*(db_end) == ';') { | ||
*db_end = '\0'; | ||
} | ||
|
||
char *uid_quoted = NULL, *pwd_quoted = NULL; | ||
bool should_quote_uid = !php_odbc_connstr_is_quoted(uid) && php_odbc_connstr_should_quote(uid); | ||
bool should_quote_pwd = !php_odbc_connstr_is_quoted(pwd) && php_odbc_connstr_should_quote(pwd); | ||
if (should_quote_uid) { | ||
size_t estimated_length = php_odbc_connstr_estimate_quote_length(uid); | ||
uid_quoted = emalloc(estimated_length); | ||
php_odbc_connstr_quote(uid_quoted, uid, estimated_length); | ||
} else { | ||
uid_quoted = uid; | ||
bool should_quote_uid, should_quote_pwd; | ||
if (use_uid_arg) { | ||
should_quote_uid = !php_odbc_connstr_is_quoted(uid) && php_odbc_connstr_should_quote(uid); | ||
if (should_quote_uid) { | ||
size_t estimated_length = php_odbc_connstr_estimate_quote_length(uid); | ||
uid_quoted = emalloc(estimated_length); | ||
php_odbc_connstr_quote(uid_quoted, uid, estimated_length); | ||
} else { | ||
uid_quoted = uid; | ||
} | ||
|
||
if (!use_pwd_arg) { | ||
spprintf(&ldb, 0, "%s;UID=%s;", db, uid_quoted); | ||
} | ||
} | ||
if (should_quote_pwd) { | ||
size_t estimated_length = php_odbc_connstr_estimate_quote_length(pwd); | ||
pwd_quoted = emalloc(estimated_length); | ||
php_odbc_connstr_quote(pwd_quoted, pwd, estimated_length); | ||
} else { | ||
pwd_quoted = pwd; | ||
|
||
if (use_pwd_arg) { | ||
should_quote_pwd = !php_odbc_connstr_is_quoted(pwd) && php_odbc_connstr_should_quote(pwd); | ||
if (should_quote_pwd) { | ||
size_t estimated_length = php_odbc_connstr_estimate_quote_length(pwd); | ||
pwd_quoted = emalloc(estimated_length); | ||
php_odbc_connstr_quote(pwd_quoted, pwd, estimated_length); | ||
} else { | ||
pwd_quoted = pwd; | ||
} | ||
|
||
if (!use_uid_arg) { | ||
spprintf(&ldb, 0, "%s;PWD=%s;", db, pwd_quoted); | ||
} | ||
} | ||
|
||
if (use_uid_arg && use_pwd_arg) { | ||
spprintf(&ldb, 0, "%s;UID=%s;PWD=%s;", db, uid_quoted, pwd_quoted); | ||
} | ||
spprintf(&ldb, 0, "%s;UID=%s;PWD=%s", db, uid_quoted, pwd_quoted); | ||
|
||
if (uid_quoted && should_quote_uid) { | ||
efree(uid_quoted); | ||
} | ||
|
@@ -2167,18 +2191,19 @@ int odbc_sqlconnect(odbc_connection **conn, char *db, char *uid, char *pwd, int | |
/* {{{ odbc_do_connect */ | ||
void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) | ||
{ | ||
char *db, *uid, *pwd; | ||
char *db, *uid=NULL, *pwd=NULL; | ||
size_t db_len, uid_len, pwd_len; | ||
zend_long pv_opt = SQL_CUR_DEFAULT; | ||
odbc_connection *db_conn; | ||
int cur_opt; | ||
|
||
/* Now an optional 4th parameter specifying the cursor type | ||
* defaulting to the cursors default | ||
*/ | ||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|l", &db, &db_len, &uid, &uid_len, &pwd, &pwd_len, &pv_opt) == FAILURE) { | ||
RETURN_THROWS(); | ||
} | ||
ZEND_PARSE_PARAMETERS_START(1, 4) | ||
Z_PARAM_STRING(db, db_len) | ||
Z_PARAM_OPTIONAL | ||
Z_PARAM_STRING_OR_NULL(uid, uid_len) | ||
Z_PARAM_STRING_OR_NULL(pwd, pwd_len) | ||
Z_PARAM_LONG(pv_opt) | ||
ZEND_PARSE_PARAMETERS_END(); | ||
Comment on lines
-2179
to
+2206
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not just: if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s!s!l", &db, &db_len, &uid, &uid_len, &pwd, &pwd_len, &pv_opt) == FAILURE) { ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for confirmation. I read this RFC and decided that If I'm wrong, I will rewrite it to use |
||
|
||
cur_opt = pv_opt; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
--TEST-- | ||
odbc_connect(): Basic test for odbc_connect(). (When not using a DSN alias) | ||
--EXTENSIONS-- | ||
odbc | ||
--SKIPIF-- | ||
<?php | ||
include 'config.inc'; | ||
if (strpos($dsn, '=') === false) { | ||
die('skip uses a DSN alias'); | ||
} | ||
include 'skipif.inc'; | ||
?> | ||
--FILE-- | ||
<?php | ||
|
||
include 'config.inc'; | ||
$dsn = str_replace(";uid={$user};pwd={$pass}", '', $dsn); | ||
|
||
echo "dsn without credentials / correct user / correct password\n"; | ||
$conn = odbc_connect($dsn, $user, $pass); | ||
echo $conn ? "Connected.\n\n" : ""; | ||
if ($conn) odbc_close($conn); | ||
|
||
echo "dsn with correct user / incorrect user / correct password\n"; | ||
$conn = odbc_connect("{$dsn};uid={$user}", 'hoge', $pass); | ||
echo $conn ? "Connected.\n\n" : ""; | ||
if ($conn) odbc_close($conn); | ||
|
||
echo "dsn with correct password / correct user / incorrect password\n"; | ||
$conn = odbc_connect("{$dsn};PWD={$pass}", $user, 'fuga'); | ||
echo $conn ? "Connected.\n\n" : ""; | ||
if ($conn) odbc_close($conn); | ||
|
||
echo "dsn with correct credentials / incorrect user / incorrect password\n"; | ||
$conn = odbc_connect("{$dsn};Uid={$user};pwD={$pass}", 'hoge', 'fuga'); | ||
echo $conn ? "Connected.\n\n" : ""; | ||
if ($conn) odbc_close($conn); | ||
|
||
echo "dsn with correct credentials / null user / null password\n"; | ||
$conn = odbc_connect("{$dsn};Uid={$user};pwD={$pass}", null, null); | ||
echo $conn ? "Connected.\n\n" : ""; | ||
if ($conn) odbc_close($conn); | ||
|
||
echo "dsn with correct credentials / not set user / not set password\n"; | ||
$conn = odbc_connect("{$dsn};Uid={$user};pwD={$pass}"); | ||
echo $conn ? "Connected.\n" : ""; | ||
if ($conn) odbc_close($conn); | ||
?> | ||
--EXPECT-- | ||
dsn without credentials / correct user / correct password | ||
Connected. | ||
|
||
dsn with correct user / incorrect user / correct password | ||
Connected. | ||
|
||
dsn with correct password / correct user / incorrect password | ||
Connected. | ||
|
||
dsn with correct credentials / incorrect user / incorrect password | ||
Connected. | ||
|
||
dsn with correct credentials / null user / null password | ||
Connected. | ||
|
||
dsn with correct credentials / not set user / not set password | ||
Connected. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
--TEST-- | ||
Basic test for connection. (When not using a DSN alias) | ||
--EXTENSIONS-- | ||
pdo_odbc | ||
--SKIPIF-- | ||
<?php | ||
require 'ext/pdo/tests/pdo_test.inc'; | ||
PDOTest::skip(); | ||
$dsn = getenv('PDO_ODBC_TEST_DSN'); | ||
if (!$dsn || strpos($dsn, '=') === false) { | ||
die('skip'); | ||
} | ||
?> | ||
--FILE-- | ||
<?php | ||
$dsnWithCredentials = getenv('PDO_ODBC_TEST_DSN'); | ||
$user = getenv('PDO_ODBC_TEST_USER'); | ||
$password = getenv('PDO_ODBC_TEST_PASS'); | ||
|
||
$dsn = str_replace(";uid={$user};pwd={$password}", '', $dsnWithCredentials); | ||
|
||
echo "dsn without credentials / correct user / correct password\n"; | ||
try { | ||
$db = new PDO($dsn, $user, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); | ||
echo "Connected.\n\n"; | ||
$db = null; | ||
} catch (PDOException $e) { | ||
echo $e->getMessage()."\n"; | ||
} | ||
|
||
echo "dsn with credentials / no user / no password\n"; | ||
try { | ||
$db = new PDO("{$dsn};uid={$user};pwd={$password}", null, null, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); | ||
echo "Connected.\n\n"; | ||
$db = null; | ||
} catch (PDOException $e) { | ||
echo $e->getMessage()."\n"; | ||
} | ||
|
||
echo "dsn with correct user / incorrect user / correct password\n"; | ||
try { | ||
$db = new PDO("{$dsn};UID={$user}", 'hoge', $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); | ||
echo "Connected.\n\n"; | ||
$db = null; | ||
} catch (PDOException $e) { | ||
echo $e->getMessage()."\n"; | ||
} | ||
|
||
echo "dsn with correct password / correct user / incorrect password\n"; | ||
try { | ||
$db = new PDO("{$dsn};PWD={$password}", $user, 'fuga', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); | ||
echo "Connected.\n\n"; | ||
$db = null; | ||
} catch (PDOException $e) { | ||
echo $e->getMessage()."\n"; | ||
} | ||
|
||
echo "dsn with correct credentials / incorrect user / incorrect password\n"; | ||
try { | ||
$db = new PDO("{$dsn};Uid={$user};Pwd={$password}", 'hoge', 'fuga', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); | ||
echo "Connected.\n"; | ||
$db = null; | ||
} catch (PDOException $e) { | ||
echo $e->getMessage()."\n"; | ||
} | ||
?> | ||
--EXPECT-- | ||
dsn without credentials / correct user / correct password | ||
Connected. | ||
|
||
dsn with credentials / no user / no password | ||
Connected. | ||
|
||
dsn with correct user / incorrect user / correct password | ||
Connected. | ||
|
||
dsn with correct password / correct user / incorrect password | ||
Connected. | ||
|
||
dsn with correct credentials / incorrect user / incorrect password | ||
Connected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment above that this should be identical to the code in the PDO driver and vice versa
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in ad06797