php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #48293 user name send to mysql server in an incorrect encoding (PHP_5_3 and above only)
Submitted: 2009-05-15 12:16 UTC Modified: 2009-06-25 22:54 UTC
From: aaa_whoknows_me at list dot ru Assigned:
Status: Closed Package: MySQL related
PHP Version: 5.3.0RC2 OS: Windows
Private report: No CVE-ID: None
 [2009-05-15 12:16 UTC] aaa_whoknows_me at list dot ru
Description:
------------
PHP >= 5.3.0 sends user name to mysql server in an incorrect encoding in some cases.
-----------------------
In this case PHP uses UTF-8 as its default encoding. PHP sends user name in mysql server default encoding. But in some cases mysql uses different encodings for data storing and sql queries. Consider a following situation:
my.ini
[mysql]
default-character-set=utf8
 [mysqld]
default-character-set=ucs2
So, 'user' in UTF-8 == '????' in UTF-16BE

Reproduce code:
---------------
$link = mysql_connect('user', 'password', 'database');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
echo 'Connected successfully';
mysql_close($link);
---------------
try {
    $dbh = new PDO('mysql:host=localhost;dbname=database', 'user', 'password');
    foreach($dbh->query('SELECT id FROM users;') as $row) {
        print_r($row);
    }
    $dbh = null;
} catch (PDOException $e) {
    print "Error!: " . $e->getMessage() . "<br/>";
}
---------------
$mysqli = new mysqli('localhost', 'user', 'password', 'database');

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

/* Select queries return a resultset */
if ($result = $mysqli->query("SELECT id FROM users;")) {
    printf("Select returned %d rows.\n", $result->num_rows);

    /* free result set */
    $result->close();
}

$mysqli->close();

Expected result:
----------------
A successful connection to the mysql database.

Actual result:
--------------
Access denied for user '????'@'localhost' (using password: YES)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-05-15 17:26 UTC] jani@php.net
Just to make sure: This does not happen with PHP 5.2.9 ??
 [2009-05-16 15:14 UTC] aaa_whoknows_me at list dot ru
It applies only to PHP 5.3.0 and higher. Now I'm using PHP 5.2.9-2 for Windows and it is able to connect to the same MySQL server.
 [2009-05-18 14:57 UTC] andrey@php.net
mysqlnd (5.3.0) doesn't read the my.ini/my.cnf at all, thus also not the [mysql] section. Yes, mysqlnd set the charset of the connection to be the charset of the server sent during the handshake. In the greeting packet the server says which its default charset is. The server interprets the username in the the charset sent by the client.
Libmysql doesn't look at what the server advertises but uses its own charset, sometimes pulled from the config, sometimes what is set through mysql_options - depends how used.
You can overcome mysql's behavior by doing something like
$conn = new mysqli(); // no params, no connection
$conn->options(MYSQLI_SET_CHARSET_NAME, "yourcharset");
$conn->connect("host", "user", "pass"...);

HTH,
Andrey
 [2009-05-18 15:27 UTC] carsten_sttgt at gmx dot de
Just a question:

> mysqlnd (5.3.0) doesn't read the my.ini/my.cnf at all,
> thus also not the [mysql] section.
>
> You can overcome mysql's behavior by doing something like
> $conn->options(MYSQLI_SET_CHARSET_NAME, "yourcharset");

The Options "MYSQLI_READ_DEFAULT_FILE" and "MYSQLI_READ_DEFAULT_GROUP" are still available with mysqlnd?

If yes, you should also change the description at [1].
--> "instead of my.cnf" += " or none as of 5.3.10 with mysqlnd"

If no:
--> "only available with libmysql"

(IMHO there is an other place in the docu, which also describe these options.)
 
Regards,
Carsten

[1] http://de.php.net/manual/en/mysqli.options.php
 [2009-05-18 16:34 UTC] andrey@php.net
mysqlnd doesn't read the configuration files of MySQL. Calling these doesn't result in an error but it is a no-op.
Please file a documentation bug!

Thanks
 [2009-05-21 10:12 UTC] aaa_whoknows_me at list dot ru
>$conn = new mysqli(); // no params, no connection
>$conn->options(MYSQLI_SET_CHARSET_NAME, "yourcharset");
>$conn->connect("host", "user", "pass"...);
Unfortunatly, it didn't help. I tried to use utf8, utf-8, ucs2, utf16, utf-16 and I sent username in all these charsets in all possible combinations but it didn't work anyway.
 [2009-05-21 10:20 UTC] aaa_whoknows_me at list dot ru
Oh, and the most important thing:
this code
>$conn->options(MYSQLI_SET_CHARSET_NAME, "utf8");
raises an error
Couldn't fetch mysqli.
It happens with any charset.
 [2009-05-21 11:48 UTC] carsten_sttgt at gmx dot de
> $conn = new mysqli(); // no params, no connection

$conn = mysqli_init();


> $conn->connect("host", "user", "pass"...);

$conn->real_connect("host", "user", "pass"...);

Regards,
Carsten
 [2009-05-21 13:43 UTC] aaa_whoknows_me at list dot ru
Thank you very much!
It seems to work!
 [2009-06-02 13:23 UTC] aaa_whoknows_me at list dot ru
>$conn = mysqli_init();
>$conn->options(MYSQLI_SET_CHARSET_NAME, "utf8");
>$conn->real_connect($db_host,$db_user,$db_pass,$db_name);

How can I do the same actions with PDO?

$pdo = new PDO( 
    'mysql:host=hostname;dbname=defaultDbName', 
    'username', 
    'password', 
    $options
);

What options should I use to do the same thing as with mysqli?
 [2009-06-25 22:54 UTC] kalle@php.net
Marked as closed. As for the PDO question; it does not seems like PDO offers that ability as the separate drivers does.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri May 17 03:01:32 2024 UTC