(root)/
glibc-2.38/
debug/
tst-sprintf-fortify-unchecked.c
       1  /* Tests for fortified sprintf with unknown buffer bounds (bug 30039).
       2     Copyright (C) 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 <printf.h>
      20  #include <stdarg.h>
      21  #include <stdio.h>
      22  #include <string.h>
      23  #include <support/check.h>
      24  
      25  /* This test is not built with _FORTIFY_SOURCE.  Instead it calls the
      26     appropriate implementation directly.  The fortify mode is specified
      27     in this variable.  */
      28  static int fortify_mode;
      29  
      30  /* This does not handle long-double redirects etc., but we test only
      31     format strings that stay within the confines of the base
      32     implementation.  */
      33  int __vsprintf_chk (char *s, int flag, size_t slen, const char *format,
      34                      va_list ap);
      35  
      36  /* Invoke vsprintf or __vsprintf_chk according to fortify_mode.  */
      37  static int
      38  my_vsprintf (char *buf, const char *format, va_list ap)
      39  {
      40    int result;
      41    if (fortify_mode == 0)
      42      result = vsprintf (buf, format, ap);
      43    else
      44      /* Call the fortified version with an unspecified length.  */
      45      result = __vsprintf_chk (buf, fortify_mode - 1, -1, format, ap);
      46    return result;
      47  }
      48  
      49  /* Run one test, with the specified expected output.  */
      50  static void __attribute ((format (printf, 2, 3)))
      51  do_check (const char *expected, const char *format, ...)
      52  {
      53    va_list ap;
      54    va_start (ap, format);
      55  
      56    char buf_expected[24];
      57    memset (buf_expected, '@', sizeof (buf_expected));
      58    TEST_VERIFY (strlen (expected) < sizeof (buf_expected));
      59    strcpy (buf_expected, expected);
      60  
      61    char buf[sizeof (buf_expected)];
      62    memset (buf, '@', sizeof (buf));
      63  
      64    int ret = my_vsprintf (buf, format, ap);
      65    TEST_COMPARE_BLOB (buf_expected, sizeof (buf_expected), buf, sizeof (buf));
      66    TEST_COMPARE (ret, strlen (expected));
      67  
      68    va_end (ap);
      69  }
      70  
      71  /* Run the tests in all fortify modes.  */
      72  static void
      73  do_tests (void)
      74  {
      75    for (fortify_mode = 0; fortify_mode <= 3; ++fortify_mode)
      76      {
      77        do_check ("0", "%d", 0);
      78        do_check ("-2147483648", "%d", -2147483647 - 1);
      79        do_check ("-9223372036854775808", "%lld", -9223372036854775807LL - 1);
      80        do_check ("", "%s", "");
      81        do_check ("                      ", "%22s", "");
      82        do_check ("XXXXXXXXXXXXXXXXXXXXXX", "%s", "XXXXXXXXXXXXXXXXXXXXXX");
      83        do_check ("1.125000", "%f", 1.125);
      84        do_check ("1.125", "%g", 1.125);
      85        do_check ("1.125", "%.8g", 1.125);
      86      }
      87  }
      88  
      89  /* printf callback that falls back to the glibc-supplied
      90     implementation.  */
      91  static int
      92  dummy_printf_function (FILE *__stream,
      93                         const struct printf_info *__info,
      94                         const void *const *__args)
      95  {
      96    return -2;                    /* Request fallback.  */
      97  }
      98  
      99  /* Likewise for the type information.  */
     100  static int
     101  dummy_arginfo_function (const struct printf_info *info,
     102                          size_t n, int *argtypes, int *size)
     103  {
     104    return -1;                    /* Request fallback.  */
     105  }
     106  
     107  static int
     108  do_test (void)
     109  {
     110    do_tests ();
     111  
     112    /* Activate __printf_function_invoke mode.  */
     113    register_printf_specifier ('d', dummy_printf_function,
     114                               dummy_arginfo_function);
     115    register_printf_specifier ('g', dummy_printf_function,
     116                               dummy_arginfo_function);
     117    register_printf_specifier ('s', dummy_printf_function,
     118                               dummy_arginfo_function);
     119  
     120    /* Rerun the tests with callback functions.  */
     121    do_tests ();
     122  
     123    return 0;
     124  }
     125  
     126  #include <support/test-driver.c>