Skip to content

Commit e74589a

Browse files
committed
address most of remarks
1 parent d23895d commit e74589a

File tree

1 file changed

+96
-41
lines changed

1 file changed

+96
-41
lines changed

ext/sockets/sockets.c

+96-41
Original file line numberDiff line numberDiff line change
@@ -1435,6 +1435,54 @@ PHP_FUNCTION(socket_bind)
14351435
}
14361436
/* }}} */
14371437

1438+
#ifdef AF_PACKET
1439+
#define ETH_SUB_CHECKLENGTH(a, lyr) \
1440+
do { \
1441+
if ((char *)ipdata + sizeof(a) < ZSTR_VAL(recv_buf) + slen) { \
1442+
zend_string_efree(recv_buf); \
1443+
Z_DELREF_P(zpayload); \
1444+
ZEND_TRY_ASSIGN_REF_VALUE(arg2, obj); \
1445+
ZEND_TRY_ASSIGN_REF_STRING(arg5, ifrname); \
1446+
if (arg6) { \
1447+
ZEND_TRY_ASSIGN_REF_LONG(arg6, sll.sll_ifindex);\
1448+
} \
1449+
zend_value_error("invalid %s header", lyr); \
1450+
return FAILURE; \
1451+
} \
1452+
} while (0)
1453+
static zend_result php_socket_afpacket_add_tcp(unsigned char *ipdata, struct sockaddr_ll sll, char *ifrname, zend_string *recv_buf,
1454+
size_t slen, zval *szpayload, zval *zpayload, zval *obj, zval *arg2, zval *arg5, zval *arg6) {
1455+
struct tcphdr a;
1456+
ETH_SUB_CHECKLENGTH(a, "TCP");
1457+
memcpy(&a, ipdata, sizeof(a));
1458+
struct tcphdr *tcp = &a;
1459+
object_init_ex(szpayload, tcppacket_ce);
1460+
zend_update_property_long(Z_OBJCE_P(szpayload), Z_OBJ_P(szpayload), ZEND_STRL("srcPort"), ntohs(tcp->th_sport));
1461+
zend_update_property_long(Z_OBJCE_P(szpayload), Z_OBJ_P(szpayload), ZEND_STRL("dstPort"), ntohs(tcp->th_dport));
1462+
zend_update_property_long(Z_OBJCE_P(szpayload), Z_OBJ_P(szpayload), ZEND_STRL("headerSize"), sizeof(*tcp));
1463+
zend_update_property_string(Z_OBJCE_P(szpayload), Z_OBJ_P(szpayload), ZEND_STRL("rawPacket"), (char *)ipdata);
1464+
zend_update_property(Z_OBJCE_P(zpayload), Z_OBJ_P(zpayload), ZEND_STRL("payload"), szpayload);
1465+
Z_DELREF_P(szpayload);
1466+
return SUCCESS;
1467+
}
1468+
1469+
static zend_result php_socket_afpacket_add_udp(unsigned char *ipdata, struct sockaddr_ll sll, char *ifrname, zend_string *recv_buf,
1470+
size_t slen, zval *szpayload, zval *zpayload, zval *obj, zval *arg2, zval *arg5, zval *arg6) {
1471+
struct udphdr a;
1472+
ETH_SUB_CHECKLENGTH(a, "UDP");
1473+
memcpy(&a, ipdata, sizeof(a));
1474+
struct udphdr *udp = &a;
1475+
object_init_ex(szpayload, udppacket_ce);
1476+
zend_update_property_long(Z_OBJCE_P(szpayload), Z_OBJ_P(szpayload), ZEND_STRL("srcPort"), ntohs(udp->uh_sport));
1477+
zend_update_property_long(Z_OBJCE_P(szpayload), Z_OBJ_P(szpayload), ZEND_STRL("dstPort"), ntohs(udp->uh_dport));
1478+
zend_update_property_long(Z_OBJCE_P(szpayload), Z_OBJ_P(szpayload), ZEND_STRL("headerSize"), sizeof(*udp));
1479+
zend_update_property_string(Z_OBJCE_P(szpayload), Z_OBJ_P(szpayload), ZEND_STRL("rawPacket"), (char *)ipdata);
1480+
zend_update_property(Z_OBJCE_P(zpayload), Z_OBJ_P(zpayload), ZEND_STRL("payload"), szpayload);
1481+
Z_DELREF_P(szpayload);
1482+
return SUCCESS;
1483+
}
1484+
#endif
1485+
14381486
/* {{{ Receives data from a connected socket */
14391487
PHP_FUNCTION(socket_recv)
14401488
{
@@ -1665,6 +1713,12 @@ PHP_FUNCTION(socket_recvfrom)
16651713
RETURN_FALSE;
16661714
}
16671715

1716+
if (UNEXPECTED(slen < ETH_HLEN)) {
1717+
zend_value_error("invalid ethernet frame buffer length");
1718+
zend_string_efree(recv_buf);
1719+
RETURN_THROWS();
1720+
}
1721+
16681722
if (UNEXPECTED(!if_indextoname(sll.sll_ifindex, ifrname))) {
16691723
PHP_SOCKET_ERROR(php_sock, "unable to get the interface name", errno);
16701724
zend_string_efree(recv_buf);
@@ -1681,6 +1735,7 @@ PHP_FUNCTION(socket_recvfrom)
16811735
zend_update_property_long(Z_OBJCE(obj), Z_OBJ(obj), ZEND_STRL("headerSize"), ETH_HLEN);
16821736
zend_update_property_long(Z_OBJCE(obj), Z_OBJ(obj), ZEND_STRL("ethProtocol"), protocol);
16831737

1738+
16841739
switch (protocol) {
16851740
case ETH_P_IP: {
16861741
payload = ((unsigned char *)e + ETH_HLEN);
@@ -1717,29 +1772,15 @@ PHP_FUNCTION(socket_recvfrom)
17171772

17181773
switch (ip->protocol) {
17191774
case IPPROTO_TCP: {
1720-
struct tcphdr a;
1721-
memcpy(&a, ipdata, sizeof(a));
1722-
struct tcphdr *tcp = &a;
1723-
object_init_ex(&szpayload, tcppacket_ce);
1724-
zend_update_property_long(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("srcPort"), ntohs(tcp->th_sport));
1725-
zend_update_property_long(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("dstPort"), ntohs(tcp->th_dport));
1726-
zend_update_property_long(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("headerSize"), sizeof(*tcp));
1727-
zend_update_property_string(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("rawPacket"), (char *)ipdata);
1728-
zend_update_property(Z_OBJCE(zpayload), Z_OBJ(zpayload), ZEND_STRL("payload"), &szpayload);
1729-
Z_DELREF(szpayload);
1775+
if (php_socket_afpacket_add_tcp(ipdata, sll, ifrname, recv_buf, slen, &szpayload, &zpayload, &obj, arg2, arg5, arg6) == FAILURE) {
1776+
RETURN_THROWS();
1777+
}
17301778
break;
17311779
}
17321780
case IPPROTO_UDP: {
1733-
struct udphdr a;
1734-
memcpy(&a, ipdata, sizeof(a));
1735-
struct udphdr *udp = &a;
1736-
object_init_ex(&szpayload, udppacket_ce);
1737-
zend_update_property_long(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("srcPort"), ntohs(udp->uh_sport));
1738-
zend_update_property_long(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("dstPort"), ntohs(udp->uh_dport));
1739-
zend_update_property_long(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("headerSize"), sizeof(*udp));
1740-
zend_update_property_string(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("rawPacket"), (char *)ipdata);
1741-
zend_update_property(Z_OBJCE(zpayload), Z_OBJ(zpayload), ZEND_STRL("payload"), &szpayload);
1742-
Z_DELREF(szpayload);
1781+
if (php_socket_afpacket_add_udp(ipdata, sll, ifrname, recv_buf, slen, &szpayload, &zpayload, &obj, arg2, arg5, arg6) == FAILURE) {
1782+
RETURN_THROWS();
1783+
}
17431784
break;
17441785
}
17451786
default:
@@ -1764,6 +1805,20 @@ PHP_FUNCTION(socket_recvfrom)
17641805
memcpy(&a, payload, sizeof(a));
17651806
struct ipv6hdr *ip = &a;
17661807
size_t totalip = sizeof(*ip) + ip->payload_len;
1808+
if (totalip < slen) {
1809+
ZVAL_NULL(&zpayload);
1810+
zend_update_property(Z_OBJCE(obj), Z_OBJ(obj), ZEND_STRL("payload"), &zpayload);
1811+
zend_update_property_string(Z_OBJCE(obj), Z_OBJ(obj), ZEND_STRL("rawPacket"), ZSTR_VAL(recv_buf));
1812+
zend_string_efree(recv_buf);
1813+
ZEND_TRY_ASSIGN_REF_VALUE(arg2, &obj);
1814+
ZEND_TRY_ASSIGN_REF_STRING(arg5, ifrname);
1815+
1816+
if (arg6) {
1817+
ZEND_TRY_ASSIGN_REF_LONG(arg6, sll.sll_ifindex);
1818+
}
1819+
zend_value_error("invalid transport header length");
1820+
RETURN_THROWS();
1821+
}
17671822
char s[INET6_ADDRSTRLEN], d[INET6_ADDRSTRLEN];
17681823
inet_ntop(AF_INET6, &ip->saddr, s, sizeof(s));
17691824
inet_ntop(AF_INET6, &ip->daddr, d, sizeof(d));
@@ -1778,29 +1833,15 @@ PHP_FUNCTION(socket_recvfrom)
17781833

17791834
switch (ipprotocol) {
17801835
case IPPROTO_TCP: {
1781-
struct tcphdr a;
1782-
memcpy(&a, ipdata, sizeof(a));
1783-
struct tcphdr *tcp = &a;
1784-
object_init_ex(&szpayload, tcppacket_ce);
1785-
zend_update_property_long(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("srcPort"), ntohs(tcp->th_sport));
1786-
zend_update_property_long(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("dstPort"), ntohs(tcp->th_dport));
1787-
zend_update_property_long(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("headerSize"), sizeof(*tcp));
1788-
zend_update_property_string(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("rawPacket"), (char *)ipdata);
1789-
zend_update_property(Z_OBJCE(zpayload), Z_OBJ(zpayload), ZEND_STRL("payload"), &szpayload);
1790-
Z_DELREF(szpayload);
1836+
if (php_socket_afpacket_add_tcp(ipdata, sll, ifrname, recv_buf, slen, &szpayload, &zpayload, &obj, arg2, arg5, arg6) == FAILURE) {
1837+
RETURN_THROWS();
1838+
}
17911839
break;
17921840
}
17931841
case IPPROTO_UDP: {
1794-
struct udphdr a;
1795-
memcpy(&a, ipdata, sizeof(a));
1796-
struct udphdr *udp = &a;
1797-
object_init_ex(&szpayload, udppacket_ce);
1798-
zend_update_property_long(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("srcPort"), ntohs(udp->uh_sport));
1799-
zend_update_property_long(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("dstPort"), ntohs(udp->uh_dport));
1800-
zend_update_property_long(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("headerSize"), sizeof(*udp));
1801-
zend_update_property_string(Z_OBJCE(szpayload), Z_OBJ(szpayload), ZEND_STRL("rawPacket"), (char *)ipdata);
1802-
zend_update_property(Z_OBJCE(zpayload), Z_OBJ(zpayload), ZEND_STRL("payload"), &szpayload);
1803-
Z_DELREF(szpayload);
1842+
if (php_socket_afpacket_add_udp(ipdata, sll, ifrname, recv_buf, slen, &szpayload, &zpayload, &obj, arg2, arg5, arg6) == FAILURE) {
1843+
RETURN_THROWS();
1844+
}
18041845
break;
18051846
}
18061847
// TODO IPPROTO_ICMPV6 support
@@ -1821,7 +1862,21 @@ PHP_FUNCTION(socket_recvfrom)
18211862
break;
18221863
}
18231864
case ETH_P_LOOP: {
1824-
struct ethhdr *innere = (struct ethhdr *)((unsigned char *)e + ETH_HLEN);
1865+
payload = ((unsigned char *)e + ETH_HLEN);
1866+
struct ethhdr a;
1867+
if ((char *)payload + sizeof(a) < ZSTR_VAL(recv_buf) + slen) {
1868+
zend_string_efree(recv_buf);
1869+
Z_DELREF(zpayload);
1870+
ZEND_TRY_ASSIGN_REF_VALUE(arg2, &obj);
1871+
ZEND_TRY_ASSIGN_REF_STRING(arg5, ifrname);
1872+
if (arg6) {
1873+
ZEND_TRY_ASSIGN_REF_LONG(arg6, sll.sll_ifindex);
1874+
}
1875+
zend_value_error("invalid LOOP header");
1876+
RETURN_THROWS();
1877+
}
1878+
memcpy(&a, payload, sizeof(a));
1879+
struct ethhdr *innere = &a;
18251880
zval innerp;
18261881
ZVAL_NULL(&innerp);
18271882
object_init_ex(&zpayload, ethpacket_ce);

0 commit comments

Comments
 (0)