Repository: bitcoin/bitcoin
File: src/common/netif.cpp (C++)

Code before:

    // Receive response.
    char response[4096];
    ssize_t total_bytes_read{0};
    bool done{false};
    bool multi_part{false};
    while (!done) {
        int64_t recv_result;
        do {
            recv_result = sock->Recv(response, sizeof(response), 0);
        } while (recv_result < 0 && (errno == EINTR || errno == EAGAIN));
        if (recv_result < 0) {
            LogPrintLevel(BCLog::NET, BCLog::Level::Error, "recv() from netlink socket: %s\n", NetworkErrorString(errno));
            return std::nullopt;
        }

        total_bytes_read += recv_result;
        if (total_bytes_read > NETLINK_MAX_RESPONSE_SIZE) {
            LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "Netlink response exceeded size limit (%zu bytes, family=%d)\n", NETLINK_MAX_RESPONSE_SIZE, family);
            return std::nullopt;
        }

        bool processed_one{false};
        for (nlmsghdr* hdr = (nlmsghdr*)response; NLMSG_OK(hdr, recv_result); hdr = NLMSG_NEXT(hdr, recv_result)) {
            rtmsg* r = (rtmsg*)NLMSG_DATA(hdr);
            int remaining_len = RTM_PAYLOAD(hdr);

            processed_one = true;
            if (hdr->nlmsg_flags & NLM_F_MULTI) {
                multi_part = true;
            }

            if (hdr->nlmsg_type == NLMSG_DONE) {
                done = true;
                break;
            }

            if (hdr->nlmsg_type != RTM_NEWROUTE) {
                continue; // Skip non-route messages
            }

            // Only consider default routes (destination prefix length of 0).
            if (r->rtm_dst_len != 0) {
                continue;
            }

            // Iterate over the attributes.
            rtattr* rta_gateway = nullptr;
            int scope_id = 0;
            for (rtattr* attr = RTM_RTA(r); RTA_OK(attr, remaining_len); attr = RTA_NEXT(attr, remaining_len)) {
                if (attr->rta_type == RTA_GATEWAY) {

Review comment (security):
These could be moved after `if (hdr->nlmsg_type == NLMSG_DONE) {` to avoid the integer sanitizer warning in #33245

Code after:

    // Receive response.
    char response[4096];
    ssize_t total_bytes_read{0};
    bool done{false};
    while (!done) {
        int64_t recv_result;
        do {
            recv_result = sock->Recv(response, sizeof(response), 0);
        } while (recv_result < 0 && (errno == EINTR || errno == EAGAIN));
        if (recv_result < 0) {
            LogPrintLevel(BCLog::NET, BCLog::Level::Error, "recv() from netlink socket: %s\n", NetworkErrorString(errno));
            return std::nullopt;
        }

        total_bytes_read += recv_result;
        if (total_bytes_read > NETLINK_MAX_RESPONSE_SIZE) {
            LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "Netlink response exceeded size limit (%zu bytes, family=%d)\n", NETLINK_MAX_RESPONSE_SIZE, family);
            return std::nullopt;
        }

        for (nlmsghdr* hdr = (nlmsghdr*)response; NLMSG_OK(hdr, recv_result); hdr = NLMSG_NEXT(hdr, recv_result)) {
            if (!(hdr->nlmsg_flags & NLM_F_MULTI)) {
                done = true;
            }

            if (hdr->nlmsg_type == NLMSG_DONE) {
                done = true;
                break;
            }

            rtmsg* r = (rtmsg*)NLMSG_DATA(hdr);
            int remaining_len = RTM_PAYLOAD(hdr);

            if (hdr->nlmsg_type != RTM_NEWROUTE) {
                continue; // Skip non-route messages
            }

            // Only consider default routes (destination prefix length of 0).
            if (r->rtm_dst_len != 0) {
                continue;
            }

            // Iterate over the attributes.
            rtattr* rta_gateway = nullptr;
            int scope_id = 0;
            for (rtattr* attr = RTM_RTA(r); RTA_OK(attr, remaining_len); attr = RTA_NEXT(attr, remaining_len)) {
                if (attr->rta_type == RTA_GATEWAY) {
                    rta_gateway = attr;
                } else if (attr->rta_type == RTA_OIF && sizeof(int) == RTA_PAYLOAD(attr)) {
                    std::memcpy(&scope_id, RTA_DATA(attr), sizeof(scope_id));