Skip to content

Commit 75b7ffa

Browse files
authored
Fix memory invalid read/write (#4379)
* Fix ipv6 address buffer overflow * Fix Socket::readVectorAll invalid write * Fix System::gethostbyname with c-ares invalid write.
1 parent 7a9a5b1 commit 75b7ffa

File tree

3 files changed

+39
-26
lines changed

3 files changed

+39
-26
lines changed

ext-src/swoole_async_coro.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ using swoole::Timer;
2929
using swoole::coroutine::Socket;
3030

3131
struct DNSCacheEntity {
32-
char address[16];
32+
char address[INET6_ADDRSTRLEN];
3333
time_t update_time;
3434
};
3535

ext-src/swoole_socket_coro.cc

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -843,9 +843,12 @@ static void sw_inline php_swoole_init_socket(zval *zobject, SocketObject *sock)
843843
sock->socket->set_zero_copy(true);
844844
sock->socket->set_buffer_allocator(sw_zend_string_allocator());
845845
zend_update_property_long(swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("fd"), sock->socket->get_fd());
846-
zend_update_property_long(swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("domain"), sock->socket->get_sock_domain());
847-
zend_update_property_long(swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("type"), sock->socket->get_sock_type());
848-
zend_update_property_long(swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("protocol"), sock->socket->get_sock_protocol());
846+
zend_update_property_long(
847+
swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("domain"), sock->socket->get_sock_domain());
848+
zend_update_property_long(
849+
swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("type"), sock->socket->get_sock_type());
850+
zend_update_property_long(
851+
swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("protocol"), sock->socket->get_sock_protocol());
849852
}
850853

851854
SW_API bool php_swoole_export_socket(zval *zobject, Socket *_socket) {
@@ -1479,26 +1482,27 @@ static void swoole_socket_coro_read_vector(INTERNAL_FUNCTION_PARAMETERS, const b
14791482

14801483
std::unique_ptr<iovec[]> iov(new iovec[iovcnt]);
14811484

1482-
SW_HASHTABLE_FOREACH_START(vht, zelement)
1483-
if (!ZVAL_IS_LONG(zelement)) {
1484-
zend_throw_exception_ex(swoole_socket_coro_exception_ce,
1485-
EINVAL,
1486-
"Item #[%d] must be of type int, %s given",
1487-
iov_index,
1488-
zend_get_type_by_const(Z_TYPE_P(zelement)));
1489-
RETURN_FALSE;
1490-
}
1491-
if (Z_LVAL_P(zelement) < 0) {
1492-
zend_throw_exception_ex(
1493-
swoole_socket_coro_exception_ce, EINVAL, "Item #[%d] must be greater than 0", iov_index);
1494-
RETURN_FALSE;
1495-
}
1496-
size_t iov_len = Z_LVAL_P(zelement);
1485+
SW_HASHTABLE_FOREACH_START(vht, zelement) {
1486+
if (!ZVAL_IS_LONG(zelement)) {
1487+
zend_throw_exception_ex(swoole_socket_coro_exception_ce,
1488+
EINVAL,
1489+
"Item #[%d] must be of type int, %s given",
1490+
iov_index,
1491+
zend_get_type_by_const(Z_TYPE_P(zelement)));
1492+
RETURN_FALSE;
1493+
}
1494+
if (Z_LVAL_P(zelement) < 0) {
1495+
zend_throw_exception_ex(
1496+
swoole_socket_coro_exception_ce, EINVAL, "Item #[%d] must be greater than 0", iov_index);
1497+
RETURN_FALSE;
1498+
}
1499+
size_t iov_len = Z_LVAL_P(zelement);
14971500

1498-
iov[iov_index].iov_base = zend_string_alloc(iov_len, 0)->val;
1499-
iov[iov_index].iov_len = iov_len;
1500-
iov_index++;
1501-
total_length += iov_len;
1501+
iov[iov_index].iov_base = zend_string_alloc(iov_len, 0)->val;
1502+
iov[iov_index].iov_len = iov_len;
1503+
iov_index++;
1504+
total_length += iov_len;
1505+
}
15021506
SW_HASHTABLE_FOREACH_END();
15031507

15041508
swoole::network::IOVector io_vector((struct iovec *) iov.get(), iovcnt);
@@ -1533,6 +1537,7 @@ static void swoole_socket_coro_read_vector(INTERNAL_FUNCTION_PARAMETERS, const b
15331537
real_count = iov_index + 1;
15341538
zend_string *str = zend::fetch_zend_string_by_val((char *) iov[iov_index].iov_base);
15351539
iov[iov_index].iov_base = sw_zend_string_recycle(str, iov[iov_index].iov_len, offset_bytes)->val;
1540+
iov[iov_index].iov_len = offset_bytes;
15361541
free_func(iov.get(), iovcnt, real_count);
15371542
} else {
15381543
real_count = iovcnt;
@@ -1767,9 +1772,10 @@ static PHP_METHOD(swoole_socket_coro, getOption) {
17671772
}
17681773
case SO_RCVTIMEO:
17691774
case SO_SNDTIMEO: {
1770-
double timeout = sock->socket->get_timeout(optname == SO_RCVTIMEO ? Socket::TIMEOUT_READ : Socket::TIMEOUT_WRITE);
1775+
double timeout =
1776+
sock->socket->get_timeout(optname == SO_RCVTIMEO ? Socket::TIMEOUT_READ : Socket::TIMEOUT_WRITE);
17711777
array_init(return_value);
1772-
int sec = (int) timeout;
1778+
int sec = (int) timeout;
17731779
add_assoc_long(return_value, "sec", (int) timeout);
17741780
add_assoc_long(return_value, "usec", (timeout - (double) sec) * 1000000);
17751781
break;

src/network/dns.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ struct ResolvContext {
402402
int error;
403403
bool completed;
404404
Coroutine *co;
405+
std::shared_ptr<bool> defer_task_cancelled;
405406
std::unordered_map<int, network::Socket *> sockets;
406407
std::vector<std::string> result;
407408
};
@@ -428,6 +429,7 @@ std::vector<std::string> dns_lookup_impl_with_cares(const char *domain, int fami
428429
Coroutine *co = Coroutine::get_current_safe();
429430
ctx.co = co;
430431
ctx.completed = false;
432+
ctx.defer_task_cancelled = std::make_shared<bool>(false);
431433
char lookups[] = "fb";
432434
int res;
433435
ctx.ares_opts.lookups = lookups;
@@ -533,8 +535,12 @@ std::vector<std::string> dns_lookup_impl_with_cares(const char *domain, int fami
533535
}
534536
_resume:
535537
if (ctx->co && ctx->co->is_suspending()) {
538+
auto _cancelled = ctx->defer_task_cancelled;
536539
swoole_event_defer(
537-
[](void *data) {
540+
[_cancelled](void *data) {
541+
if (*_cancelled) {
542+
return;
543+
}
538544
Coroutine *co = reinterpret_cast<Coroutine *>(data);
539545
co->resume();
540546
},
@@ -573,6 +579,7 @@ std::vector<std::string> dns_lookup_impl_with_cares(const char *domain, int fami
573579
break;
574580
}
575581
}
582+
*ctx.defer_task_cancelled = true;
576583
ares_destroy(ctx.channel);
577584
_return:
578585
return ctx.result;

0 commit comments

Comments
 (0)