From 2b18a3ff939623720e752e5f96af9ccd1ae50e7e Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Mon, 3 May 2010 18:50:47 +0000 Subject: [PATCH] Handle OOM stemming from mysqlnd_result_init in the same function and up the stack. --- ext/mysqlnd/mysqlnd_ps.c | 79 ++++++++++++++++++++++++++---------- ext/mysqlnd/mysqlnd_result.c | 23 +++++++---- 2 files changed, 73 insertions(+), 29 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 4115e68540..d8b37b01ee 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -156,20 +156,35 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s TSRMLS_DC) 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); - DBG_RETURN(result); + if (result) { + result->m.free_result(result, TRUE TSRMLS_CC); + } + DBG_RETURN(NULL); } /* }}} */ @@ -366,6 +381,10 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const */ 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 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const 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 @@ MYSQLND_METHOD(mysqlnd_stmt, result_metadata)(MYSQLND_STMT * const s TSRMLS_DC) 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); - - DBG_INF_FMT("result=%p", result); - DBG_RETURN(result); + 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); + } while (0); + + SET_OOM_ERROR(stmt->conn->error_info); + if (result) { + result->m.free_result(result, TRUE TSRMLS_CC); + } + DBG_RETURN(NULL); } /* }}} */ diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 5d5ad5012e..7c0e4e1a37 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -353,6 +353,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC) 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 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC) 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 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC) } 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_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC) } 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 @@ mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC) 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; -- 2.40.0