@@ -1436,53 +1436,48 @@ PHP_FUNCTION(socket_bind)
14361436/* }}} */
14371437
14381438#ifdef AF_PACKET
1439- #define ETH_SUB_CHECKLENGTH (a , lyr ) \
1440- do { \
1441- if ((char *)ipdata + sizeof(a) < ZSTR_VAL(recv_buf) + slen) { \
1442- return FAILURE; \
1443- } \
1444- } while (0)
14451439
1446- static zend_result php_socket_get_chunk (zend_string * dst , const zend_string * src , size_t offset , size_t len ) {
1447- if (UNEXPECTED ((offset > SIZE_MAX - len ) || offset + len > ZSTR_LEN (src ))) {
1440+ struct php_socket_chunk {
1441+ const char * buf ;
1442+ size_t buf_len ;
1443+ size_t chunk_len ;
1444+ };
1445+
1446+ static zend_result php_socket_get_chunk (struct php_socket_chunk * dst , const struct php_socket_chunk * src , size_t offset , size_t len ) {
1447+ if (UNEXPECTED ((offset > SIZE_MAX - len ) || offset + len > src -> buf_len )) {
14481448 return FAILURE ;
14491449 }
14501450
1451- memcpy (ZSTR_VAL (dst ), ZSTR_VAL (src ) + offset , len + 1 );
1452- ZSTR_LEN (dst ) = len ;
1451+ dst -> buf = src -> buf + offset ;
1452+ dst -> chunk_len = len ;
1453+ dst -> buf_len = src -> buf_len - offset ;
14531454 return SUCCESS ;
14541455}
14551456
1456- static zend_result php_socket_afpacket_add_tcp (unsigned char * ipdata , struct sockaddr_ll sll , char * ifrname , zend_string * recv_buf ,
1457- size_t slen , zval * szpayload , zval * zpayload , zval * obj , zval * data , zval * addr , zval * index ) {
1457+ static void php_socket_afpacket_add_tcp (const char * ipdata , struct sockaddr_ll sll , char * ifrname ,
1458+ zval * szpayload , zval * zpayload ) {
14581459 struct tcphdr tcp ;
1459- if ((char * )ipdata + sizeof (tcp ) < ZSTR_VAL (recv_buf ) + slen )
1460- return FAILURE ;
14611460 memcpy (& tcp , ipdata , sizeof (tcp ));
14621461 object_init_ex (szpayload , tcppacket_ce );
14631462 zend_update_property_long (Z_OBJCE_P (szpayload ), Z_OBJ_P (szpayload ), ZEND_STRL ("srcPort" ), ntohs (tcp .th_sport ));
14641463 zend_update_property_long (Z_OBJCE_P (szpayload ), Z_OBJ_P (szpayload ), ZEND_STRL ("dstPort" ), ntohs (tcp .th_dport ));
14651464 zend_update_property_long (Z_OBJCE_P (szpayload ), Z_OBJ_P (szpayload ), ZEND_STRL ("headerSize" ), sizeof (tcp ));
1466- zend_update_property_stringl (Z_OBJCE_P (szpayload ), Z_OBJ_P (szpayload ), ZEND_STRL ("rawPacket" ), ( char * ) ipdata , sizeof (tcp ));
1465+ zend_update_property_stringl (Z_OBJCE_P (szpayload ), Z_OBJ_P (szpayload ), ZEND_STRL ("rawPacket" ), ipdata , sizeof (tcp ));
14671466 zend_update_property (Z_OBJCE_P (zpayload ), Z_OBJ_P (zpayload ), ZEND_STRL ("payload" ), szpayload );
14681467 Z_DELREF_P (szpayload );
1469- return SUCCESS ;
14701468}
14711469
1472- static zend_result php_socket_afpacket_add_udp (unsigned char * ipdata , struct sockaddr_ll sll , char * ifrname , zend_string * recv_buf ,
1473- size_t slen , zval * szpayload , zval * zpayload , zval * obj , zval * data , zval * addr , zval * index ) {
1470+ static void php_socket_afpacket_add_udp (const char * ipdata , struct sockaddr_ll sll , char * ifrname ,
1471+ zval * szpayload , zval * zpayload ) {
14741472 struct udphdr udp ;
1475- if ((char * )ipdata + sizeof (udp ) < ZSTR_VAL (recv_buf ) + slen )
1476- return FAILURE ;
14771473 memcpy (& udp , ipdata , sizeof (udp ));
14781474 object_init_ex (szpayload , udppacket_ce );
14791475 zend_update_property_long (Z_OBJCE_P (szpayload ), Z_OBJ_P (szpayload ), ZEND_STRL ("srcPort" ), ntohs (udp .uh_sport ));
14801476 zend_update_property_long (Z_OBJCE_P (szpayload ), Z_OBJ_P (szpayload ), ZEND_STRL ("dstPort" ), ntohs (udp .uh_dport ));
14811477 zend_update_property_long (Z_OBJCE_P (szpayload ), Z_OBJ_P (szpayload ), ZEND_STRL ("headerSize" ), sizeof (udp ));
1482- zend_update_property_stringl (Z_OBJCE_P (szpayload ), Z_OBJ_P (szpayload ), ZEND_STRL ("rawPacket" ), ( char * ) ipdata , sizeof (udp ));
1478+ zend_update_property_stringl (Z_OBJCE_P (szpayload ), Z_OBJ_P (szpayload ), ZEND_STRL ("rawPacket" ), ipdata , sizeof (udp ));
14831479 zend_update_property (Z_OBJCE_P (zpayload ), Z_OBJ_P (zpayload ), ZEND_STRL ("payload" ), szpayload );
14841480 Z_DELREF_P (szpayload );
1485- return SUCCESS ;
14861481}
14871482#endif
14881483
@@ -1701,14 +1696,18 @@ PHP_FUNCTION(socket_recvfrom)
17011696 int recv_flags = (int )arg4 ;
17021697 zval * addr = arg5 ;
17031698 zval * index = arg6 ;
1699+ if (recv_flags > 0 && !(recv_flags & (MSG_PEEK |MSG_DONTWAIT |MSG_ERRQUEUE ))) {
1700+ zend_argument_value_error (4 , "must set one the flags MSG_PEEK, MSG_DONTWAIT, MSG_ERRQUEUE" );
1701+ RETURN_THROWS ();
1702+ }
1703+
17041704 getsockopt (php_sock -> bsd_socket , SOL_SOCKET , SO_TYPE , (char * ) & protoid , & protoidlen );
17051705
17061706 // TODO: SOCK_DGRAM support
17071707 if (protoid != SOCK_RAW ) {
17081708 zend_argument_value_error (1 , "must be SOCK_RAW socket type" );
17091709 RETURN_THROWS ();
17101710 }
1711- zend_string * dst_buf ;
17121711 slen = sizeof (sll );
17131712 memset (& sll , 0 , sizeof (sll ));
17141713 sll .sll_family = AF_PACKET ;
@@ -1723,10 +1722,10 @@ PHP_FUNCTION(socket_recvfrom)
17231722 RETURN_FALSE ;
17241723 }
17251724
1726- if ( UNEXPECTED ( slen < ETH_HLEN )) {
1727- zend_value_error ( "invalid ethernet frame buffer length" );
1728- zend_string_efree ( recv_buf );
1729- RETURN_THROWS ( );
1725+ ZEND_ASSERT ( slen >= ETH_HLEN );
1726+
1727+ if ( retval < recv_len ) {
1728+ recv_buf = zend_string_truncate ( recv_buf , retval , 0 );
17301729 }
17311730
17321731 if (UNEXPECTED (!if_indextoname (sll .sll_ifindex , ifrname ))) {
@@ -1735,45 +1734,44 @@ PHP_FUNCTION(socket_recvfrom)
17351734 RETURN_FALSE ;
17361735 }
17371736
1738- dst_buf = zend_string_alloc (recv_len + 1 , false);
1737+ struct php_socket_chunk src_buf = {
1738+ .buf = ZSTR_VAL (recv_buf ),
1739+ .buf_len = ZSTR_LEN (recv_buf ),
1740+ .chunk_len = 0
1741+ };
1742+ struct php_socket_chunk dst_buf ;
17391743
1740- if (php_socket_get_chunk (dst_buf , recv_buf , 0 , ETH_HLEN ) == FAILURE ) {
1744+ if (php_socket_get_chunk (& dst_buf , & src_buf , 0 , ETH_HLEN ) == FAILURE ) {
17411745 zend_value_error ("invalid ethernet frame buffer length" );
1742- zend_string_release (dst_buf );
17431746 zend_string_efree (recv_buf );
17441747 RETURN_THROWS ();
17451748 }
17461749
17471750 struct ethhdr e ;
1748- memcpy (& e , ZSTR_VAL ( dst_buf ) , ETH_HLEN );
1751+ memcpy (& e , dst_buf . buf , ETH_HLEN );
17491752 unsigned short protocol = ntohs (e .h_proto );
1750- unsigned char * payload ;
17511753
17521754 zval obj ;
17531755 object_init_ex (& obj , ethpacket_ce );
17541756 zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("socket" ), socket );
17551757 zend_update_property_long (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("headerSize" ), ETH_HLEN );
17561758 zend_update_property_long (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("ethProtocol" ), protocol );
17571759
1758-
17591760 switch (protocol ) {
17601761 case ETH_P_IP : {
1761- if (php_socket_get_chunk (dst_buf , recv_buf , ETH_HLEN , sizeof (struct iphdr )) == FAILURE ) {
1762+ if (php_socket_get_chunk (& dst_buf , & src_buf , 0 , sizeof (struct iphdr )) == FAILURE ) {
17621763 zval_ptr_dtor (& obj );
1763- zend_string_release (dst_buf );
17641764 zend_string_efree (recv_buf );
17651765 zend_value_error ("invalid ipv4 frame buffer length" );
17661766 RETURN_THROWS ();
17671767 }
1768- payload = ((unsigned char * )ZSTR_VAL (dst_buf ));
17691768 struct iphdr ip ;
1770- memcpy (& ip , payload , sizeof (ip ));
1769+ memcpy (& ip , dst_buf . buf , sizeof (ip ));
17711770 size_t tlayer = ip .ihl * 4 ;
17721771 size_t totalip = ntohs (ip .tot_len );
17731772
1774- if (php_socket_get_chunk (dst_buf , recv_buf , tlayer , totalip )) {
1773+ if (php_socket_get_chunk (& dst_buf , & src_buf , tlayer , totalip )) {
17751774 zval_ptr_dtor (& obj );
1776- zend_string_release (dst_buf );
17771775 zend_string_efree (recv_buf );
17781776 zend_value_error ("invalid transport header length" );
17791777 RETURN_THROWS ();
@@ -1786,75 +1784,53 @@ PHP_FUNCTION(socket_recvfrom)
17861784 zend_update_property_string (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("srcAddr" ), inet_ntoa (s ));
17871785 zend_update_property_string (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("dstAddr" ), inet_ntoa (d ));
17881786 zend_update_property_long (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("headerSize" ), totalip );
1789- zend_update_property_stringl (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("rawPacket" ), (char * )payload , ZSTR_LEN ( dst_buf ) );
1787+ zend_update_property_stringl (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("rawPacket" ), (char * )dst_buf . buf , dst_buf . chunk_len );
17901788
17911789 switch (ip .protocol ) {
17921790 case IPPROTO_TCP : {
1793- if (php_socket_get_chunk (dst_buf , recv_buf , tlayer , sizeof (struct tcphdr )) == FAILURE ) {
1794- zval_ptr_dtor (& zpayload );
1795- zval_ptr_dtor (& obj );
1796- zend_string_release (dst_buf );
1797- zend_string_efree (recv_buf );
1798- zend_value_error ("invalid tcp frame buffer length" );
1799- RETURN_THROWS ();
1800- }
1801- unsigned char * ipdata = (unsigned char * )ZSTR_VAL (dst_buf );
1802- if (php_socket_afpacket_add_tcp (ipdata , sll , ifrname , recv_buf , slen , & szpayload , & zpayload , & obj , data , addr , index ) == FAILURE ) {
1791+ if (php_socket_get_chunk (& dst_buf , & src_buf , tlayer , sizeof (struct tcphdr )) == FAILURE ) {
18031792 zval_ptr_dtor (& zpayload );
18041793 zval_ptr_dtor (& obj );
1805- zend_string_release (dst_buf );
18061794 zend_string_efree (recv_buf );
18071795 zend_value_error ("invalid tcp frame buffer length" );
18081796 RETURN_THROWS ();
18091797 }
1798+ php_socket_afpacket_add_tcp (dst_buf .buf , sll , ifrname , & szpayload , & zpayload );
18101799 break ;
18111800 }
18121801 case IPPROTO_UDP : {
1813- if (php_socket_get_chunk (dst_buf , recv_buf , tlayer , sizeof (struct udphdr )) == FAILURE ) {
1802+ if (php_socket_get_chunk (& dst_buf , & src_buf , tlayer , sizeof (struct udphdr )) == FAILURE ) {
18141803 zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("payload" ), & zpayload );
18151804 zend_update_property_stringl (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ), ZSTR_LEN (recv_buf ));
18161805 Z_DELREF_P (& zpayload );
1817- zend_string_release (dst_buf );
1818- zend_string_efree (recv_buf );
1819- zend_value_error ("invalid udp frame buffer length" );
1820- RETURN_THROWS ();
1821- }
1822- unsigned char * ipdata = (unsigned char * )ZSTR_VAL (dst_buf );
1823- if (php_socket_afpacket_add_udp (ipdata , sll , ifrname , recv_buf , slen , & szpayload , & zpayload , & obj , data , addr , index ) == FAILURE ) {
1824- zval_ptr_dtor (& zpayload );
1825- zval_ptr_dtor (& obj );
1826- zend_string_release (dst_buf );
18271806 zend_string_efree (recv_buf );
18281807 zend_value_error ("invalid udp frame buffer length" );
18291808 RETURN_THROWS ();
18301809 }
1810+ php_socket_afpacket_add_udp (dst_buf .buf , sll , ifrname , & szpayload , & zpayload );
18311811 break ;
18321812 }
18331813 default :
18341814 zval_ptr_dtor (& zpayload );
18351815 zval_ptr_dtor (& obj );
1836- zend_string_release (dst_buf );
18371816 zend_string_efree (recv_buf );
18381817 zend_value_error ("unsupported ip header protocol" );
18391818 RETURN_THROWS ();
18401819 }
18411820 break ;
18421821 }
18431822 case ETH_P_IPV6 : {
1844- if (php_socket_get_chunk (dst_buf , recv_buf , ETH_HLEN , sizeof (struct iphdr )) == FAILURE ) {
1823+ if (php_socket_get_chunk (& dst_buf , & src_buf , ETH_HLEN , sizeof (struct iphdr )) == FAILURE ) {
18451824 zval_ptr_dtor (& obj );
1846- zend_string_release (dst_buf );
18471825 zend_string_efree (recv_buf );
18481826 zend_value_error ("invalid ipv4 frame buffer length" );
18491827 RETURN_THROWS ();
18501828 }
1851- payload = ((unsigned char * )ZSTR_VAL (dst_buf ));
18521829 struct ipv6hdr ip ;
1853- memcpy (& ip , payload , sizeof (ip ));
1830+ memcpy (& ip , dst_buf . buf , sizeof (ip ));
18541831 size_t totalip = sizeof (ip ) + ip .payload_len ;
18551832 if (totalip < slen ) {
18561833 zval_ptr_dtor (& obj );
1857- zend_string_release (dst_buf );
18581834 zend_string_efree (recv_buf );
18591835 zend_value_error ("invalid transport header length" );
18601836 RETURN_THROWS ();
@@ -1867,97 +1843,74 @@ PHP_FUNCTION(socket_recvfrom)
18671843 zend_update_property_string (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("srcAddr" ), s );
18681844 zend_update_property_string (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("dstAddr" ), d );
18691845 zend_update_property_long (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("headerSize" ), totalip );
1870- zend_update_property_stringl (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("rawPacket" ), (char * )payload , totalip );
1846+ zend_update_property_stringl (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("rawPacket" ), (char * )dst_buf . buf , totalip );
18711847 unsigned char ipprotocol = ip .nexthdr ;
18721848
18731849 switch (ipprotocol ) {
18741850 case IPPROTO_TCP : {
1875- if (php_socket_get_chunk (dst_buf , recv_buf , sizeof (ip ), sizeof (struct tcphdr )) == FAILURE ) {
1876- zval_ptr_dtor (& zpayload );
1877- zval_ptr_dtor (& obj );
1878- zend_string_release (dst_buf );
1879- zend_string_efree (recv_buf );
1880- zend_value_error ("invalid tcp frame buffer length" );
1881- RETURN_THROWS ();
1882- }
1883- unsigned char * ipdata = (unsigned char * )ZSTR_VAL (dst_buf );
1884- if (php_socket_afpacket_add_tcp (ipdata , sll , ifrname , recv_buf , slen , & szpayload , & zpayload , & obj , data , addr , index ) == FAILURE ) {
1851+ if (php_socket_get_chunk (& dst_buf , & src_buf , sizeof (ip ), sizeof (struct tcphdr )) == FAILURE ) {
18851852 zval_ptr_dtor (& zpayload );
18861853 zval_ptr_dtor (& obj );
1887- zend_string_release (dst_buf );
18881854 zend_string_efree (recv_buf );
18891855 zend_value_error ("invalid tcp frame buffer length" );
18901856 RETURN_THROWS ();
18911857 }
1858+ php_socket_afpacket_add_tcp (dst_buf .buf , sll , ifrname , & szpayload , & zpayload );
18921859 break ;
18931860 }
18941861 case IPPROTO_UDP : {
1895- if (php_socket_get_chunk (dst_buf , recv_buf , sizeof (ip ), sizeof (struct udphdr )) == FAILURE ) {
1896- zval_ptr_dtor (& zpayload );
1897- zval_ptr_dtor (& obj );
1898- zend_string_release (dst_buf );
1899- zend_string_efree (recv_buf );
1900- zend_value_error ("invalid udp frame buffer length" );
1901- RETURN_THROWS ();
1902- }
1903- unsigned char * ipdata = (unsigned char * )ZSTR_VAL (dst_buf );
1904- if (php_socket_afpacket_add_udp (ipdata , sll , ifrname , recv_buf , slen , & szpayload , & zpayload , & obj , data , addr , data ) == FAILURE ) {
1862+ if (php_socket_get_chunk (& dst_buf , & src_buf , sizeof (ip ), sizeof (struct udphdr )) == FAILURE ) {
19051863 zval_ptr_dtor (& zpayload );
19061864 zval_ptr_dtor (& obj );
1907- zend_string_release (dst_buf );
19081865 zend_string_efree (recv_buf );
19091866 zend_value_error ("invalid udp frame buffer length" );
19101867 RETURN_THROWS ();
19111868 }
1869+ php_socket_afpacket_add_udp (dst_buf .buf , sll , ifrname , & szpayload , & zpayload );
19121870 break ;
19131871 }
19141872 // TODO IPPROTO_ICMPV6 support
19151873 default :
19161874 zval_ptr_dtor (& zpayload );
19171875 zval_ptr_dtor (& obj );
19181876 zend_string_efree (recv_buf );
1919- zend_string_release (dst_buf );
19201877 zend_value_error ("unsupported ipv6 header protocol" );
19211878 RETURN_THROWS ();
19221879 }
19231880 break ;
19241881 }
19251882 case ETH_P_LOOP : {
1926- if (php_socket_get_chunk (dst_buf , recv_buf , ETH_HLEN , ETH_HLEN ) == FAILURE ) {
1883+ if (php_socket_get_chunk (& dst_buf , & src_buf , ETH_HLEN , ETH_HLEN ) == FAILURE ) {
19271884 zval_ptr_dtor (& zpayload );
19281885 zval_ptr_dtor (& obj );
19291886 zend_string_efree (recv_buf );
1930- zend_string_release (dst_buf );
19311887 zend_value_error ("invalid ethernet frame buffer length" );
19321888 RETURN_THROWS ();
19331889 }
19341890 struct ethhdr innere ;
1935- payload = (unsigned char * )ZSTR_VAL (dst_buf );
1936- if ((char * )payload + sizeof (innere ) < ZSTR_VAL (recv_buf ) + slen ) {
1891+ if ((char * )dst_buf .buf + sizeof (innere ) < ZSTR_VAL (recv_buf ) + slen ) {
19371892 zval_ptr_dtor (& zpayload );
19381893 zval_ptr_dtor (& obj );
1939- zend_string_release (dst_buf );
19401894 zend_string_efree (recv_buf );
19411895 zend_value_error ("invalid ethernet loop header" );
19421896 RETURN_THROWS ();
19431897 }
1944- memcpy (& innere , payload , sizeof (innere ));
1898+ memcpy (& innere , dst_buf . buf , sizeof (innere ));
19451899 zval innerp ;
19461900 ZVAL_NULL (& innerp );
19471901 object_init_ex (& zpayload , ethpacket_ce );
19481902 zend_update_property_string (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("srcMac" ), ether_ntoa ((struct ether_addr * )innere .h_source ));
19491903 zend_update_property_string (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("dstMac" ), ether_ntoa ((struct ether_addr * )innere .h_dest ));
19501904 zend_update_property_long (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("headerSize" ), ETH_HLEN );
19511905 zend_update_property (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("socket" ), socket );
1952- zend_update_property (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("rawPacket" ), & innerp );
1906+ zend_update_property_stringl (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("rawPacket" ), ( char * ) dst_buf . buf , dst_buf . chunk_len );
19531907 zend_update_property (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("payload" ), & innerp );
19541908 zend_update_property_long (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("ethProtocol" ), 0 );
19551909 break ;
19561910 }
19571911 default :
19581912 zval_ptr_dtor (& zpayload );
19591913 zval_ptr_dtor (& obj );
1960- zend_string_release (dst_buf );
19611914 zend_string_efree (recv_buf );
19621915 zend_value_error ("unsupported ethernet protocol" );
19631916 RETURN_THROWS ();
@@ -1968,7 +1921,6 @@ PHP_FUNCTION(socket_recvfrom)
19681921 zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("payload" ), & zpayload );
19691922 zend_update_property_stringl (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ), ZSTR_LEN (recv_buf ));
19701923 Z_DELREF (zpayload );
1971- zend_string_release (dst_buf );
19721924 zend_string_efree (recv_buf );
19731925
19741926 ZEND_TRY_ASSIGN_REF_VALUE (data , & obj );
0 commit comments