andrey Tue, 25 May 2010 19:19:29 +0000
Revision: http://svn.php.net/viewvc?view=revision&revision=299752
Log:
Handle OOM in the code that generates PS Execute requests
to the server. Fixes crashes in case of OOM.
Changed paths:
U php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps.c
U php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps_codec.c
U php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c
U php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c
U php/php-src/trunk/ext/mysqlnd/mysqlnd_ps_codec.c
U php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c
Modified: php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps.c 2010-05-25 18:58:30 UTC (rev 299751)
+++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps.c 2010-05-25 19:19:29 UTC (rev 299752)
@@ -39,8 +39,7 @@
static struct st_mysqlnd_stmt_methods *mysqlnd_stmt_methods;
/* Exported by mysqlnd_ps_codec.c */
-zend_uchar* mysqlnd_stmt_execute_generate_request(MYSQLND_STMT *stmt, size_t *request_len,
- zend_bool *free_buffer TSRMLS_DC);
+enum_func_status mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC);
MYSQLND_RES * _mysqlnd_stmt_use_result(MYSQLND_STMT *stmt TSRMLS_DC);
@@ -523,8 +522,8 @@
{
MYSQLND_STMT_DATA * stmt = s->data;
enum_func_status ret;
- MYSQLND *conn = stmt->conn;
- zend_uchar *request;
+ MYSQLND * conn = stmt->conn;
+ zend_uchar *request = NULL;
size_t request_len;
zend_bool free_request;
@@ -628,14 +627,16 @@
DBG_RETURN(FAIL);
}
}
- request = mysqlnd_stmt_execute_generate_request(s, &request_len, &free_request TSRMLS_CC);
-
- /* support for buffer types should be added here ! */
+ ret = mysqlnd_stmt_execute_generate_request(s, &request, &request_len, &free_request TSRMLS_CC);
+ if (ret == PASS) {
+ /* support for buffer types should be added here ! */
+ ret = stmt->conn->m->simple_command(stmt->conn, COM_STMT_EXECUTE, (char *)request, request_len,
+ PROT_LAST /* we will handle the response packet*/,
+ FALSE, FALSE TSRMLS_CC);
+ } else {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Couldn't generate the request. Possibly OOM.");
+ }
- ret = stmt->conn->m->simple_command(stmt->conn, COM_STMT_EXECUTE, (char *)request, request_len,
- PROT_LAST /* we will handle the response packet*/,
- FALSE, FALSE TSRMLS_CC);
-
if (free_request) {
mnd_efree(request);
}
Modified: php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps_codec.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps_codec.c 2010-05-25 18:58:30 UTC (rev 299751)
+++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps_codec.c 2010-05-25 19:19:29 UTC (rev 299752)
@@ -578,22 +578,26 @@
/* {{{ mysqlnd_stmt_copy_it */
-static void
+static enum_func_status
mysqlnd_stmt_copy_it(zval *** copies, zval *original, unsigned int param_count, unsigned int current TSRMLS_DC)
{
if (!*copies) {
*copies = mnd_ecalloc(param_count, sizeof(zval *));
}
- MAKE_STD_ZVAL((*copies)[current]);
- *(*copies)[current] = *original;
- Z_SET_REFCOUNT_P((*copies)[current], 1);
- zval_copy_ctor((*copies)[current]);
+ if (*copies) {
+ MAKE_STD_ZVAL((*copies)[current]);
+ *(*copies)[current] = *original;
+ Z_SET_REFCOUNT_P((*copies)[current], 1);
+ zval_copy_ctor((*copies)[current]);
+ return PASS;
+ }
+ return FAIL;
}
/* }}} */
/* {{{ mysqlnd_stmt_execute_store_params */
-static void
+static enum_func_status
mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p,
size_t *buf_len, unsigned int null_byte_offset TSRMLS_DC)
{
@@ -603,7 +607,10 @@
size_t left = (*buf_len - (*p - *buf));
size_t data_size = 0;
zval **copies = NULL;/* if there are different types */
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_stmt_execute_store_params");
+
/* 1. Store type information */
if (stmt->send_types_to_server) {
@@ -613,6 +620,10 @@
zend_uchar *tmp_buf;
*buf_len = offset + stmt->param_count * 2 + 20;
tmp_buf = mnd_emalloc(*buf_len);
+ if (!tmp_buf) {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "OOM");
+ goto end;
+ }
memcpy(tmp_buf, *buf, offset);
*buf = tmp_buf;
@@ -643,7 +654,10 @@
for (j = i + 1; j < stmt->param_count; j++) {
if (stmt->param_bind[j].zv == the_var) {
/* Double binding of the same zval, make a copy */
- mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC);
+ if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "OOM");
+ goto end;
+ }
break;
}
}
@@ -653,7 +667,10 @@
data_size += 8;
if (Z_TYPE_P(the_var) != IS_DOUBLE) {
if (!copies || !copies[i]) {
- mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC);
+ if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "OOM");
+ goto end;
+ }
}
}
break;
@@ -668,7 +685,10 @@
#endif
if (Z_TYPE_P(the_var) != IS_LONG) {
if (!copies || !copies[i]) {
- mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC);
+ if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "OOM");
+ goto end;
+ }
}
}
break;
@@ -691,7 +711,10 @@
#endif
{
if (!copies || !copies[i]) {
- mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC);
+ if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "OOM");
+ goto end;
+ }
}
the_var = copies[i];
#if PHP_MAJOR_VERSION >= 6
@@ -714,6 +737,10 @@
zend_uchar *tmp_buf;
*buf_len = offset + data_size + 10; /* Allocate + 10 for safety */
tmp_buf = mnd_emalloc(*buf_len);
+ if (!tmp_buf) {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "OOM");
+ goto end;
+ }
memcpy(tmp_buf, *buf, offset);
/*
When too many columns the buffer provided to the function might not be sufficient.
@@ -779,6 +806,8 @@
}
}
}
+ ret = PASS;
+end:
if (copies) {
for (i = 0; i < stmt->param_count; i++) {
if (copies[i]) {
@@ -787,13 +816,16 @@
}
mnd_efree(copies);
}
+
+ DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
+ DBG_RETURN(ret);
}
/* }}} */
/* {{{ mysqlnd_stmt_execute_generate_request */
-zend_uchar* mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * s, size_t *request_len,
- zend_bool * free_buffer TSRMLS_DC)
+enum_func_status
+mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s->data;
zend_uchar *p = stmt->execute_cmd_buffer.buffer,
@@ -801,7 +833,10 @@
size_t cmd_buffer_length = stmt->execute_cmd_buffer.length;
unsigned int null_byte_offset,
null_count= (stmt->param_count + 7) / 8;
+ enum_func_status ret;
+ DBG_ENTER("mysqlnd_stmt_execute_generate_request");
+
int4store(p, stmt->stmt_id);
p += 4;
@@ -824,11 +859,13 @@
int1store(p, stmt->send_types_to_server);
p++;
- mysqlnd_stmt_execute_store_params(s, &cmd_buffer, &p, &cmd_buffer_length, null_byte_offset TSRMLS_CC);
+ ret = mysqlnd_stmt_execute_store_params(s, &cmd_buffer, &p, &cmd_buffer_length, null_byte_offset TSRMLS_CC);
*free_buffer = (cmd_buffer != stmt->execute_cmd_buffer.buffer);
*request_len = (p - cmd_buffer);
- return cmd_buffer;
+ *request = cmd_buffer;
+ DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
+ DBG_RETURN(ret);
}
/* }}} */
Modified: php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c 2010-05-25 18:58:30 UTC (rev 299751)
+++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c 2010-05-25 19:19:29 UTC (rev 299752)
@@ -394,6 +394,7 @@
*/
conn->error_info = rset_header->error_info;
ret = FAIL;
+ DBG_ERR_FMT("error=%s", rset_header->error_info.error);
/* Return back from CONN_QUERY_SENT */
CONN_SET_STATE(conn, CONN_READY);
break;
Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c 2010-05-25 18:58:30 UTC (rev 299751)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c 2010-05-25 19:19:29 UTC (rev 299752)
@@ -39,8 +39,7 @@
static struct st_mysqlnd_stmt_methods *mysqlnd_stmt_methods;
/* Exported by mysqlnd_ps_codec.c */
-zend_uchar* mysqlnd_stmt_execute_generate_request(MYSQLND_STMT *stmt, size_t *request_len,
- zend_bool *free_buffer TSRMLS_DC);
+enum_func_status mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC);
MYSQLND_RES * _mysqlnd_stmt_use_result(MYSQLND_STMT *stmt TSRMLS_DC);
@@ -523,8 +522,8 @@
{
MYSQLND_STMT_DATA * stmt = s->data;
enum_func_status ret;
- MYSQLND *conn = stmt->conn;
- zend_uchar *request;
+ MYSQLND * conn = stmt->conn;
+ zend_uchar *request = NULL;
size_t request_len;
zend_bool free_request;
@@ -628,14 +627,16 @@
DBG_RETURN(FAIL);
}
}
- request = mysqlnd_stmt_execute_generate_request(s, &request_len, &free_request TSRMLS_CC);
-
- /* support for buffer types should be added here ! */
+ ret = mysqlnd_stmt_execute_generate_request(s, &request, &request_len, &free_request TSRMLS_CC);
+ if (ret == PASS) {
+ /* support for buffer types should be added here ! */
+ ret = stmt->conn->m->simple_command(stmt->conn, COM_STMT_EXECUTE, (char *)request, request_len,
+ PROT_LAST /* we will handle the response packet*/,
+ FALSE, FALSE TSRMLS_CC);
+ } else {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Couldn't generate the request. Possibly OOM.");
+ }
- ret = stmt->conn->m->simple_command(stmt->conn, COM_STMT_EXECUTE, (char *)request, request_len,
- PROT_LAST /* we will handle the response packet*/,
- FALSE, FALSE TSRMLS_CC);
-
if (free_request) {
mnd_efree(request);
}
Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_ps_codec.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_ps_codec.c 2010-05-25 18:58:30 UTC (rev 299751)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_ps_codec.c 2010-05-25 19:19:29 UTC (rev 299752)
@@ -578,22 +578,26 @@
/* {{{ mysqlnd_stmt_copy_it */
-static void
+static enum_func_status
mysqlnd_stmt_copy_it(zval *** copies, zval *original, unsigned int param_count, unsigned int current TSRMLS_DC)
{
if (!*copies) {
*copies = mnd_ecalloc(param_count, sizeof(zval *));
}
- MAKE_STD_ZVAL((*copies)[current]);
- *(*copies)[current] = *original;
- Z_SET_REFCOUNT_P((*copies)[current], 1);
- zval_copy_ctor((*copies)[current]);
+ if (*copies) {
+ MAKE_STD_ZVAL((*copies)[current]);
+ *(*copies)[current] = *original;
+ Z_SET_REFCOUNT_P((*copies)[current], 1);
+ zval_copy_ctor((*copies)[current]);
+ return PASS;
+ }
+ return FAIL;
}
/* }}} */
/* {{{ mysqlnd_stmt_execute_store_params */
-static void
+static enum_func_status
mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p,
size_t *buf_len, unsigned int null_byte_offset TSRMLS_DC)
{
@@ -603,7 +607,10 @@
size_t left = (*buf_len - (*p - *buf));
size_t data_size = 0;
zval **copies = NULL;/* if there are different types */
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_stmt_execute_store_params");
+
/* 1. Store type information */
if (stmt->send_types_to_server) {
@@ -613,6 +620,10 @@
zend_uchar *tmp_buf;
*buf_len = offset + stmt->param_count * 2 + 20;
tmp_buf = mnd_emalloc(*buf_len);
+ if (!tmp_buf) {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "OOM");
+ goto end;
+ }
memcpy(tmp_buf, *buf, offset);
*buf = tmp_buf;
@@ -643,7 +654,10 @@
for (j = i + 1; j < stmt->param_count; j++) {
if (stmt->param_bind[j].zv == the_var) {
/* Double binding of the same zval, make a copy */
- mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC);
+ if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "OOM");
+ goto end;
+ }
break;
}
}
@@ -653,7 +667,10 @@
data_size += 8;
if (Z_TYPE_P(the_var) != IS_DOUBLE) {
if (!copies || !copies[i]) {
- mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC);
+ if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "OOM");
+ goto end;
+ }
}
}
break;
@@ -668,7 +685,10 @@
#endif
if (Z_TYPE_P(the_var) != IS_LONG) {
if (!copies || !copies[i]) {
- mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC);
+ if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "OOM");
+ goto end;
+ }
}
}
break;
@@ -691,7 +711,10 @@
#endif
{
if (!copies || !copies[i]) {
- mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC);
+ if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "OOM");
+ goto end;
+ }
}
the_var = copies[i];
#if PHP_MAJOR_VERSION >= 6
@@ -714,6 +737,10 @@
zend_uchar *tmp_buf;
*buf_len = offset + data_size + 10; /* Allocate + 10 for safety */
tmp_buf = mnd_emalloc(*buf_len);
+ if (!tmp_buf) {
+ SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "OOM");
+ goto end;
+ }
memcpy(tmp_buf, *buf, offset);
/*
When too many columns the buffer provided to the function might not be sufficient.
@@ -779,6 +806,8 @@
}
}
}
+ ret = PASS;
+end:
if (copies) {
for (i = 0; i < stmt->param_count; i++) {
if (copies[i]) {
@@ -787,13 +816,16 @@
}
mnd_efree(copies);
}
+
+ DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
+ DBG_RETURN(ret);
}
/* }}} */
/* {{{ mysqlnd_stmt_execute_generate_request */
-zend_uchar* mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * s, size_t *request_len,
- zend_bool * free_buffer TSRMLS_DC)
+enum_func_status
+mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s->data;
zend_uchar *p = stmt->execute_cmd_buffer.buffer,
@@ -801,7 +833,10 @@
size_t cmd_buffer_length = stmt->execute_cmd_buffer.length;
unsigned int null_byte_offset,
null_count= (stmt->param_count + 7) / 8;
+ enum_func_status ret;
+ DBG_ENTER("mysqlnd_stmt_execute_generate_request");
+
int4store(p, stmt->stmt_id);
p += 4;
@@ -824,11 +859,13 @@
int1store(p, stmt->send_types_to_server);
p++;
- mysqlnd_stmt_execute_store_params(s, &cmd_buffer, &p, &cmd_buffer_length, null_byte_offset TSRMLS_CC);
+ ret = mysqlnd_stmt_execute_store_params(s, &cmd_buffer, &p, &cmd_buffer_length, null_byte_offset TSRMLS_CC);
*free_buffer = (cmd_buffer != stmt->execute_cmd_buffer.buffer);
*request_len = (p - cmd_buffer);
- return cmd_buffer;
+ *request = cmd_buffer;
+ DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
+ DBG_RETURN(ret);
}
/* }}} */
Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c 2010-05-25 18:58:30 UTC (rev 299751)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c 2010-05-25 19:19:29 UTC (rev 299752)
@@ -394,6 +394,7 @@
*/
conn->error_info = rset_header->error_info;
ret = FAIL;
+ DBG_ERR_FMT("error=%s", rset_header->error_info.error);
/* Return back from CONN_QUERY_SENT */
CONN_SET_STATE(conn, CONN_READY);
break;
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php