[PATCH v2 8/8] resolv: Add test case tst-ns_sprintrr (bug 34033, bug 34069)

Florian Weimer fweimer@redhat.com
Fri Jun 19 14:50:44 GMT 2026


* Adhemerval Zanella Netto:

> On 16/06/26 13:32, Florian Weimer wrote:
>> This test case covers both input buffer overreads and output buffer
>> overflows.  It should systematically cover these issues.
>> 
>> I used code auto-generation for updating the test expectations for
>> truncated RDATA in TXT, ISDN records, after writing the rest
>> of the test by hand.
>> 
>> Assisted-by: LLM
>
> LGTM, some suggestions below.
>
> Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
>
>> ---
>>  resolv/Makefile          |   2 +
>>  resolv/tst-ns_sprintrr.c | 328 +++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 330 insertions(+)
>>  create mode 100644 resolv/tst-ns_sprintrr.c
>> 
>> diff --git a/resolv/Makefile b/resolv/Makefile
>> index 68b3a4dbf3..02cc751732 100644
>> --- a/resolv/Makefile
>> +++ b/resolv/Makefile
>> @@ -108,6 +108,7 @@ tests += \
>>    tst-ns_name \
>>    tst-ns_name_compress \
>>    tst-ns_name_pton \
>> +  tst-ns_sprintrr \
>>    tst-res_hconf_reorder \
>>    tst-res_hnok \
>>    tst-resolv-aliases \
>
> Ok.
>
>> @@ -341,5 +342,6 @@ $(objpfx)tst-ns_name: $(objpfx)libresolv.so
>>  $(objpfx)tst-ns_name.out: tst-ns_name.data
>>  $(objpfx)tst-ns_name_compress: $(objpfx)libresolv.so
>>  $(objpfx)tst-ns_name_pton: $(objpfx)libresolv.so
>> +$(objpfx)tst-ns_sprintrr: $(objpfx)libresolv.so
>>  $(objpfx)tst-res_hnok: $(objpfx)libresolv.so
>>  $(objpfx)tst-p_secstodate: $(objpfx)libresolv.so
>> diff --git a/resolv/tst-ns_sprintrr.c b/resolv/tst-ns_sprintrr.c
>> new file mode 100644
>> index 0000000000..9083d28d2d
>> --- /dev/null
>> +++ b/resolv/tst-ns_sprintrr.c
>> @@ -0,0 +1,328 @@
>> +/* Tests for the ns_sprintrr function.
>> +   Copyright (C) 2026 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <https://www.gnu.org/licenses/>.  */
>> +
>> +#include <arpa/nameser.h>
>> +
>> +#include <alloc_buffer.h>
>> +#include <arpa/inet.h>
>> +#include <libc-diag.h>
>> +#include <stdbool.h>
>> +#include <string.h>
>> +#include <support/check.h>
>> +#include <support/next_to_fault.h>
>> +
>> +#include <stdio.h>
>> +
>> +/* Regions that test_one_record uses for input and output.  */
>> +static struct support_next_to_fault ntf_in;
>> +static struct support_next_to_fault ntf_out;
>> +
>> +/* This is used by test_one_record to construct the packet.   */
>> +static const char packet_prefix[] =
>> +  /* DNS response with one question, one answer record.  */
>> +  "AA\x81\x80\0\1\0\1\0\0\0\0"
>> +  /* Question: www.example.org/IN/ANY.  */
>> +  "\3www\7example\3org\0\0\xff\0\1"
>> +  /* Response: compression reference.  */
>> +  "\xc0\x0c";
>> +
>> +/* Use ns_sprintrr to format a DNS record (starting with
>> +   packet_prefix) of type RTYPE, with a record payload of RDATALEN
>> +   bytes starting at RDATA.  Check successful formatting against
>> +   EXPECTED.  Try various truncated input and output buffers to catch
>> +   overreads and buffer overflows, using ntf_in and ntf_out above.  */
>> +static void
>> +test_one_record (uint16_t rtype, const char *rdata, size_t rdatalen,
>> +                 const char *expected)
>> +{
>> +  struct rr_header
>> +  {
>> +    uint16_t typ;
>> +    uint16_t cls;
>> +    uint32_t ttl;
>> +    uint16_t rdatalen;
>> +    uint16_t pad;
>> +  } hdr =
>> +    {
>> +      .typ = htons (rtype),
>> +      .cls = htons (ns_c_in),
>> +      .ttl = htonl (86400),     /* One day.  */
>> +      .rdatalen = htons (rdatalen),
>> +    };
>> +  size_t hdrlen = offsetof (struct rr_header, pad);
>> +  TEST_COMPARE (hdrlen, 10);
>
> I haven't checked this on all supported ABIs, but this seems to be true for
> all supported ABIs.  I think you can make it a _Static_assert instead.

It has to be 10.  But hdrlen is not a constant expression, so I would
have to repeat it.  I'm going to change it to enum constant.

>> +  /* Construct the packet from packet_prefix, hdr, and rdata.  */
>> +  char packet[512];
>
> I think you can make this unsigned and remove the cast below.

Yeah, unsigned char * leads to fewer casts in the end.

>> +  bool success = false;
>> +  for (size_t result_size = 1; result_size <= max_result_size; ++result_size)
>> +    {
>> +      char *result_start = ntf_out.buffer + ntf_out.length - result_size;
>> +      memset (result_start, 'X', result_size);
>> +
>> +      /* ns_sprintrr was deprecated in 2.34.  */
>> +      DIAG_PUSH_NEEDS_COMMENT;
>> +      DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdeprecated-declarations");
>
> Maybe use 12.0, since it is the current minimal support version
> anyway.

Not sure what the rules for permanent exemptions are.  Should I use
16.1?

Thanks,
Florian



More information about the Libc-alpha mailing list