andrey Mon, 03 May 2010 18:50:47 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=298920
Log: Handle OOM stemming from mysqlnd_result_init in the same function and up the stack. 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_result.c U php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.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-03 17:47:58 UTC (rev 298919) +++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_ps.c 2010-05-03 18:50:47 UTC (rev 298920) @@ -156,20 +156,35 @@ SET_EMPTY_ERROR(stmt->conn->error_info); MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS); - result = mysqlnd_result_init(stmt->result->field_count, stmt->persistent TSRMLS_CC); + do { + result = mysqlnd_result_init(stmt->result->field_count, stmt->persistent TSRMLS_CC); + if (!result) { + SET_OOM_ERROR(stmt->conn->error_info); + break; + } - result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC); + result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC); + if (!result->meta) { + SET_OOM_ERROR(stmt->conn->error_info); + break; + } - if ((result = result->m.store_result(result, conn, TRUE TSRMLS_CC))) { - stmt->upsert_status.affected_rows = result->stored_data->row_count; - stmt->state = MYSQLND_STMT_PREPARED; - result->type = MYSQLND_RES_PS_BUF; - } else { - stmt->error_info = conn->error_info; - stmt->state = MYSQLND_STMT_PREPARED; + if ((result = result->m.store_result(result, conn, TRUE TSRMLS_CC))) { + stmt->upsert_status.affected_rows = result->stored_data->row_count; + stmt->state = MYSQLND_STMT_PREPARED; + result->type = MYSQLND_RES_PS_BUF; + } else { + stmt->error_info = conn->error_info; + stmt->state = MYSQLND_STMT_PREPARED; + break; + } + DBG_RETURN(result); + } while (0); + + if (result) { + result->m.free_result(result, TRUE TSRMLS_CC); } - - DBG_RETURN(result); + DBG_RETURN(NULL); } /* }}} */ @@ -366,6 +381,10 @@ */ if (stmt_to_prepare->field_count) { MYSQLND_RES * result = mysqlnd_result_init(stmt_to_prepare->field_count, stmt_to_prepare->persistent TSRMLS_CC); + if (!result) { + SET_OOM_ERROR(stmt->conn->error_info); + goto fail; + } /* Allocate the result now as it is needed for the reading of metadata */ stmt_to_prepare->result = result; @@ -374,7 +393,8 @@ result->type = MYSQLND_RES_PS_BUF; if (FAIL == result->m.read_result_metadata(result, stmt_to_prepare->conn TSRMLS_CC) || - FAIL == mysqlnd_stmt_prepare_read_eof(s_to_prepare TSRMLS_CC)) { + FAIL == mysqlnd_stmt_prepare_read_eof(s_to_prepare TSRMLS_CC)) + { goto fail; } } @@ -1655,15 +1675,32 @@ In the meantime we don't need a zval cache reference for this fake result set, so we don't get one. */ - result = mysqlnd_result_init(stmt->field_count, stmt->persistent TSRMLS_CC); - result->type = MYSQLND_RES_NORMAL; - result->m.fetch_row = result->m.fetch_row_normal_unbuffered; - result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED)); - result->unbuf->eof_reached = TRUE; - result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC); + do { + result = mysqlnd_result_init(stmt->field_count, stmt->persistent TSRMLS_CC); + if (!result) { + break; + } + result->type = MYSQLND_RES_NORMAL; + result->m.fetch_row = result->m.fetch_row_normal_unbuffered; + result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED)); + if (!result->unbuf) { + break; + } + result->unbuf->eof_reached = TRUE; + result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC); + if (!result->meta) { + break; + } - DBG_INF_FMT("result=%p", result); - DBG_RETURN(result); + DBG_INF_FMT("result=%p", result); + DBG_RETURN(result); + } while (0); + + SET_OOM_ERROR(stmt->conn->error_info); + if (result) { + result->m.free_result(result, TRUE TSRMLS_CC); + } + DBG_RETURN(NULL); } /* }}} */ 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-03 17:47:58 UTC (rev 298919) +++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c 2010-05-03 18:50:47 UTC (rev 298920) @@ -353,6 +353,7 @@ MYSQLND_STMT_DATA * stmt = s ? s->data:NULL; enum_func_status ret; MYSQLND_PACKET_RSET_HEADER * rset_header; + MYSQLND_PACKET_EOF * fields_eof; DBG_ENTER("mysqlnd_query_read_result_set_header"); DBG_INF_FMT("stmt=%d", stmt? stmt->stmt_id:0); @@ -420,8 +421,7 @@ ret = PASS; MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_NON_RSET_QUERY); break; - default:{ /* Result set */ - MYSQLND_PACKET_EOF * fields_eof; + default: do { /* Result set */ MYSQLND_RES * result; enum_mysqlnd_collected_stats stat = STAT_LAST; @@ -464,7 +464,12 @@ } result = stmt->result; } - + if (!result) { + SET_OOM_ERROR(conn->error_info); + ret = FAIL; + break; + } + if (FAIL == (ret = result->m.read_result_metadata(result, conn TSRMLS_CC))) { /* For PS, we leave them in Prepared state */ if (!stmt && conn->current_result) { @@ -517,11 +522,9 @@ } MYSQLND_INC_CONN_STATISTIC(conn->stats, stat); } - - PACKET_FREE(fields_eof); - - break; - } + } while (0); + PACKET_FREE(fields_eof); + break; /* switch break */ } } while (0); PACKET_FREE(rset_header); @@ -1546,6 +1549,10 @@ DBG_ENTER("mysqlnd_result_init"); DBG_INF_FMT("field_count=%u", field_count); + + if (!ret) { + DBG_RETURN(NULL); + } ret->persistent = persistent; ret->field_count = field_count; Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c =================================================================== --- php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c 2010-05-03 17:47:58 UTC (rev 298919) +++ php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c 2010-05-03 18:50:47 UTC (rev 298920) @@ -156,20 +156,35 @@ SET_EMPTY_ERROR(stmt->conn->error_info); MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS); - result = mysqlnd_result_init(stmt->result->field_count, stmt->persistent TSRMLS_CC); + do { + result = mysqlnd_result_init(stmt->result->field_count, stmt->persistent TSRMLS_CC); + if (!result) { + SET_OOM_ERROR(stmt->conn->error_info); + break; + } - result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC); + result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC); + if (!result->meta) { + SET_OOM_ERROR(stmt->conn->error_info); + break; + } - if ((result = result->m.store_result(result, conn, TRUE TSRMLS_CC))) { - stmt->upsert_status.affected_rows = result->stored_data->row_count; - stmt->state = MYSQLND_STMT_PREPARED; - result->type = MYSQLND_RES_PS_BUF; - } else { - stmt->error_info = conn->error_info; - stmt->state = MYSQLND_STMT_PREPARED; + if ((result = result->m.store_result(result, conn, TRUE TSRMLS_CC))) { + stmt->upsert_status.affected_rows = result->stored_data->row_count; + stmt->state = MYSQLND_STMT_PREPARED; + result->type = MYSQLND_RES_PS_BUF; + } else { + stmt->error_info = conn->error_info; + stmt->state = MYSQLND_STMT_PREPARED; + break; + } + DBG_RETURN(result); + } while (0); + + if (result) { + result->m.free_result(result, TRUE TSRMLS_CC); } - - DBG_RETURN(result); + DBG_RETURN(NULL); } /* }}} */ @@ -366,6 +381,10 @@ */ if (stmt_to_prepare->field_count) { MYSQLND_RES * result = mysqlnd_result_init(stmt_to_prepare->field_count, stmt_to_prepare->persistent TSRMLS_CC); + if (!result) { + SET_OOM_ERROR(stmt->conn->error_info); + goto fail; + } /* Allocate the result now as it is needed for the reading of metadata */ stmt_to_prepare->result = result; @@ -374,7 +393,8 @@ result->type = MYSQLND_RES_PS_BUF; if (FAIL == result->m.read_result_metadata(result, stmt_to_prepare->conn TSRMLS_CC) || - FAIL == mysqlnd_stmt_prepare_read_eof(s_to_prepare TSRMLS_CC)) { + FAIL == mysqlnd_stmt_prepare_read_eof(s_to_prepare TSRMLS_CC)) + { goto fail; } } @@ -1655,15 +1675,32 @@ In the meantime we don't need a zval cache reference for this fake result set, so we don't get one. */ - result = mysqlnd_result_init(stmt->field_count, stmt->persistent TSRMLS_CC); - result->type = MYSQLND_RES_NORMAL; - result->m.fetch_row = result->m.fetch_row_normal_unbuffered; - result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED)); - result->unbuf->eof_reached = TRUE; - result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC); + do { + result = mysqlnd_result_init(stmt->field_count, stmt->persistent TSRMLS_CC); + if (!result) { + break; + } + result->type = MYSQLND_RES_NORMAL; + result->m.fetch_row = result->m.fetch_row_normal_unbuffered; + result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED)); + if (!result->unbuf) { + break; + } + result->unbuf->eof_reached = TRUE; + result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC); + if (!result->meta) { + break; + } - DBG_INF_FMT("result=%p", result); - DBG_RETURN(result); + DBG_INF_FMT("result=%p", result); + DBG_RETURN(result); + } while (0); + + SET_OOM_ERROR(stmt->conn->error_info); + if (result) { + result->m.free_result(result, TRUE TSRMLS_CC); + } + DBG_RETURN(NULL); } /* }}} */ Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c =================================================================== --- php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c 2010-05-03 17:47:58 UTC (rev 298919) +++ php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c 2010-05-03 18:50:47 UTC (rev 298920) @@ -353,6 +353,7 @@ MYSQLND_STMT_DATA * stmt = s ? s->data:NULL; enum_func_status ret; MYSQLND_PACKET_RSET_HEADER * rset_header; + MYSQLND_PACKET_EOF * fields_eof; DBG_ENTER("mysqlnd_query_read_result_set_header"); DBG_INF_FMT("stmt=%d", stmt? stmt->stmt_id:0); @@ -420,8 +421,7 @@ ret = PASS; MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_NON_RSET_QUERY); break; - default:{ /* Result set */ - MYSQLND_PACKET_EOF * fields_eof; + default: do { /* Result set */ MYSQLND_RES * result; enum_mysqlnd_collected_stats stat = STAT_LAST; @@ -464,7 +464,12 @@ } result = stmt->result; } - + if (!result) { + SET_OOM_ERROR(conn->error_info); + ret = FAIL; + break; + } + if (FAIL == (ret = result->m.read_result_metadata(result, conn TSRMLS_CC))) { /* For PS, we leave them in Prepared state */ if (!stmt && conn->current_result) { @@ -517,11 +522,9 @@ } MYSQLND_INC_CONN_STATISTIC(conn->stats, stat); } - - PACKET_FREE(fields_eof); - - break; - } + } while (0); + PACKET_FREE(fields_eof); + break; /* switch break */ } } while (0); PACKET_FREE(rset_header); @@ -1546,6 +1549,10 @@ DBG_ENTER("mysqlnd_result_init"); DBG_INF_FMT("field_count=%u", field_count); + + if (!ret) { + DBG_RETURN(NULL); + } ret->persistent = persistent; ret->field_count = field_count;
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php