@@ -1634,7 +1634,8 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer,
1634
1634
zval * current_field , * end_field , * start_field ;
1635
1635
zend_uchar * p = row_buffer -> ptr ;
1636
1636
size_t data_size = row_buffer -> app ;
1637
- zend_uchar * bit_area = (zend_uchar * ) row_buffer -> ptr + data_size + 1 ; /* we allocate from here */
1637
+ /* we allocate from here. In pre-7.0 it was +1, as there was an additional \0 for the last string in the packet - because of the zval optimizations - using no-copy */
1638
+ zend_uchar * bit_area = (zend_uchar * ) row_buffer -> ptr + data_size ;
1638
1639
const zend_uchar * const packet_end = (zend_uchar * ) row_buffer -> ptr + data_size ;
1639
1640
1640
1641
DBG_ENTER ("php_mysqlnd_rowp_read_text_protocol_aux" );
@@ -1761,9 +1762,25 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer,
1761
1762
*/
1762
1763
p -= len ;
1763
1764
if (Z_TYPE_P (current_field ) == IS_LONG ) {
1765
+ /*
1766
+ Andrey : See below. No need of bit_area, as we can use on stack for this.
1767
+ The bit area should be removed - the `prealloc_more_bytes` in php_mysqlnd_read_row_ex()
1768
+
1769
+ char tmp[22];
1770
+ const size_t tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, Z_LVAL_P(current_field));
1771
+ ZVAL_STRINGL(current_field, tmp, tmp_len);
1772
+ */
1764
1773
bit_area += 1 + sprintf ((char * )start , ZEND_LONG_FMT , Z_LVAL_P (current_field ));
1765
1774
ZVAL_STRINGL (current_field , (char * ) start , bit_area - start - 1 );
1766
- } else if (Z_TYPE_P (current_field ) == IS_STRING ){
1775
+ } else if (Z_TYPE_P (current_field ) == IS_STRING ) {
1776
+ /*
1777
+ Andrey : This is totally sensless, but I am not gonna remove it in a production version.
1778
+ This copies the data from the zval to the bit area. The destroys the original value
1779
+ and creates the same one from the bit area. No need. It was making sense in pre-7.0
1780
+ when we used zval IS_STRING with no-copy that referred to the bit area.
1781
+ The bit area has no sense in both the case of IS_LONG and IS_STRING as 7.0 zval
1782
+ IS_STRING always copies.
1783
+ */
1767
1784
memcpy (bit_area , Z_STRVAL_P (current_field ), Z_STRLEN_P (current_field ));
1768
1785
bit_area += Z_STRLEN_P (current_field );
1769
1786
* bit_area ++ = '\0' ;
@@ -1847,7 +1864,15 @@ php_mysqlnd_rowp_read(void * _packet)
1847
1864
packet_type_to_statistic_packet_count [PROT_ROW_PACKET ],
1848
1865
1 );
1849
1866
1850
- /* packet->row_buffer->ptr is of size 'data_size + 1' */
1867
+ /*
1868
+ packet->row_buffer->ptr is of size 'data_size'
1869
+ in pre-7.0 it was really 'data_size + 1' although it was counted as 'data_size'
1870
+ The +1 was for the additional byte needed to \0 terminate the last string in the row.
1871
+ This was needed as the zvals of pre-7.0 could use external memory (no copy param to ZVAL_STRINGL).
1872
+ However, in 7.0+ the strings always copy. Thus this +1 byte was removed. Also the optimization or \0
1873
+ terminating every string, which did overwrite the lengths from the packet. For this reason we needed
1874
+ to keep (and copy) the lengths externally.
1875
+ */
1851
1876
packet -> header .size = data_size ;
1852
1877
packet -> row_buffer -> app = data_size ;
1853
1878
0 commit comments