Skip to content

Conversation

@baranyaib90
Copy link
Contributor

Hi Aaron,
here we go again. I have a few changes:

  1. @stangri faced a few divide by 0 crashes because of my new code in DNS truncation logic. Hopefully that got fixed in this pack.
  2. I have fixed a few warnings I met while compiling in Alpine container.
  3. cmake version requirement raised becaused of deprecation warning.
  4. I made some clang tidy changes, because I had enough of NOLINT comments in code. I hope it is OK for you.

Take your time.
Best regards,
Balázs

Compatibility with CMake < 3.10 will be removed
from a future version of CMake.

warning: call to '_curl_easy_setopt_err_long' declared with
attribute warning: curl_easy_setopt expects a long argument
The operation of dividing by a fraction is
equivalent to multiplying by its reciprocal.
Safer, minus one clang tidy rule.
@baranyaib90
Copy link
Contributor Author

Hy @aarond10, any update?

@aarond10 aarond10 merged commit 7b27ecd into aarond10:master Oct 7, 2025
2 checks passed
@aarond10
Copy link
Owner

aarond10 commented Oct 7, 2025

Oh, sorry! I reviewed but didn't merge.

// rough estimate to reach size limit
size_t answers = ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER);
size_t answers_to_keep = (size_limit - DNS_HEADER_LENGTH) / (old_size / answers);
size_t answers_to_keep = ((size_limit - DNS_HEADER_LENGTH) * answers) / old_size;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we should simplify this whole function to something like this (nb: untested)?

while (*buflen > 0) {
    ares_status_t status = ares_dns_parse((const unsigned char *)buf, *buflen, 0, &dnsrec);
    if (status != ARES_SUCCESS) {
      WLOG("Failed to parse DNS response: %s", ares_strerror((int)status));
      return;
    }
    int32_t packet_len = *buflen;
    while (packet_len > size_limit) {
        size_t current_count = ares_dns_record_rr_cnt(dnsrec, ARES_DNS_SECTION_ANSWER);
        if (current_count <= 1) { // Stop if we are about to delete the last record
            ELOG("Cannot trim any more records. Still too large.");
            break;
        }

        // Get the last record
        const ares_dns_rr_t *last_record = ares_dns_record_rr_get_const(dns_record, ARES_DNS_SECTION_ANSWER, current_count - 1);
        if (last_record == NULL) {
            printf("Error finding last record.\n");
            break;
        }

        // Estimate the size of the record we are about to delete
        size_t size_to_remove = 10 + strlen(lat_record->name) + 1 + last_record->rdata_len;

        status = ares_dns_record_rr_del(dns_record, ARES_DNS_SECTION_ANSWER, current_count - 1);
        if (status != ARES_SUCCESS) {
            ELOG("Error deleting record: %s", ares_strerror(status));
            break;
        }
        
        // Subtract the estimated size from our total
        // Note: This is an approximation. The actual size reduction
        // might differ slightly due to name compression effects.
        packet_len -= size_to_remove;
    }
    status = ares_dns_record_write_packet(dnsrec, buf, buflen);
}
...

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think this might be a good idea...

Copy link
Contributor Author

@baranyaib90 baranyaib90 Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, I will check later more deeply, but this code looks to be AI generated with lots of mistakes:

This was my bigges issue with truncation: you can't know trough public API how large the record is that you intend to remove.
That is why I suppose that records are even sized (not true for TXT records obviously) and I'm using ratio-based estimation how much should be removed. If the DNS response would be still over the limit, I'm starting to aggressively reduce the size by dropping half of the records all the time until limit is reached or 1 remains (because even for TXT record, the maximum string limit is 255 char, so should fit in minimum 512).
I try not to waste CPU time by calling ares_dns_write() way too many times, but with current public API of c-ares there is no better option.
I agree, that current function is large and complicated, but at lest it seems to work and I would better not touch it until there is an issue with it.
Br, Balázs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants