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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: yu at nic dot fujitsu dot com
New email:
PHP Version: OS:

 

 [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: Sun Dec 22 03:01:28 2024 UTC