Commit 20003bec2b9 for php.net

commit 20003bec2b9f9db87cea59fb395bd2e736d1a8a0
Author: Calvin Buckley <calvinb@php.net>
Date:   Thu Jul 30 01:26:42 2026 -0300

    odbc: Quote spaces in UID/PWD appended to connection string (#22791)

    Drivers have no standard parsing, and may react weirdly to spaces in a
    connection string. When we append the UID/PWD parameters for the user
    and pass parameters of `odbc_(p)connect` or the PDO constructor, add
    spaces to the list of characters that require quoting.

    This fixes issues related to significant whitespace possibly not being
    parsed in a username or password, or having whitespace mangle parsing of
    a connection string. Note that there is no security impact because in
    order to do something interesting, you must be able to control the ';='
    characters, and we already quote in those cases.

diff --git a/ext/odbc/tests/odbc_utils.phpt b/ext/odbc/tests/odbc_utils.phpt
index 05d23e78aae..613749cf0d8 100644
--- a/ext/odbc/tests/odbc_utils.phpt
+++ b/ext/odbc/tests/odbc_utils.phpt
@@ -17,11 +17,14 @@
 // 2. See $with_end_curly2; should_quote doesn't care about if the string is already quoted.
 $with_end_curly3 = "{foo}}bar}";
 // 1. No, it's not quoted.
-// 2. It doesn't need to be quoted because of no s
+// 2. It doesn't need to be quoted because of no special characters.
 $with_no_end_curly1 = "foobar";
 // 1. Yes, it is quoted and any characters are properly escaped.
 // 2. See $with_end_curly2.
 $with_no_end_curly2 = "{foobar}";
+// 1. No, it's not quoted.
+// 2. Yes, spaces should be quoted, as drivers can interpret them differently.
+$with_spaces = "  foobar  ";

 echo "# Is quoted?\n";
 echo "With end curly brace 1: ";
@@ -34,6 +37,8 @@
 var_dump(odbc_connection_string_is_quoted($with_no_end_curly1));
 echo "Without end curly brace 2: ";
 var_dump(odbc_connection_string_is_quoted($with_no_end_curly2));
+echo "With spaces: ";
+var_dump(odbc_connection_string_is_quoted($with_spaces));

 echo "# Should quote?\n";
 echo "With end curly brace 1: ";
@@ -46,6 +51,8 @@
 var_dump(odbc_connection_string_should_quote($with_no_end_curly1));
 echo "Without end curly brace 2: ";
 var_dump(odbc_connection_string_should_quote($with_no_end_curly2));
+echo "With spaces: ";
+var_dump(odbc_connection_string_should_quote($with_spaces));

 echo "# Quote?\n";
 echo "With end curly brace 1: ";
@@ -58,6 +65,8 @@
 var_dump(odbc_connection_string_quote($with_no_end_curly1));
 echo "Without end curly brace 2: ";
 var_dump(odbc_connection_string_quote($with_no_end_curly2));
+echo "With spaces: ";
+var_dump(odbc_connection_string_quote($with_spaces));

 ?>
 --EXPECTF--
@@ -67,15 +76,18 @@
 With end curly brace 3: bool(true)
 Without end curly brace 1: bool(false)
 Without end curly brace 2: bool(true)
+With spaces: bool(false)
 # Should quote?
 With end curly brace 1: bool(true)
 With end curly brace 2: bool(true)
 With end curly brace 3: bool(true)
 Without end curly brace 1: bool(false)
 Without end curly brace 2: bool(true)
+With spaces: bool(true)
 # Quote?
 With end curly brace 1: string(10) "{foo}}bar}"
 With end curly brace 2: string(13) "{{foo}}bar}}}"
 With end curly brace 3: string(15) "{{foo}}}}bar}}}"
 Without end curly brace 1: string(8) "{foobar}"
 Without end curly brace 2: string(11) "{{foobar}}}"
+With spaces: string(12) "{  foobar  }"
diff --git a/main/php_odbc_utils.c b/main/php_odbc_utils.c
index 5cba835f81e..162a1eb31df 100644
--- a/main/php_odbc_utils.c
+++ b/main/php_odbc_utils.c
@@ -64,12 +64,17 @@ PHPAPI bool php_odbc_connstr_is_quoted(const char *str)
  * attribute values that contain the characters []{}(),;?*=!@ not enclosed
  * with braces should be avoided."
  *
+ * We also add spaces too, as driver connection string parameter parsing isn't
+ * standardized and can be quite sloppy; it can lead to significant whitespace
+ * not being parsed or confusing parsing of different sections. Note that this
+ * lacks security impact as we already quote the ';=' characters when parsing.
+ *
  * Note that it assumes that the string is *not* already quoted. You should
  * check beforehand.
  */
 PHPAPI bool php_odbc_connstr_should_quote(const char *str)
 {
-	return strpbrk(str, "[]{}(),;?*=!@") != NULL;
+	return strpbrk(str, "[]{}(),;?*=!@ ") != NULL;
 }

 /**