andrey Thu, 29 Apr 2010 15:49:51 +0000
Revision: http://svn.php.net/viewvc?view=revision&revision=298781
Log:
Handle OOM cases, in case of persistent connections this is real
and the Zend MM won't help.
Changed paths:
U php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd.c
U php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_priv.h
U php/php-src/trunk/ext/mysqlnd/mysqlnd.c
U php/php-src/trunk/ext/mysqlnd/mysqlnd_priv.h
Modified: php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd.c 2010-04-29 15:47:41 UTC (rev 298780)
+++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd.c 2010-04-29 15:49:51 UTC (rev 298781)
@@ -61,6 +61,7 @@
PHPAPI const char * const mysqlnd_server_gone = "MySQL server has gone away";
PHPAPI const char * const mysqlnd_out_of_sync = "Commands out of sync; you can't run this command now";
+PHPAPI const char * const mysqlnd_out_of_memory = "Out of memory";
PHPAPI MYSQLND_STATS *mysqlnd_global_stats = NULL;
static zend_bool mysqlnd_library_initted = FALSE;
@@ -524,16 +525,25 @@
transport_len = spprintf(&transport, 0, "tcp://%s:%d", host, port);
}
+ if (!transport) {
+ goto err; /* OOM */
+ }
DBG_INF_FMT("transport=%s", transport);
conn->scheme = mnd_pestrndup(transport, transport_len, conn->persistent);
conn->scheme_len = transport_len;
efree(transport); /* allocated by spprintf */
transport = NULL;
+ if (!conn->scheme) {
+ goto err; /* OOM */
+ }
}
greet_packet = conn->protocol->m.get_greet_packet(conn->protocol, FALSE TSRMLS_CC);
auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
ok_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
+ if (!greet_packet || !auth_packet || !ok_packet) {
+ goto err; /* OOM */
+ }
if (FAIL == conn->net->m.connect(conn->net, conn->scheme, conn->scheme_len, conn->persistent, &errstr, &errcode TSRMLS_CC)) {
goto err;
@@ -602,6 +612,9 @@
auth_packet->client_flags= mysql_flags;
conn->scramble = auth_packet->server_scramble_buf = mnd_pemalloc(SCRAMBLE_LENGTH, conn->persistent);
+ if (!conn->scramble) {
+ goto err; /* OOM */
+ }
memcpy(auth_packet->server_scramble_buf, greet_packet->scramble_buf, SCRAMBLE_LENGTH);
if (!PACKET_WRITE(auth_packet, conn)) {
@@ -668,20 +681,35 @@
conn->connect_or_select_db = mnd_pestrndup(db, db_len, conn->persistent);
conn->connect_or_select_db_len = db_len;
+ if (!conn->user || !conn->passwd || !conn->connect_or_select_db) {
+ goto err; /* OOM */
+ }
+
if (!unix_socket) {
-
conn->host = mnd_pestrdup(host, conn->persistent);
+ if (!conn->host) {
+ goto err; /* OOM */
+ }
conn->host_len = strlen(conn->host);
{
char *p;
spprintf(&p, 0, "%s via TCP/IP", conn->host);
+ if (!p) {
+ goto err; /* OOM */
+ }
conn->host_info = mnd_pestrdup(p, conn->persistent);
efree(p); /* allocated by spprintf */
+ if (!conn->host_info) {
+ goto err; /* OOM */
+ }
}
} else {
conn->unix_socket = mnd_pestrdup(socket, conn->persistent);
+ conn->host_info = mnd_pestrdup("Localhost via UNIX socket", conn->persistent);
+ if (!conn->unix_socket || !conn->host_info) {
+ goto err; /* OOM */
+ }
conn->unix_socket_len = strlen(conn->unix_socket);
- conn->host_info = mnd_pestrdup("Localhost via UNIX socket", conn->persistent);
}
conn->client_flag = auth_packet->client_flags;
conn->max_packet_size = auth_packet->max_packet_size;
@@ -720,15 +748,17 @@
unsigned int current_command = 0;
for (; current_command < conn->options.num_commands; ++current_command) {
const char * const command = conn->options.init_commands[current_command];
- MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_EXECUTED_COUNT);
- if (PASS != conn->m->query(conn, command, strlen(command) TSRMLS_CC)) {
- MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_FAILED_COUNT);
- goto err;
+ if (command) {
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_EXECUTED_COUNT);
+ if (PASS != conn->m->query(conn, command, strlen(command) TSRMLS_CC)) {
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_FAILED_COUNT);
+ goto err;
+ }
+ if (conn->last_query_type == QUERY_SELECT) {
+ MYSQLND_RES * result = conn->m->use_result(conn TSRMLS_CC);
+ result->m.free_result(result, TRUE TSRMLS_CC);
+ }
}
- if (conn->last_query_type == QUERY_SELECT) {
- MYSQLND_RES * result = conn->m->use_result(conn TSRMLS_CC);
- result->m.free_result(result, TRUE TSRMLS_CC);
- }
}
}
@@ -782,6 +812,7 @@
if (!conn) {
self_alloced = TRUE;
if (!(conn = mysqlnd_init(FALSE))) {
+ /* OOM */
DBG_RETURN(NULL);
}
}
@@ -1110,7 +1141,8 @@
result->m.fetch_row = result->m.fetch_row_normal_unbuffered;
result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
if (!result->unbuf) {
- DBG_ERR("OOM");
+ /* OOM */
+ SET_OOM_ERROR(conn->error_info);
result->m.free_result(result, TRUE TSRMLS_CC);
DBG_RETURN(NULL);
}
@@ -1252,6 +1284,11 @@
}
conn->connect_or_select_db = mnd_pestrndup(db, db_len, conn->persistent);
conn->connect_or_select_db_len = db_len;
+ if (!conn->connect_or_select_db) {
+ /* OOM */
+ SET_OOM_ERROR(conn->error_info);
+ ret = FAIL;
+ }
}
DBG_RETURN(ret);
}
@@ -1860,10 +1897,16 @@
}
}
if (ret == PASS) {
- mnd_pefree(conn->user, conn->persistent);
+ if (conn->user) {
+ mnd_pefree(conn->user, conn->persistent);
+ }
conn->user = mnd_pestrndup(user, user_len, conn->persistent);
- mnd_pefree(conn->passwd, conn->persistent);
+
+ if (conn->passwd) {
+ mnd_pefree(conn->passwd, conn->persistent);
+ }
conn->passwd = mnd_pestrdup(passwd, conn->persistent);
+
if (conn->last_message) {
mnd_pefree(conn->last_message, conn->persistent);
conn->last_message = NULL;
@@ -1896,6 +1939,7 @@
const char * const value
TSRMLS_DC)
{
+ enum_func_status ret = PASS;
DBG_ENTER("mysqlnd_conn::set_client_option");
DBG_INF_FMT("conn=%llu option=%d", conn->thread_id, option);
switch (option) {
@@ -1915,7 +1959,7 @@
case MYSQL_OPT_CONNECT_TIMEOUT:
case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
- conn->net->m.set_client_option(conn->net, option, value TSRMLS_CC);
+ ret = conn->net->m.set_client_option(conn->net, option, value TSRMLS_CC);
break;
#if PHP_MAJOR_VERSION >= 6
case MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE:
@@ -1943,11 +1987,11 @@
conn->options.init_commands = mnd_perealloc(conn->options.init_commands, sizeof(char *) * (conn->options.num_commands + 1),
conn->persistent);
if (!conn->options.init_commands) {
- DBG_RETURN(FAIL);
+ goto oom;
}
conn->options.init_commands[conn->options.num_commands] = mnd_pestrdup(value, conn->persistent);
if (!conn->options.init_commands[conn->options.num_commands]) {
- DBG_RETURN(FAIL);
+ goto oom;
}
++conn->options.num_commands;
break;
@@ -1966,6 +2010,9 @@
conn->options.charset_name = NULL;
}
conn->options.charset_name = mnd_pestrdup(value, conn->persistent);
+ if (!conn->options.charset_name) {
+ goto oom;
+ }
DBG_INF_FMT("charset=%s", conn->options.charset_name);
break;
#ifdef WHEN_SUPPORTED_BY_MYSQLI
@@ -1990,9 +2037,12 @@
/* not sure, todo ? */
#endif
default:
- DBG_RETURN(FAIL);
+ ret = FAIL;
}
- DBG_RETURN(PASS);
+ DBG_RETURN(ret);
+oom:
+ SET_OOM_ERROR(conn->error_info);
+ DBG_RETURN(FAIL);
}
/* }}} */
@@ -2176,6 +2226,9 @@
DBG_ENTER("mysqlnd_init");
DBG_INF_FMT("persistent=%d", persistent);
+ if (!ret) {
+ DBG_RETURN(NULL);
+ }
ret->persistent = persistent;
ret->m = mysqlnd_conn_methods;
Modified: php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_priv.h
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_priv.h 2010-04-29 15:47:41 UTC (rev 298780)
+++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_priv.h 2010-04-29 15:49:51 UTC (rev 298781)
@@ -127,6 +127,9 @@
strlcpy(error_info.error, (c), sizeof(error_info.error)); \
}
+#define SET_OOM_ERROR(error_info) SET_CLIENT_ERROR(error_info, CR_OUT_OF_MEMORY, UNKNOWN_SQLSTATE, mysqlnd_out_of_memory)
+
+
#define SET_STMT_ERROR(stmt, a, b, c) SET_CLIENT_ERROR(stmt->error_info, a, b, c)
@@ -157,6 +160,7 @@
PHPAPI extern const char * const mysqlnd_old_passwd;
PHPAPI extern const char * const mysqlnd_out_of_sync;
PHPAPI extern const char * const mysqlnd_server_gone;
+PHPAPI extern const char * const mysqlnd_out_of_memory;
enum_func_status mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_warning TSRMLS_DC);
Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd.c 2010-04-29 15:47:41 UTC (rev 298780)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd.c 2010-04-29 15:49:51 UTC (rev 298781)
@@ -61,6 +61,7 @@
PHPAPI const char * const mysqlnd_server_gone = "MySQL server has gone away";
PHPAPI const char * const mysqlnd_out_of_sync = "Commands out of sync; you can't run this command now";
+PHPAPI const char * const mysqlnd_out_of_memory = "Out of memory";
PHPAPI MYSQLND_STATS *mysqlnd_global_stats = NULL;
static zend_bool mysqlnd_library_initted = FALSE;
@@ -524,16 +525,25 @@
transport_len = spprintf(&transport, 0, "tcp://%s:%d", host, port);
}
+ if (!transport) {
+ goto err; /* OOM */
+ }
DBG_INF_FMT("transport=%s", transport);
conn->scheme = mnd_pestrndup(transport, transport_len, conn->persistent);
conn->scheme_len = transport_len;
efree(transport); /* allocated by spprintf */
transport = NULL;
+ if (!conn->scheme) {
+ goto err; /* OOM */
+ }
}
greet_packet = conn->protocol->m.get_greet_packet(conn->protocol, FALSE TSRMLS_CC);
auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
ok_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
+ if (!greet_packet || !auth_packet || !ok_packet) {
+ goto err; /* OOM */
+ }
if (FAIL == conn->net->m.connect(conn->net, conn->scheme, conn->scheme_len, conn->persistent, &errstr, &errcode TSRMLS_CC)) {
goto err;
@@ -602,6 +612,9 @@
auth_packet->client_flags= mysql_flags;
conn->scramble = auth_packet->server_scramble_buf = mnd_pemalloc(SCRAMBLE_LENGTH, conn->persistent);
+ if (!conn->scramble) {
+ goto err; /* OOM */
+ }
memcpy(auth_packet->server_scramble_buf, greet_packet->scramble_buf, SCRAMBLE_LENGTH);
if (!PACKET_WRITE(auth_packet, conn)) {
@@ -668,20 +681,35 @@
conn->connect_or_select_db = mnd_pestrndup(db, db_len, conn->persistent);
conn->connect_or_select_db_len = db_len;
+ if (!conn->user || !conn->passwd || !conn->connect_or_select_db) {
+ goto err; /* OOM */
+ }
+
if (!unix_socket) {
-
conn->host = mnd_pestrdup(host, conn->persistent);
+ if (!conn->host) {
+ goto err; /* OOM */
+ }
conn->host_len = strlen(conn->host);
{
char *p;
spprintf(&p, 0, "%s via TCP/IP", conn->host);
+ if (!p) {
+ goto err; /* OOM */
+ }
conn->host_info = mnd_pestrdup(p, conn->persistent);
efree(p); /* allocated by spprintf */
+ if (!conn->host_info) {
+ goto err; /* OOM */
+ }
}
} else {
conn->unix_socket = mnd_pestrdup(socket, conn->persistent);
+ conn->host_info = mnd_pestrdup("Localhost via UNIX socket", conn->persistent);
+ if (!conn->unix_socket || !conn->host_info) {
+ goto err; /* OOM */
+ }
conn->unix_socket_len = strlen(conn->unix_socket);
- conn->host_info = mnd_pestrdup("Localhost via UNIX socket", conn->persistent);
}
conn->client_flag = auth_packet->client_flags;
conn->max_packet_size = auth_packet->max_packet_size;
@@ -720,15 +748,17 @@
unsigned int current_command = 0;
for (; current_command < conn->options.num_commands; ++current_command) {
const char * const command = conn->options.init_commands[current_command];
- MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_EXECUTED_COUNT);
- if (PASS != conn->m->query(conn, command, strlen(command) TSRMLS_CC)) {
- MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_FAILED_COUNT);
- goto err;
+ if (command) {
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_EXECUTED_COUNT);
+ if (PASS != conn->m->query(conn, command, strlen(command) TSRMLS_CC)) {
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_FAILED_COUNT);
+ goto err;
+ }
+ if (conn->last_query_type == QUERY_SELECT) {
+ MYSQLND_RES * result = conn->m->use_result(conn TSRMLS_CC);
+ result->m.free_result(result, TRUE TSRMLS_CC);
+ }
}
- if (conn->last_query_type == QUERY_SELECT) {
- MYSQLND_RES * result = conn->m->use_result(conn TSRMLS_CC);
- result->m.free_result(result, TRUE TSRMLS_CC);
- }
}
}
@@ -782,6 +812,7 @@
if (!conn) {
self_alloced = TRUE;
if (!(conn = mysqlnd_init(FALSE))) {
+ /* OOM */
DBG_RETURN(NULL);
}
}
@@ -1110,7 +1141,8 @@
result->m.fetch_row = result->m.fetch_row_normal_unbuffered;
result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
if (!result->unbuf) {
- DBG_ERR("OOM");
+ /* OOM */
+ SET_OOM_ERROR(conn->error_info);
result->m.free_result(result, TRUE TSRMLS_CC);
DBG_RETURN(NULL);
}
@@ -1252,6 +1284,11 @@
}
conn->connect_or_select_db = mnd_pestrndup(db, db_len, conn->persistent);
conn->connect_or_select_db_len = db_len;
+ if (!conn->connect_or_select_db) {
+ /* OOM */
+ SET_OOM_ERROR(conn->error_info);
+ ret = FAIL;
+ }
}
DBG_RETURN(ret);
}
@@ -1860,10 +1897,16 @@
}
}
if (ret == PASS) {
- mnd_pefree(conn->user, conn->persistent);
+ if (conn->user) {
+ mnd_pefree(conn->user, conn->persistent);
+ }
conn->user = mnd_pestrndup(user, user_len, conn->persistent);
- mnd_pefree(conn->passwd, conn->persistent);
+
+ if (conn->passwd) {
+ mnd_pefree(conn->passwd, conn->persistent);
+ }
conn->passwd = mnd_pestrdup(passwd, conn->persistent);
+
if (conn->last_message) {
mnd_pefree(conn->last_message, conn->persistent);
conn->last_message = NULL;
@@ -1896,6 +1939,7 @@
const char * const value
TSRMLS_DC)
{
+ enum_func_status ret = PASS;
DBG_ENTER("mysqlnd_conn::set_client_option");
DBG_INF_FMT("conn=%llu option=%d", conn->thread_id, option);
switch (option) {
@@ -1915,7 +1959,7 @@
case MYSQL_OPT_CONNECT_TIMEOUT:
case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
- conn->net->m.set_client_option(conn->net, option, value TSRMLS_CC);
+ ret = conn->net->m.set_client_option(conn->net, option, value TSRMLS_CC);
break;
#if PHP_MAJOR_VERSION >= 6
case MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE:
@@ -1943,11 +1987,11 @@
conn->options.init_commands = mnd_perealloc(conn->options.init_commands, sizeof(char *) * (conn->options.num_commands + 1),
conn->persistent);
if (!conn->options.init_commands) {
- DBG_RETURN(FAIL);
+ goto oom;
}
conn->options.init_commands[conn->options.num_commands] = mnd_pestrdup(value, conn->persistent);
if (!conn->options.init_commands[conn->options.num_commands]) {
- DBG_RETURN(FAIL);
+ goto oom;
}
++conn->options.num_commands;
break;
@@ -1966,6 +2010,9 @@
conn->options.charset_name = NULL;
}
conn->options.charset_name = mnd_pestrdup(value, conn->persistent);
+ if (!conn->options.charset_name) {
+ goto oom;
+ }
DBG_INF_FMT("charset=%s", conn->options.charset_name);
break;
#ifdef WHEN_SUPPORTED_BY_MYSQLI
@@ -1990,9 +2037,12 @@
/* not sure, todo ? */
#endif
default:
- DBG_RETURN(FAIL);
+ ret = FAIL;
}
- DBG_RETURN(PASS);
+ DBG_RETURN(ret);
+oom:
+ SET_OOM_ERROR(conn->error_info);
+ DBG_RETURN(FAIL);
}
/* }}} */
@@ -2176,6 +2226,9 @@
DBG_ENTER("mysqlnd_init");
DBG_INF_FMT("persistent=%d", persistent);
+ if (!ret) {
+ DBG_RETURN(NULL);
+ }
ret->persistent = persistent;
ret->m = mysqlnd_conn_methods;
Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_priv.h
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_priv.h 2010-04-29 15:47:41 UTC (rev 298780)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_priv.h 2010-04-29 15:49:51 UTC (rev 298781)
@@ -127,6 +127,9 @@
strlcpy(error_info.error, (c), sizeof(error_info.error)); \
}
+#define SET_OOM_ERROR(error_info) SET_CLIENT_ERROR(error_info, CR_OUT_OF_MEMORY, UNKNOWN_SQLSTATE, mysqlnd_out_of_memory)
+
+
#define SET_STMT_ERROR(stmt, a, b, c) SET_CLIENT_ERROR(stmt->error_info, a, b, c)
@@ -157,6 +160,7 @@
PHPAPI extern const char * const mysqlnd_old_passwd;
PHPAPI extern const char * const mysqlnd_out_of_sync;
PHPAPI extern const char * const mysqlnd_server_gone;
+PHPAPI extern const char * const mysqlnd_out_of_memory;
enum_func_status mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_warning TSRMLS_DC);
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php