Skip to content

Commit 8327764

Browse files
committed
ext/odbc: do not mutate the caller's DSN string
odbc_sqlconnect() stripped a trailing semicolon by writing a NUL into the Z_PARAM_STRING buffer, which is a zend_string. Shared variables, interned literals, and const values used as the DSN were permanently altered (strlen unchanged, last byte became NUL). Compute the base length instead and pass it to spprintf with %.*s, matching the non-mutating approach used when assembling UID/PWD into the connect string.
1 parent 0549c8e commit 8327764

2 files changed

Lines changed: 26 additions & 6 deletions

File tree

ext/odbc/php_odbc.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,9 +2217,9 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool
22172217

22182218
/* Force UID and PWD to be set in the DSN */
22192219
if (use_uid_arg || use_pwd_arg) {
2220-
db_end--;
2221-
if ((unsigned char)*(db_end) == ';') {
2222-
*db_end = '\0';
2220+
size_t base_len = db_len;
2221+
if (base_len > 0 && db[base_len - 1] == ';') {
2222+
base_len--;
22232223
}
22242224

22252225
char *uid_quoted = NULL, *pwd_quoted = NULL;
@@ -2235,7 +2235,7 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool
22352235
}
22362236

22372237
if (!use_pwd_arg) {
2238-
spprintf(&ldb, 0, "%s;UID=%s;", db, uid_quoted);
2238+
spprintf(&ldb, 0, "%.*s;UID=%s;", (int) base_len, db, uid_quoted);
22392239
}
22402240
}
22412241

@@ -2250,12 +2250,12 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool
22502250
}
22512251

22522252
if (!use_uid_arg) {
2253-
spprintf(&ldb, 0, "%s;PWD=%s;", db, pwd_quoted);
2253+
spprintf(&ldb, 0, "%.*s;PWD=%s;", (int) base_len, db, pwd_quoted);
22542254
}
22552255
}
22562256

22572257
if (use_uid_arg && use_pwd_arg) {
2258-
spprintf(&ldb, 0, "%s;UID=%s;PWD=%s;", db, uid_quoted, pwd_quoted);
2258+
spprintf(&ldb, 0, "%.*s;UID=%s;PWD=%s;", (int) base_len, db, uid_quoted, pwd_quoted);
22592259
}
22602260

22612261
if (uid_quoted && should_quote_uid) {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
odbc_connect() must not mutate the caller's DSN string
3+
--EXTENSIONS--
4+
odbc
5+
--FILE--
6+
<?php
7+
/* The '=' selects the connection-string form and the trailing ';' is what the
8+
* UID/PWD assembly used to overwrite with a NUL, in the caller's own buffer. */
9+
$dsn = 'Driver=DoesNotExist;Database=x;SS001;';
10+
const DSN_CONST = 'Driver=DoesNotExist;Database=x;SS001_CONST;';
11+
12+
@odbc_connect($dsn, 'u', 'p');
13+
@odbc_connect(DSN_CONST, 'u', 'p');
14+
15+
var_dump($dsn);
16+
var_dump(DSN_CONST);
17+
?>
18+
--EXPECT--
19+
string(37) "Driver=DoesNotExist;Database=x;SS001;"
20+
string(43) "Driver=DoesNotExist;Database=x;SS001_CONST;"

0 commit comments

Comments
 (0)