diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c index c9e134f7a3e..6e17412edb5 100644 --- a/ext/mysqlnd/mysqlnd.c +++ b/ext/mysqlnd/mysqlnd.c @@ -257,6 +257,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, simple_command_handle_response)(MYSQLND_CONN_D conn->persistent); if (!ignore_upsert_status) { + memset(conn->upsert_status, 0, sizeof(*conn->upsert_status)); conn->upsert_status->warning_count = ok_response->warning_count; conn->upsert_status->server_status = ok_response->server_status; conn->upsert_status->affected_rows = ok_response->affected_rows; @@ -319,6 +320,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, simple_command_send_request)(MYSQLND_CONN_DATA DBG_ENTER("mysqlnd_conn_data::simple_command_send_request"); DBG_INF_FMT("command=%s silent=%u", mysqlnd_command_to_text[command], silent); + DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status); switch (CONN_GET_STATE(conn)) { case CONN_READY: @@ -333,10 +335,6 @@ MYSQLND_METHOD(mysqlnd_conn_data, simple_command_send_request)(MYSQLND_CONN_DATA DBG_RETURN(FAIL); } - /* clean UPSERT info */ - if (!ignore_upsert_status) { - memset(conn->upsert_status, 0, sizeof(*conn->upsert_status)); - } SET_ERROR_AFF_ROWS(conn); SET_EMPTY_ERROR(*conn->error_info); @@ -811,6 +809,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn, { goto err; } + memset(conn->upsert_status, 0, sizeof(*conn->upsert_status)); conn->upsert_status->warning_count = 0; conn->upsert_status->server_status = greet_packet->server_status; conn->upsert_status->affected_rows = 0; @@ -1183,6 +1182,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_query)(MYSQLND_CONN_DATA * conn, const ch enum_func_status ret = FAIL; DBG_ENTER("mysqlnd_conn_data::send_query"); DBG_INF_FMT("conn=%llu query=%s", conn->thread_id, query); + DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status); if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) { ret = conn->m->simple_command(conn, COM_QUERY, (zend_uchar *) query, query_len, @@ -1193,6 +1193,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_query)(MYSQLND_CONN_DATA * conn, const ch } conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); } + DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status); DBG_RETURN(ret); } /* }}} */ @@ -1208,6 +1209,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, reap_query)(MYSQLND_CONN_DATA * conn TSRMLS_DC DBG_ENTER("mysqlnd_conn_data::reap_query"); DBG_INF_FMT("conn=%llu", conn->thread_id); + DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status); if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) { if (state <= CONN_READY || state == CONN_QUIT_SENT) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not opened, clear or has been closed"); @@ -1218,6 +1220,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, reap_query)(MYSQLND_CONN_DATA * conn TSRMLS_DC conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); } + DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status); DBG_RETURN(ret); } /* }}} */ @@ -1603,6 +1606,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, escape_string)(MYSQLND_CONN_DATA * const conn, DBG_INF_FMT("conn=%llu", conn->thread_id); if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) { + DBG_INF_FMT("server_status=%u", conn->upsert_status->server_status); if (conn->upsert_status->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) { ret = mysqlnd_cset_escape_quotes(conn->charset, newstr, escapestr, escapestr_len TSRMLS_CC); } else { diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 15b293825b4..1eca92776f6 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -486,6 +486,7 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s TSRMLS_DC) ret = mysqlnd_query_read_result_set_header(stmt->conn, s TSRMLS_CC); if (ret == FAIL) { COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); + memset(stmt->upsert_status, 0, sizeof(*stmt->upsert_status)); stmt->upsert_status->affected_rows = conn->upsert_status->affected_rows; if (CONN_GET_STATE(conn) == CONN_QUIT_SENT) { /* close the statement here, the connection has been closed */ @@ -905,6 +906,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int DBG_INF("EOF"); /* Mark the connection as usable again */ result->unbuf->eof_reached = TRUE; + memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status)); result->conn->upsert_status->warning_count = row_packet->warning_count; result->conn->upsert_status->server_status = row_packet->server_status; /* @@ -1014,6 +1016,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla row_packet->skip_extraction = stmt->result_bind? FALSE:TRUE; + memset(stmt->upsert_status, 0, sizeof(*stmt->upsert_status)); if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) { unsigned int i, field_count = result->field_count; diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 20d941e05b6..4d9c6559322 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -415,6 +415,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s DBG_INF("UPSERT"); conn->last_query_type = QUERY_UPSERT; conn->field_count = rset_header->field_count; + memset(conn->upsert_status, 0, sizeof(*conn->upsert_status)); conn->upsert_status->warning_count = rset_header->warning_count; conn->upsert_status->server_status = rset_header->server_status; conn->upsert_status->affected_rows = rset_header->affected_rows; @@ -702,6 +703,7 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC) /* Mark the connection as usable again */ DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status); result->unbuf->eof_reached = TRUE; + memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status)); result->conn->upsert_status->warning_count = row_packet->warning_count; result->conn->upsert_status->server_status = row_packet->server_status; /* @@ -828,6 +830,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla /* Mark the connection as usable again */ DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status); result->unbuf->eof_reached = TRUE; + memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status)); result->conn->upsert_status->warning_count = row_packet->warning_count; result->conn->upsert_status->server_status = row_packet->server_status; /* @@ -1175,6 +1178,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c /* Finally clean */ if (row_packet->eof) { + memset(conn->upsert_status, 0, sizeof(*conn->upsert_status)); conn->upsert_status->warning_count = row_packet->warning_count; conn->upsert_status->server_status = row_packet->server_status; } diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 669970789ba..0d29973cdea 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -827,6 +827,7 @@ php_mysqlnd_ok_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC) packet->error, sizeof(packet->error), &packet->error_no, packet->sqlstate TSRMLS_CC); + DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status); DBG_RETURN(PASS); } /* Everything was fine! */ @@ -1069,6 +1070,7 @@ php_mysqlnd_rset_header_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC) packet->error_info.error, sizeof(packet->error_info.error), &packet->error_info.error_no, packet->error_info.sqlstate TSRMLS_CC); + DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status); DBG_RETURN(PASS); } diff --git a/ext/pdo_mysql/tests/bug66141.phpt b/ext/pdo_mysql/tests/bug66141.phpt new file mode 100644 index 00000000000..3a28509314e --- /dev/null +++ b/ext/pdo_mysql/tests/bug66141.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug #66141 (mysqlnd quote function is wrong with NO_BACKSLASH_ESCAPES after failed query) +--SKIPIF-- + +--FILE-- +quote($input); + +$db->query('set session sql_mode="NO_BACKSLASH_ESCAPES"'); + +// injection text from some user input + +$quotedInput1 = $db->quote($input); + +$db->query('something that throws an exception'); + +$quotedInput2 = $db->quote($input); + +var_dump($quotedInput0); +var_dump($quotedInput1); +var_dump($quotedInput2); +?> +done +--EXPECTF-- +Warning: PDO::query(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'something that throws an exception' at line %d in %s on line %d +string(50) "'Something\', 1 as one, 2 as two FROM dual; -- f'" +string(50) "'Something'', 1 as one, 2 as two FROM dual; -- f'" +string(50) "'Something'', 1 as one, 2 as two FROM dual; -- f'" +done \ No newline at end of file