From d53337bbe7850fa60c1ae653ff2a234ab24a0b47 Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Tue, 4 May 2010 14:02:42 +0000 Subject: [PATCH] OOM stability fixes --- ext/mysqlnd/mysqlnd_ps.c | 30 ++++++++++++++++++------------ ext/mysqlnd/mysqlnd_result.c | 9 ++++++++- ext/mysqlnd/mysqlnd_wireprotocol.c | 25 ++++++++++++++++++------- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index d8b37b01ee..778663b08a 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -1227,19 +1227,25 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in if (CONN_GET_STATE(conn) == CONN_READY) { size_t packet_len; - stmt->param_bind[param_no].flags |= MYSQLND_PARAM_BIND_BLOB_USED; cmd_buf = mnd_emalloc(packet_len = STMT_ID_LENGTH + 2 + length); - - int4store(cmd_buf, stmt->stmt_id); - int2store(cmd_buf + STMT_ID_LENGTH, param_no); - memcpy(cmd_buf + STMT_ID_LENGTH + 2, data, length); - - /* COM_STMT_SEND_LONG_DATA doesn't send an OK packet*/ - ret = conn->m->simple_command(conn, cmd, (char *)cmd_buf, packet_len, - PROT_LAST , FALSE, TRUE TSRMLS_CC); - mnd_efree(cmd_buf); - if (FAIL == ret) { - stmt->error_info = conn->error_info; + if (cmd_buf) { + stmt->param_bind[param_no].flags |= MYSQLND_PARAM_BIND_BLOB_USED; + + int4store(cmd_buf, stmt->stmt_id); + int2store(cmd_buf + STMT_ID_LENGTH, param_no); + memcpy(cmd_buf + STMT_ID_LENGTH + 2, data, length); + + /* COM_STMT_SEND_LONG_DATA doesn't send an OK packet*/ + ret = conn->m->simple_command(conn, cmd, (char *)cmd_buf, packet_len, + PROT_LAST , FALSE, TRUE TSRMLS_CC); + mnd_efree(cmd_buf); + if (FAIL == ret) { + stmt->error_info = conn->error_info; + } + } else { + ret = FAIL; + SET_OOM_ERROR(stmt->error_info); + SET_OOM_ERROR(conn->error_info); } /* Cover protocol error: COM_STMT_SEND_LONG_DATA was designed to be quick and not diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 26e05ac7f7..02380457f8 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -359,9 +359,16 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC) DBG_INF_FMT("stmt=%d", stmt? stmt->stmt_id:0); ret = FAIL; - rset_header = conn->protocol->m.get_rset_header_packet(conn->protocol, FALSE TSRMLS_CC); do { + rset_header = conn->protocol->m.get_rset_header_packet(conn->protocol, FALSE TSRMLS_CC); + if (!rset_header) { + SET_OOM_ERROR(conn->error_info); + ret = FAIL; + break; + } + SET_ERROR_AFF_ROWS(conn); + if (FAIL == (ret = PACKET_READ(rset_header, conn))) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error reading result set's header"); break; diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 75391d390a..39a3c94b04 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -777,6 +777,7 @@ void php_mysqlnd_cmd_free_mem(void *_packet, zend_bool alloca TSRMLS_DC) static enum_func_status php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC) { + enum_func_status ret = PASS; size_t buf_len = conn->net->cmd_buffer.length; zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer; zend_uchar *p = buf; @@ -819,9 +820,14 @@ php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC) */ len = packet->header.size - 1; packet->info_or_local_file = mnd_emalloc(len + 1); - memcpy(packet->info_or_local_file, p, len); - packet->info_or_local_file[len] = '\0'; - packet->info_or_local_file_len = len; + if (packet->info_or_local_file) { + memcpy(packet->info_or_local_file, p, len); + packet->info_or_local_file[len] = '\0'; + packet->info_or_local_file_len = len; + } else { + SET_OOM_ERROR(conn->error_info); + ret = FAIL; + } break; case 0x00: DBG_INF("UPSERT"); @@ -841,9 +847,14 @@ php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC) /* Check for additional textual data */ if (packet->header.size > (size_t) (p - buf) && (len = php_mysqlnd_net_field_length(&p))) { packet->info_or_local_file = mnd_emalloc(len + 1); - memcpy(packet->info_or_local_file, p, len); - packet->info_or_local_file[len] = '\0'; - packet->info_or_local_file_len = len; + if (packet->info_or_local_file) { + memcpy(packet->info_or_local_file, p, len); + packet->info_or_local_file[len] = '\0'; + packet->info_or_local_file_len = len; + } else { + SET_OOM_ERROR(conn->error_info); + ret = FAIL; + } } DBG_INF_FMT("affected_rows=%llu last_insert_id=%llu server_status=%d warning_count=%d", packet->affected_rows, packet->last_insert_id, @@ -856,7 +867,7 @@ php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC) } BAIL_IF_NO_MORE_DATA; - DBG_RETURN(PASS); + DBG_RETURN(ret); premature_end: DBG_ERR_FMT("RSET_HEADER packet %d bytes shorter than expected", p - begin - packet->header.size); php_error_docref(NULL TSRMLS_CC, E_WARNING, "RSET_HEADER packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected", -- 2.40.0