]> granicus.if.org Git - php/commitdiff
Handle OOM stemming from mysqlnd_result_init in the same
authorAndrey Hristov <andrey@php.net>
Mon, 3 May 2010 18:50:47 +0000 (18:50 +0000)
committerAndrey Hristov <andrey@php.net>
Mon, 3 May 2010 18:50:47 +0000 (18:50 +0000)
function and up the stack.

ext/mysqlnd/mysqlnd_ps.c
ext/mysqlnd/mysqlnd_result.c

index 4115e685403ae0ef4ffd754bf140aa7f8efd83c2..d8b37b01ee0c66a60d08ee6897c0853548d99d02 100644 (file)
@@ -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);       
 }
 /* }}} */
 
index 5d5ad5012e57545e590b96c5915e37f75cdc9828..7c0e4e1a3730fd2f17da5f9975f08f50e6a48378 100644 (file)
@@ -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;