@@ -1450,6 +1450,17 @@ PHP_FUNCTION(socket_bind)
14501450 return FAILURE; \
14511451 } \
14521452 } while (0)
1453+
1454+ static zend_result php_socket_get_chunk (zend_string * dst , const zend_string * src , size_t offset , size_t len ) {
1455+ if (UNEXPECTED ((offset > SIZE_MAX - len ) || offset + len > ZSTR_LEN (src ))) {
1456+ return FAILURE ;
1457+ }
1458+
1459+ memcpy (ZSTR_VAL (dst ), ZSTR_VAL (src ) + offset , len );
1460+ ZSTR_LEN (dst ) = len ;
1461+ return SUCCESS ;
1462+ }
1463+
14531464static zend_result php_socket_afpacket_add_tcp (unsigned char * ipdata , struct sockaddr_ll sll , char * ifrname , zend_string * recv_buf ,
14541465 size_t slen , zval * szpayload , zval * zpayload , zval * obj , zval * arg2 , zval * arg5 , zval * arg6 ) {
14551466 struct tcphdr a ;
@@ -1614,7 +1625,7 @@ PHP_FUNCTION(socket_recvfrom)
16141625 }
16151626#endif
16161627
1617- recv_buf = zend_string_alloc (arg3 + 1 , 0 );
1628+ recv_buf = zend_string_alloc (arg3 + 1 , false );
16181629
16191630 switch (php_sock -> type ) {
16201631 case AF_UNIX :
@@ -1700,6 +1711,7 @@ PHP_FUNCTION(socket_recvfrom)
17001711 zend_argument_value_error (1 , "must be SOCK_RAW socket type" );
17011712 RETURN_THROWS ();
17021713 }
1714+ zend_string * dst_buf ;
17031715 slen = sizeof (sll );
17041716 memset (& sll , 0 , sizeof (sll ));
17051717 sll .sll_family = AF_PACKET ;
@@ -1726,7 +1738,18 @@ PHP_FUNCTION(socket_recvfrom)
17261738 RETURN_FALSE ;
17271739 }
17281740
1729- struct ethhdr * e = (struct ethhdr * )ZSTR_VAL (recv_buf );
1741+ dst_buf = zend_string_alloc (arg3 , false);
1742+
1743+ if (php_socket_get_chunk (dst_buf , recv_buf , 0 , ETH_HLEN ) == FAILURE ) {
1744+ zend_value_error ("invalid ethernet frame buffer length" );
1745+ zend_string_efree (dst_buf );
1746+ zend_string_efree (recv_buf );
1747+ RETURN_THROWS ();
1748+ }
1749+
1750+ struct ethhdr a ;
1751+ memcpy (& a , ZSTR_VAL (dst_buf ), ETH_HLEN );
1752+ struct ethhdr * e = & a ;
17301753 unsigned short protocol = ntohs (e -> h_proto );
17311754 unsigned char * payload ;
17321755
@@ -1739,7 +1762,13 @@ PHP_FUNCTION(socket_recvfrom)
17391762
17401763 switch (protocol ) {
17411764 case ETH_P_IP : {
1742- payload = ((unsigned char * )e + ETH_HLEN );
1765+ if (php_socket_get_chunk (dst_buf , recv_buf , ETH_HLEN , sizeof (struct iphdr )) == FAILURE ) {
1766+ zend_value_error ("invalid ipv4 frame buffer length" );
1767+ zend_string_efree (dst_buf );
1768+ zend_string_efree (recv_buf );
1769+ RETURN_THROWS ();
1770+ }
1771+ payload = ((unsigned char * )ZSTR_VAL (dst_buf ));
17431772 struct iphdr a ;
17441773 memcpy (& a , payload , sizeof (a ));
17451774 struct iphdr * ip = & a ;
@@ -1750,6 +1779,7 @@ PHP_FUNCTION(socket_recvfrom)
17501779 ZVAL_NULL (& zpayload );
17511780 zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("payload" ), & zpayload );
17521781 zend_update_property_string (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ));
1782+ zend_string_efree (dst_buf );
17531783 zend_string_efree (recv_buf );
17541784 ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
17551785 ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
@@ -1760,7 +1790,6 @@ PHP_FUNCTION(socket_recvfrom)
17601790 zend_value_error ("invalid transport header length" );
17611791 RETURN_THROWS ();
17621792 }
1763- unsigned char * ipdata = payload + tlayer ;
17641793 struct in_addr s , d ;
17651794 s .s_addr = ip -> saddr ;
17661795 d .s_addr = ip -> daddr ;
@@ -1773,13 +1802,31 @@ PHP_FUNCTION(socket_recvfrom)
17731802
17741803 switch (ip -> protocol ) {
17751804 case IPPROTO_TCP : {
1805+ if (php_socket_get_chunk (dst_buf , recv_buf , tlayer , sizeof (struct tcphdr )) == FAILURE ) {
1806+ zend_value_error ("invalid tcp frame buffer length" );
1807+ zend_string_efree (dst_buf );
1808+ zend_string_efree (recv_buf );
1809+ RETURN_THROWS ();
1810+ }
1811+ unsigned char * ipdata = (unsigned char * )ZSTR_VAL (dst_buf );
17761812 if (php_socket_afpacket_add_tcp (ipdata , sll , ifrname , recv_buf , slen , & szpayload , & zpayload , & obj , arg2 , arg5 , arg6 ) == FAILURE ) {
1813+ zend_string_efree (dst_buf );
1814+ zend_string_efree (recv_buf );
17771815 RETURN_THROWS ();
17781816 }
17791817 break ;
17801818 }
17811819 case IPPROTO_UDP : {
1820+ if (php_socket_get_chunk (dst_buf , recv_buf , tlayer , sizeof (struct udphdr )) == FAILURE ) {
1821+ zend_value_error ("invalid udp frame buffer length" );
1822+ zend_string_efree (dst_buf );
1823+ zend_string_efree (recv_buf );
1824+ RETURN_THROWS ();
1825+ }
1826+ unsigned char * ipdata = (unsigned char * )ZSTR_VAL (dst_buf );
17821827 if (php_socket_afpacket_add_udp (ipdata , sll , ifrname , recv_buf , slen , & szpayload , & zpayload , & obj , arg2 , arg5 , arg6 ) == FAILURE ) {
1828+ zend_string_efree (dst_buf );
1829+ zend_string_efree (recv_buf );
17831830 RETURN_THROWS ();
17841831 }
17851832 break ;
@@ -1788,6 +1835,7 @@ PHP_FUNCTION(socket_recvfrom)
17881835 zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("payload" ), & zpayload );
17891836 zend_update_property_string (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ));
17901837 zend_string_efree (recv_buf );
1838+ zend_string_efree (dst_buf );
17911839 Z_DELREF (zpayload );
17921840 ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
17931841 ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
@@ -1801,7 +1849,13 @@ PHP_FUNCTION(socket_recvfrom)
18011849 break ;
18021850 }
18031851 case ETH_P_IPV6 : {
1804- payload = ((unsigned char * )e + ETH_HLEN );
1852+ if (php_socket_get_chunk (dst_buf , recv_buf , ETH_HLEN , sizeof (struct iphdr )) == FAILURE ) {
1853+ zend_value_error ("invalid ipv4 frame buffer length" );
1854+ zend_string_efree (dst_buf );
1855+ zend_string_efree (recv_buf );
1856+ RETURN_THROWS ();
1857+ }
1858+ payload = ((unsigned char * )ZSTR_VAL (dst_buf ));
18051859 struct ipv6hdr a ;
18061860 memcpy (& a , payload , sizeof (a ));
18071861 struct ipv6hdr * ip = & a ;
@@ -1811,6 +1865,7 @@ PHP_FUNCTION(socket_recvfrom)
18111865 zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("payload" ), & zpayload );
18121866 zend_update_property_string (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ));
18131867 zend_string_efree (recv_buf );
1868+ zend_string_efree (dst_buf );
18141869 ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
18151870 ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
18161871
@@ -1830,17 +1885,34 @@ PHP_FUNCTION(socket_recvfrom)
18301885 zend_update_property_long (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("headerSize" ), totalip );
18311886 zend_update_property_stringl (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("rawPacket" ), (char * )payload , totalip );
18321887 unsigned char ipprotocol = ip -> nexthdr ;
1833- unsigned char * ipdata = payload + sizeof (* ip );
18341888
18351889 switch (ipprotocol ) {
18361890 case IPPROTO_TCP : {
1891+ if (php_socket_get_chunk (dst_buf , recv_buf , sizeof (* ip ), sizeof (struct tcphdr )) == FAILURE ) {
1892+ zend_value_error ("invalid tcp frame buffer length" );
1893+ zend_string_efree (dst_buf );
1894+ zend_string_efree (recv_buf );
1895+ RETURN_THROWS ();
1896+ }
1897+ unsigned char * ipdata = (unsigned char * )ZSTR_VAL (dst_buf );
18371898 if (php_socket_afpacket_add_tcp (ipdata , sll , ifrname , recv_buf , slen , & szpayload , & zpayload , & obj , arg2 , arg5 , arg6 ) == FAILURE ) {
1899+ zend_string_efree (dst_buf );
1900+ zend_string_efree (recv_buf );
18381901 RETURN_THROWS ();
18391902 }
18401903 break ;
18411904 }
18421905 case IPPROTO_UDP : {
1906+ if (php_socket_get_chunk (dst_buf , recv_buf , sizeof (* ip ), sizeof (struct udphdr )) == FAILURE ) {
1907+ zend_value_error ("invalid udp frame buffer length" );
1908+ zend_string_efree (dst_buf );
1909+ zend_string_efree (recv_buf );
1910+ RETURN_THROWS ();
1911+ }
1912+ unsigned char * ipdata = (unsigned char * )ZSTR_VAL (dst_buf );
18431913 if (php_socket_afpacket_add_udp (ipdata , sll , ifrname , recv_buf , slen , & szpayload , & zpayload , & obj , arg2 , arg5 , arg6 ) == FAILURE ) {
1914+ zend_string_efree (dst_buf );
1915+ zend_string_efree (recv_buf );
18441916 RETURN_THROWS ();
18451917 }
18461918 break ;
@@ -1850,6 +1922,7 @@ PHP_FUNCTION(socket_recvfrom)
18501922 zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("payload" ), & zpayload );
18511923 zend_update_property_string (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ));
18521924 zend_string_efree (recv_buf );
1925+ zend_string_efree (dst_buf );
18531926 Z_DELREF (zpayload );
18541927 ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
18551928 ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
@@ -1863,10 +1936,17 @@ PHP_FUNCTION(socket_recvfrom)
18631936 break ;
18641937 }
18651938 case ETH_P_LOOP : {
1866- payload = ((unsigned char * )e + ETH_HLEN );
1939+ if (php_socket_get_chunk (dst_buf , recv_buf , ETH_HLEN , ETH_HLEN ) == FAILURE ) {
1940+ zend_value_error ("invalid ethernet frame buffer length" );
1941+ zend_string_efree (recv_buf );
1942+ zend_string_efree (dst_buf );
1943+ RETURN_THROWS ();
1944+ }
1945+ payload = (unsigned char * )ZSTR_VAL (dst_buf );
18671946 struct ethhdr a ;
18681947 if ((char * )payload + sizeof (a ) < ZSTR_VAL (recv_buf ) + slen ) {
18691948 zend_string_efree (recv_buf );
1949+ zend_string_efree (dst_buf );
18701950 Z_DELREF (zpayload );
18711951 ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
18721952 ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
@@ -1895,6 +1975,8 @@ PHP_FUNCTION(socket_recvfrom)
18951975 zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("payload" ), & zpayload );
18961976 zend_update_property_string (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ));
18971977 zend_string_efree (recv_buf );
1978+ zend_string_efree (dst_buf );
1979+
18981980 ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
18991981 ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
19001982
@@ -1911,6 +1993,7 @@ PHP_FUNCTION(socket_recvfrom)
19111993 zend_update_property_string (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ));
19121994 Z_DELREF (zpayload );
19131995 zend_string_efree (recv_buf );
1996+ zend_string_free (dst_buf );
19141997
19151998 ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
19161999 ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
0 commit comments