(root)/
glibc-2.38/
resolv/
tst-ns_name_length_uncompressed.c
       1  /* Test __ns_name_length_uncompressed.
       2     Copyright (C) 2022-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <arpa/nameser.h>
      20  #include <array_length.h>
      21  #include <errno.h>
      22  #include <stdio.h>
      23  #include <support/check.h>
      24  #include <support/next_to_fault.h>
      25  
      26  /* Reference implementation based on other building blocks.  */
      27  static int
      28  reference_length (const unsigned char *p, const unsigned char *eom)
      29  {
      30    unsigned char buf[NS_MAXCDNAME];
      31    int n = __ns_name_unpack (p, eom, p, buf, sizeof (buf));
      32    if (n < 0)
      33      return n;
      34    const unsigned char *q = buf;
      35    if (__ns_name_skip (&q, array_end (buf)) < 0)
      36      return -1;
      37    if (q - buf != n)
      38      /* Compressed name.  */
      39      return -1;
      40    return n;
      41  }
      42  
      43  static int
      44  do_test (void)
      45  {
      46    {
      47      unsigned char buf[] = { 3, 'w', 'w', 'w', 0, 0, 0 };
      48      TEST_COMPARE (reference_length (buf, array_end (buf)), sizeof (buf) - 2);
      49      TEST_COMPARE (__ns_name_length_uncompressed (buf, array_end (buf)),
      50                    sizeof (buf) - 2);
      51      TEST_COMPARE (reference_length (array_end (buf) - 1, array_end (buf)), 1);
      52      TEST_COMPARE (__ns_name_length_uncompressed (array_end (buf) - 1,
      53                                                   array_end (buf)), 1);
      54      buf[4]  = 0xc0;             /* Forward compression reference.  */
      55      buf[5]  = 0x06;
      56      TEST_COMPARE (reference_length (buf, array_end (buf)), -1);
      57      TEST_COMPARE (__ns_name_length_uncompressed (buf, array_end (buf)), -1);
      58    }
      59  
      60    struct support_next_to_fault ntf = support_next_to_fault_allocate (300);
      61  
      62    /* Buffer region with all possible bytes at start and end.  */
      63    for (int length = 1; length <= 300; ++length)
      64      {
      65        unsigned char *end = (unsigned char *) ntf.buffer + ntf.length;
      66        unsigned char *start = end - length;
      67        memset (start, 'X', length);
      68        for (int first = 0; first <= 255; ++first)
      69          {
      70            *start = first;
      71            for (int last = 0; last <= 255; ++last)
      72              {
      73                start[length - 1] = last;
      74                TEST_COMPARE (reference_length (start, end),
      75                              __ns_name_length_uncompressed (start, end));
      76              }
      77          }
      78      }
      79  
      80    /* Poor man's fuzz testing: patch two bytes.   */
      81    {
      82      unsigned char ref[] =
      83        {
      84          7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'n', 'e', 't', 0, 0, 0
      85        };
      86      TEST_COMPARE (reference_length (ref, array_end (ref)), 13);
      87      TEST_COMPARE (__ns_name_length_uncompressed (ref, array_end (ref)), 13);
      88  
      89      int good = 0;
      90      int bad = 0;
      91      for (int length = 1; length <= sizeof (ref); ++length)
      92        {
      93          unsigned char *end = (unsigned char *) ntf.buffer + ntf.length;
      94          unsigned char *start = end - length;
      95          memcpy (start, ref, length);
      96  
      97          for (int patch1_pos = 0; patch1_pos < length; ++patch1_pos)
      98            {
      99              for (int patch1_value = 0; patch1_value <= 255; ++patch1_value)
     100                {
     101                  start[patch1_pos] = patch1_value;
     102                  for (int patch2_pos = 0; patch2_pos < length; ++patch2_pos)
     103                    {
     104                      for (int patch2_value = 0; patch2_value <= 255;
     105                           ++patch2_value)
     106                        {
     107                          start[patch2_pos] = patch2_value;
     108                          int expected = reference_length (start, end);
     109                          errno = EINVAL;
     110                          int actual
     111                            =  __ns_name_length_uncompressed (start, end);
     112                          if (actual > 0)
     113                            ++good;
     114                          else
     115                            {
     116                              TEST_COMPARE (errno, EMSGSIZE);
     117                              ++bad;
     118                            }
     119                          TEST_COMPARE (expected, actual);
     120                        }
     121                      start[patch2_pos] = ref[patch2_pos];
     122                    }
     123                }
     124              start[patch1_pos] = ref[patch1_pos];
     125            }
     126        }
     127      printf ("info: patched inputs with success: %d\n", good);
     128      printf ("info: patched inputs with failure: %d\n", bad);
     129    }
     130  
     131    support_next_to_fault_free (&ntf);
     132    return 0;
     133  }
     134  
     135  #include <support/test-driver.c>