diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 16617078d3c1..8b78308f9426 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -2217,9 +2217,9 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool /* Force UID and PWD to be set in the DSN */ if (use_uid_arg || use_pwd_arg) { - db_end--; - if ((unsigned char)*(db_end) == ';') { - *db_end = '\0'; + size_t base_len = db_len; + if (base_len > 0 && db[base_len - 1] == ';') { + base_len--; } 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 } if (!use_pwd_arg) { - spprintf(&ldb, 0, "%s;UID=%s;", db, uid_quoted); + spprintf(&ldb, 0, "%.*s;UID=%s;", (int) base_len, db, uid_quoted); } } @@ -2250,12 +2250,12 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool } if (!use_uid_arg) { - spprintf(&ldb, 0, "%s;PWD=%s;", db, pwd_quoted); + spprintf(&ldb, 0, "%.*s;PWD=%s;", (int) base_len, 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;", (int) base_len, db, uid_quoted, pwd_quoted); } if (uid_quoted && should_quote_uid) { diff --git a/ext/odbc/tests/gh_odbc_dsn_immutability.phpt b/ext/odbc/tests/gh_odbc_dsn_immutability.phpt new file mode 100644 index 000000000000..e3023b387c70 --- /dev/null +++ b/ext/odbc/tests/gh_odbc_dsn_immutability.phpt @@ -0,0 +1,20 @@ +--TEST-- +odbc_connect() must not mutate the caller's DSN string +--EXTENSIONS-- +odbc +--FILE-- + +--EXPECT-- +string(37) "Driver=DoesNotExist;Database=x;SS001;" +string(43) "Driver=DoesNotExist;Database=x;SS001_CONST;"