@@ -1450,6 +1450,17 @@ PHP_FUNCTION(socket_bind)
1450
1450
return FAILURE; \
1451
1451
} \
1452
1452
} 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
+
1453
1464
static zend_result php_socket_afpacket_add_tcp (unsigned char * ipdata , struct sockaddr_ll sll , char * ifrname , zend_string * recv_buf ,
1454
1465
size_t slen , zval * szpayload , zval * zpayload , zval * obj , zval * arg2 , zval * arg5 , zval * arg6 ) {
1455
1466
struct tcphdr a ;
@@ -1614,7 +1625,7 @@ PHP_FUNCTION(socket_recvfrom)
1614
1625
}
1615
1626
#endif
1616
1627
1617
- recv_buf = zend_string_alloc (arg3 + 1 , 0 );
1628
+ recv_buf = zend_string_alloc (arg3 + 1 , false );
1618
1629
1619
1630
switch (php_sock -> type ) {
1620
1631
case AF_UNIX :
@@ -1700,6 +1711,7 @@ PHP_FUNCTION(socket_recvfrom)
1700
1711
zend_argument_value_error (1 , "must be SOCK_RAW socket type" );
1701
1712
RETURN_THROWS ();
1702
1713
}
1714
+ zend_string * dst_buf ;
1703
1715
slen = sizeof (sll );
1704
1716
memset (& sll , 0 , sizeof (sll ));
1705
1717
sll .sll_family = AF_PACKET ;
@@ -1726,7 +1738,18 @@ PHP_FUNCTION(socket_recvfrom)
1726
1738
RETURN_FALSE ;
1727
1739
}
1728
1740
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 ;
1730
1753
unsigned short protocol = ntohs (e -> h_proto );
1731
1754
unsigned char * payload ;
1732
1755
@@ -1739,7 +1762,13 @@ PHP_FUNCTION(socket_recvfrom)
1739
1762
1740
1763
switch (protocol ) {
1741
1764
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 ));
1743
1772
struct iphdr a ;
1744
1773
memcpy (& a , payload , sizeof (a ));
1745
1774
struct iphdr * ip = & a ;
@@ -1750,6 +1779,7 @@ PHP_FUNCTION(socket_recvfrom)
1750
1779
ZVAL_NULL (& zpayload );
1751
1780
zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("payload" ), & zpayload );
1752
1781
zend_update_property_string (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ));
1782
+ zend_string_efree (dst_buf );
1753
1783
zend_string_efree (recv_buf );
1754
1784
ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
1755
1785
ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
@@ -1760,7 +1790,6 @@ PHP_FUNCTION(socket_recvfrom)
1760
1790
zend_value_error ("invalid transport header length" );
1761
1791
RETURN_THROWS ();
1762
1792
}
1763
- unsigned char * ipdata = payload + tlayer ;
1764
1793
struct in_addr s , d ;
1765
1794
s .s_addr = ip -> saddr ;
1766
1795
d .s_addr = ip -> daddr ;
@@ -1773,13 +1802,31 @@ PHP_FUNCTION(socket_recvfrom)
1773
1802
1774
1803
switch (ip -> protocol ) {
1775
1804
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 );
1776
1812
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 );
1777
1815
RETURN_THROWS ();
1778
1816
}
1779
1817
break ;
1780
1818
}
1781
1819
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 );
1782
1827
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 );
1783
1830
RETURN_THROWS ();
1784
1831
}
1785
1832
break ;
@@ -1788,6 +1835,7 @@ PHP_FUNCTION(socket_recvfrom)
1788
1835
zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("payload" ), & zpayload );
1789
1836
zend_update_property_string (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ));
1790
1837
zend_string_efree (recv_buf );
1838
+ zend_string_efree (dst_buf );
1791
1839
Z_DELREF (zpayload );
1792
1840
ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
1793
1841
ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
@@ -1801,7 +1849,13 @@ PHP_FUNCTION(socket_recvfrom)
1801
1849
break ;
1802
1850
}
1803
1851
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 ));
1805
1859
struct ipv6hdr a ;
1806
1860
memcpy (& a , payload , sizeof (a ));
1807
1861
struct ipv6hdr * ip = & a ;
@@ -1811,6 +1865,7 @@ PHP_FUNCTION(socket_recvfrom)
1811
1865
zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("payload" ), & zpayload );
1812
1866
zend_update_property_string (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ));
1813
1867
zend_string_efree (recv_buf );
1868
+ zend_string_efree (dst_buf );
1814
1869
ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
1815
1870
ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
1816
1871
@@ -1830,17 +1885,34 @@ PHP_FUNCTION(socket_recvfrom)
1830
1885
zend_update_property_long (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("headerSize" ), totalip );
1831
1886
zend_update_property_stringl (Z_OBJCE (zpayload ), Z_OBJ (zpayload ), ZEND_STRL ("rawPacket" ), (char * )payload , totalip );
1832
1887
unsigned char ipprotocol = ip -> nexthdr ;
1833
- unsigned char * ipdata = payload + sizeof (* ip );
1834
1888
1835
1889
switch (ipprotocol ) {
1836
1890
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 );
1837
1898
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 );
1838
1901
RETURN_THROWS ();
1839
1902
}
1840
1903
break ;
1841
1904
}
1842
1905
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 );
1843
1913
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 );
1844
1916
RETURN_THROWS ();
1845
1917
}
1846
1918
break ;
@@ -1850,6 +1922,7 @@ PHP_FUNCTION(socket_recvfrom)
1850
1922
zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("payload" ), & zpayload );
1851
1923
zend_update_property_string (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ));
1852
1924
zend_string_efree (recv_buf );
1925
+ zend_string_efree (dst_buf );
1853
1926
Z_DELREF (zpayload );
1854
1927
ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
1855
1928
ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
@@ -1863,10 +1936,17 @@ PHP_FUNCTION(socket_recvfrom)
1863
1936
break ;
1864
1937
}
1865
1938
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 );
1867
1946
struct ethhdr a ;
1868
1947
if ((char * )payload + sizeof (a ) < ZSTR_VAL (recv_buf ) + slen ) {
1869
1948
zend_string_efree (recv_buf );
1949
+ zend_string_efree (dst_buf );
1870
1950
Z_DELREF (zpayload );
1871
1951
ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
1872
1952
ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
@@ -1895,6 +1975,8 @@ PHP_FUNCTION(socket_recvfrom)
1895
1975
zend_update_property (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("payload" ), & zpayload );
1896
1976
zend_update_property_string (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ));
1897
1977
zend_string_efree (recv_buf );
1978
+ zend_string_efree (dst_buf );
1979
+
1898
1980
ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
1899
1981
ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
1900
1982
@@ -1911,6 +1993,7 @@ PHP_FUNCTION(socket_recvfrom)
1911
1993
zend_update_property_string (Z_OBJCE (obj ), Z_OBJ (obj ), ZEND_STRL ("rawPacket" ), ZSTR_VAL (recv_buf ));
1912
1994
Z_DELREF (zpayload );
1913
1995
zend_string_efree (recv_buf );
1996
+ zend_string_free (dst_buf );
1914
1997
1915
1998
ZEND_TRY_ASSIGN_REF_VALUE (arg2 , & obj );
1916
1999
ZEND_TRY_ASSIGN_REF_STRING (arg5 , ifrname );
0 commit comments