there is a crash stack in iOS14.2 (arm64):
* thread #1245, queue = 'com.xxx.xxx.sdt (QOS: UNSPECIFIED)', stop reason = EXC_BAD_ACCESS (code=1, address=0x175ce5548)
frame #0: 0x000000010bac2548 XXXApp`RecvWithinTime(int, char*, unsigned long, sockaddr*, unsigned int*, unsigned int, unsigned int) [inlined] __darwin_fd_set(_fd=536872413, _p=0x0000000171ce5490) at _fd_def.h:93:56
frame #1: 0x000000010bac24d4 XXXApp`RecvWithinTime(_fd=536872413, _buf="", _buf_n=65536, _addr=0x0000000171ce5788, _len=0x0000000171ce5780, _sec=3, _usec=0) at dnsquery.cc:556
frame #2: 0x000000010babecc4 XXXApp`try_socket_gethostbyname(_host="xx.xxx.com", _ipinfo=0x0000000171d05f44, _timeout=3000, _dnsserver="2408:8000:1010:1::8", _qtype=1, _socket_errno=0x0000000171d05d98, _interface_name="") at dnsquery.cc:321:30
source code of RecvWithinTime and __darwin_fd_set are:
int RecvWithinTime(int _fd, char* _buf, size_t _buf_n, struct sockaddr* _addr, socklen_t* _len, unsigned int _sec, unsigned _usec) {
struct timeval tv;
fd_set readfds, exceptfds;
int n = 0;
FD_ZERO(&readfds);
FD_SET(_fd, &readfds); // line 554, why crash not happened here ?
FD_ZERO(&exceptfds); // line 555
FD_SET(_fd, &exceptfds); // line 556, crashed here
...
}
__header_always_inline void
__darwin_fd_set(int _fd, struct fd_set *const _p)
{
if (__darwin_check_fd_set(_fd, (const void *) _p)) {
// crash here: crash address 0x175ce5548 = (unsigned long)_fd / __DARWIN_NFDBITS (&exceptfds) = 536872413/32 * 4 0x0000000171ce5490
(_p->fds_bits[(unsigned long)_fd / __DARWIN_NFDBITS] |= ((__int32_t)(((unsigned long)1) << ((unsigned long)_fd % __DARWIN_NFDBITS))));
}
}
_fd is initialized with -1:
#define INVALID_SOCKET -1
SOCKET _fd = INVALID_SOCKET;
as you can see,in the crash stack,the value of _fd is 536872413, and it's the reason why crash happened.
Another interesting thing is why crash not happened in line 554 but line 556 with the same value of _fd(536872413).
CodePudding user response:
Given the additional information, you cannot call FD_SET with an invalid file descriptor. -1 is not a valid file descriptor (no open file will ever have that value).
An fd_set is a fixed size buffer. Executing FD_CLR() or FD_SET() with a value of fd that is negative or is equal to or larger than FD_SETSIZE will result in undefined behavior. Moreover, POSIX requires fd to be a valid file descriptor.