Home > Back-end >  Confused why FD_SET crashes with a large value like 536872413?
Confused why FD_SET crashes with a large value like 536872413?

Time:11-01

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.

  • Related