@@ -1391,47 +1391,39 @@ php_mysqlnd_read_row_ex(MYSQLND_PFC * pfc,
13911391 SET_CONNECTION_STATE (connection_state , CONN_QUIT_SENT );
13921392 set_packet_error (error_info , CR_SERVER_GONE_ERROR , UNKNOWN_SQLSTATE , mysqlnd_server_gone );
13931393 } else {
1394+ /* If the packet is split in multiple chunks, allocate a temporary buffer that we can
1395+ * reallocate, and only afterwards copy it to the pool when we know the final size. */
1396+ zend_uchar * buf = NULL ;
1397+ while (header .size >= MYSQLND_MAX_PACKET_SIZE ) {
1398+ buf = erealloc (buf , * data_size + header .size );
1399+ p = buf + * data_size ;
1400+ * data_size += header .size ;
1401+
1402+ if (UNEXPECTED (PASS != (ret = pfc -> data -> m .receive (pfc , vio , p , header .size , stats , error_info )))) {
1403+ DBG_ERR ("Empty row packet body" );
1404+ SET_CONNECTION_STATE (connection_state , CONN_QUIT_SENT );
1405+ set_packet_error (error_info , CR_SERVER_GONE_ERROR , UNKNOWN_SQLSTATE , mysqlnd_server_gone );
1406+ efree (buf );
1407+ DBG_RETURN (FAIL );
1408+ }
1409+ if (FAIL == mysqlnd_read_header (pfc , vio , & header , stats , error_info )) {
1410+ efree (buf );
1411+ DBG_RETURN (FAIL );
1412+ }
1413+ }
1414+
1415+ buffer -> ptr = pool -> get_chunk (pool , * data_size + header .size + prealloc_more_bytes );
1416+ if (buf ) {
1417+ memcpy (buffer -> ptr , buf , * data_size );
1418+ efree (buf );
1419+ }
1420+ p = (zend_uchar * ) buffer -> ptr + * data_size ;
13941421 * data_size += header .size ;
1395- buffer -> ptr = pool -> get_chunk (pool , * data_size + prealloc_more_bytes );
1396- p = buffer -> ptr ;
13971422
13981423 if (UNEXPECTED (PASS != (ret = pfc -> data -> m .receive (pfc , vio , p , header .size , stats , error_info )))) {
13991424 DBG_ERR ("Empty row packet body" );
14001425 SET_CONNECTION_STATE (connection_state , CONN_QUIT_SENT );
14011426 set_packet_error (error_info , CR_SERVER_GONE_ERROR , UNKNOWN_SQLSTATE , mysqlnd_server_gone );
1402- } else {
1403- while (header .size >= MYSQLND_MAX_PACKET_SIZE ) {
1404- if (FAIL == mysqlnd_read_header (pfc , vio , & header , stats , error_info )) {
1405- ret = FAIL ;
1406- break ;
1407- }
1408-
1409- * data_size += header .size ;
1410-
1411- /* Empty packet after MYSQLND_MAX_PACKET_SIZE packet. That's ok, break */
1412- if (!header .size ) {
1413- break ;
1414- }
1415-
1416- /*
1417- We have to realloc the buffer.
1418- */
1419- buffer -> ptr = pool -> resize_chunk (pool , buffer -> ptr , * data_size - header .size , * data_size + prealloc_more_bytes );
1420- if (!buffer -> ptr ) {
1421- SET_OOM_ERROR (error_info );
1422- ret = FAIL ;
1423- break ;
1424- }
1425- /* The position could have changed, recalculate */
1426- p = (zend_uchar * ) buffer -> ptr + (* data_size - header .size );
1427-
1428- if (PASS != (ret = pfc -> data -> m .receive (pfc , vio , p , header .size , stats , error_info ))) {
1429- DBG_ERR ("Empty row packet body" );
1430- SET_CONNECTION_STATE (connection_state , CONN_QUIT_SENT );
1431- set_packet_error (error_info , CR_SERVER_GONE_ERROR , UNKNOWN_SQLSTATE , mysqlnd_server_gone );
1432- break ;
1433- }
1434- }
14351427 }
14361428 }
14371429 if (ret == FAIL && buffer -> ptr ) {
0 commit comments