php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #37867 MySQL extension lacks charset function
Submitted: 2006-06-21 04:14 UTC Modified: 2006-07-04 11:54 UTC
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: yu at nic dot fujitsu dot com Assigned:
Status: Wont fix Package: MySQL related
PHP Version: 4.4.2 OS: NetBSD 3.0
Private report: No CVE-ID: None
 [2006-06-21 04:14 UTC] yu at nic dot fujitsu dot com
Description:
------------
MySQL4.1 and MySQL5 have a function,
mysql_set_character_set(), which sets up MySQL internal
character set.

To set MySQL character set correctly both in client-side
and in server-side, calling this function is the only
right way after the connection is created (by mysql_real_connect()).

It is not right to call "set names" SQL statement by 
mysql_query, because this call sets only in server-side
charset.  To set up client-side charset, mysql_set_character_set() is needed. But PHP4.4.2 and 5.1.4
have no interface to call this function.

(There is another way to set charset correctly.
Calling mysql_options() with MYSQL_SET_CHARSET_NAME before
mysql_real_connect() do the same thing internally.
But PHP4.4.2 and 5.1.4 don't have this interface.)


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-06-21 06:54 UTC] georg@php.net
To use the features of MySQL 4.1 and above you should use the mysqli extension, which has mysqli_set_charset function.


 [2006-06-21 08:10 UTC] yu at nic dot fujitsu dot com
PHP 4.4.2 has no mysqli extension, so I cannot use it...
Are there any plan to backport it from PHP5?

Without this charset interface, client-side charset is
always set to latin1, and mysql_real_escape_string()
cannot handle multibyte strings well.  For example,
1. Client-side: sjis(Japanese Shift-JIS) string
   "0x95 0x27" is escaped to "0x95 0x27 0x27"
   by mysql_real_escape_string() call.
2. Server-side: "0x95 0x27" part is recognized as valid
   sjis multibyte character, and following "0x27" is
   recognized as single quote...  easily SQL injected.

As a result, almost all PHP4 programs using multibyte charset in MySQL extension would be affected by this SQL injection bug.
 [2006-07-04 11:54 UTC] yu at nic dot fujitsu dot com
With the following patch, I can set charset by calling mysql_set_charset() func, the right way mysql expects.
I'll be happy if you merge this to the main source.

Thanks.

--- ext/mysql/php_mysql.c       2006-01-01 22:46:55.000000000 +0900
+++ ext/mysql/php_mysql.c       2006-07-04 17:29:22.000000000 +0900
@@ -161,6 +161,7 @@
        PHP_FE(mysql_stat,                                                                      NULL)
        PHP_FE(mysql_thread_id,                                                         NULL)
        PHP_FE(mysql_client_encoding,                                   NULL)
+       PHP_FE(mysql_set_charset,                                       NULL)
        PHP_FE(mysql_ping,                                                                      NULL)
 #ifdef HAVE_GETINFO_FUNCS
        PHP_FE(mysql_get_client_info,                                           NULL)
@@ -1123,6 +1124,45 @@
 /* }}} */
 #endif
 
+/* {{{ proto string mysql_set_charset(string csname, [int link_identifier])
+       set client character set */
+PHP_FUNCTION(mysql_set_charset)
+{
+       zval **csname, **mysql_link;
+       int id;
+       php_mysql_conn *mysql;
+       
+       switch(ZEND_NUM_ARGS()) {
+               case 1:
+                       if (zend_get_parameters_ex(1, &csname)==FAILURE) {
+                               RETURN_FALSE;
+                       }
+                       id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+                       CHECK_LINK(id);
+                       break;
+               case 2:
+                       if (zend_get_parameters_ex(2, &csname, &mysql_link)==FAILURE) {
+                               RETURN_FALSE;
+                       }
+                       id = -1;
+                       break;
+               default:
+                       WRONG_PARAM_COUNT;
+                       break;
+       }
+       
+       ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink);
+       
+       convert_to_string_ex(csname);
+
+       if (mysql_set_character_set(&mysql->conn, Z_STRVAL_PP(csname))==0) {
+               RETURN_TRUE;
+       } else {
+               RETURN_FALSE;
+       }
+}
+/* }}} */
+
 #ifndef NETWARE                /* The below two functions not supported on NetWare */
 #if MYSQL_VERSION_ID < 40000
 /* {{{ proto bool mysql_create_db(string database_name [, int link_identifier])
--- ext/mysql/php_mysql.h       2006-01-01 22:46:55.000000000 +0900
+++ ext/mysql/php_mysql.h       2006-07-04 17:22:03.000000000 +0900
@@ -90,6 +90,7 @@
 PHP_FUNCTION(mysql_stat);
 PHP_FUNCTION(mysql_thread_id);
 PHP_FUNCTION(mysql_client_encoding);
+PHP_FUNCTION(mysql_set_charset);
 PHP_FUNCTION(mysql_ping);
 
 ZEND_BEGIN_MODULE_GLOBALS(mysql)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 17:01:58 2024 UTC