(root)/
glibc-2.38/
stdio-common/
tst-sscanf.c
       1  /* Copyright (C) 2000-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <array_length.h>
      19  #include <stdlib.h>
      20  #include <stdio.h>
      21  #include <locale.h>
      22  
      23  #ifndef CHAR
      24  # define CHAR char
      25  # define L(str) str
      26  # define SSCANF sscanf
      27  #endif
      28  
      29  const CHAR *str_double[] =
      30  {
      31    L("-.10000E+020.20000E+020.25000E+010.40000E+010.50000E+010.12500E+01"),
      32    L("0.10000E+020.20000E+020.25000E+010.40000E+010.50000E+010.12500E+01"),
      33    L("-1234567E0198765432E0912345678901987654321091234567890198765432109"),
      34    L("-0.1000E+020.20000E+020.25000E+010.40000E+010.50000E+010.12500E+01")
      35  };
      36  
      37  const double val_double[] =
      38  {
      39    -.10000E+02, 0.20000E+02, 0.25000E+01, 0.40000E+01, 0.50000E+01, 0.12500E+01,
      40    0.10000E+02, 0.20000E+02, 0.25000E+01, 0.40000E+01, 0.50000E+01, 0.12500E+01,
      41    -1234567E01, 98765432E09, 12345678901.0, 98765432109.0, 12345678901.0,
      42      98765432109.0,
      43    -0.1000E+02, 0.20000E+02, 0.25000E+01, 0.40000E+01, 0.50000E+01, 0.12500E+01
      44  };
      45  
      46  const CHAR *str_long[] =
      47  {
      48    L("-12345678987654321123456789987654321123456789987654321"),
      49    L("-12345678987654321123456789987654321123456789987654321"),
      50    L("-12,345,678987,654,321123,456,789987,654,321123,456,789987,654,321"),
      51    L("-12,345,678987,654,321123,456,789987,654,321123,456,789987,654,321")
      52  };
      53  
      54  const CHAR *fmt_long[] =
      55  {
      56    L("%9ld%9ld%9ld%9ld%9ld%9ld"),
      57    L("%I9ld%I9ld%I9ld%I9ld%I9ld%I9ld"),
      58    L("%'11ld%'11ld%'11ld%'11ld%'11ld%'11ld"),
      59    L("%I'11ld%I'11ld%I'11ld%I'11ld%I'11ld%I'11ld")
      60  };
      61  
      62  const long int val_long[] =
      63  {
      64    -12345678, 987654321, 123456789, 987654321, 123456789, 987654321
      65  };
      66  
      67  struct test
      68  {
      69    const CHAR *str;
      70    const CHAR *fmt;
      71    int retval;
      72  } int_tests[] =
      73  {
      74    { L("foo\n"), L("foo\nbar"), -1 },
      75    { L("foo\n"), L("foo bar"), -1 },
      76    { L("foo\n"), L("foo %d"), -1 },
      77    { L("foo\n"), L("foo\n%d"), -1 },
      78    { L("foon"), L("foonbar"), -1 },
      79    { L("foon"), L("foon%d"), -1 },
      80    { L("foo "), L("foo bar"), -1 },
      81    { L("foo "), L("foo %d"), -1 },
      82    { L("foo\t"), L("foo\tbar"), -1 },
      83    { L("foo\t"), L("foo bar"), -1 },
      84    { L("foo\t"), L("foo %d"), -1 },
      85    { L("foo\t"), L("foo\t%d"), -1 },
      86    { L("foo"), L("foo"), 0 },
      87    { L("foon"), L("foo bar"), 0 },
      88    { L("foon"), L("foo %d"), 0 },
      89    { L("foo "), L("fooxbar"), 0 },
      90    { L("foo "), L("foox%d"), 0 },
      91    { L("foo bar"), L("foon"), 0 },
      92    { L("foo bar"), L("foo bar"), 0 },
      93    { L("foo bar"), L("foo %d"), 0 },
      94    { L("foo bar"), L("foon%d"), 0 },
      95    { L("foo (nil)"), L("foo %p"), 1},
      96    { L("foo (nil)"), L("foo %4p"), 0},
      97    { L("foo "), L("foo %n"), 0 },
      98    { L("foo%bar1"), L("foo%%bar%d"), 1 },
      99    /* Some OSes skip whitespace here while others don't.  */
     100    { L("foo \t %bar1"), L("foo%%bar%d"), 1 }
     101  };
     102  
     103  struct test double_tests[] =
     104  {
     105    { L("-1"), L("%1g"), 0 },
     106    { L("-.1"), L("%2g"), 0 },
     107    { L("-inf"), L("%3g"), 0 },
     108    { L("+0"), L("%1g"),  },
     109    { L("-0x1p0"), L("%2g"), 1 },
     110    { L("-..1"), L("%g"), 0 },
     111    { L("-inf"), L("%g"), 1 }
     112  };
     113  
     114  struct test2
     115  {
     116    const CHAR *str;
     117    const CHAR *fmt;
     118    int retval;
     119    char residual;
     120  } double_tests2[] =
     121  {
     122    { L("0e+0"), L("%g%c"), 1, 0 },
     123    { L("0xe+0"), L("%g%c"), 2, '+' },
     124    { L("0x.e+0"), L("%g%c"), 2, '+' },
     125  };
     126  
     127  static int
     128  do_test (void)
     129  {
     130    double d[6];
     131    long l[6];
     132    int i, j;
     133    int tst_locale;
     134    int result = 0;
     135  
     136    tst_locale = 1;
     137    if (tst_locale)
     138      if (setlocale (LC_ALL, "en_US.ISO-8859-1") == NULL)
     139        {
     140  	puts ("Failed to set en_US locale, skipping locale related tests");
     141  	tst_locale = 0;
     142        }
     143  
     144    for (i = 0; i < 4; ++i)
     145      {
     146        if (SSCANF (str_double[i], L("%11lf%11lf%11lf%11lf%11lf%11lf"),
     147  		  &d[0], &d[1], &d[2], &d[3], &d[4], &d[5]) != 6)
     148  	{
     149  	  printf ("Double sscanf test %d wrong number of "
     150  		  "assigned inputs\n", i);
     151  	  result = 1;
     152  	}
     153        else
     154  	for (j = 0; j < 6; ++j)
     155  	  if (d[j] != val_double[6 * i + j])
     156  	    {
     157  	      printf ("Double sscanf test %d failed (%g instead of %g)\n",
     158  		      i, d[j], val_double[6 * i + j]);
     159  	      result = 1;
     160  	      break;
     161  	    }
     162      }
     163  
     164    for (i = 0; i < 4; ++i)
     165      {
     166        if (SSCANF (str_long[i], fmt_long[i],
     167  		  &l[0], &l[1], &l[2], &l[3], &l[4], &l[5]) != 6)
     168  	{
     169  	  printf ("Integer sscanf test %d wrong number of "
     170  		  "assigned inputs\n", i);
     171  	  result = 1;
     172  	}
     173        else
     174  	for (j = 0; j < 6; ++j)
     175  	  if (l[j] != val_long[j])
     176  	    {
     177  	      printf ("Integer sscanf test %d failed (%ld instead %ld)\n",
     178  		      i, l[j], val_long[j]);
     179  	      result = 1;
     180  	      break;
     181  	    }
     182  
     183        if (! tst_locale)
     184  	break;
     185      }
     186  
     187    for (i = 0; i < array_length (int_tests); ++i)
     188      {
     189        long dummy;
     190        int ret;
     191  
     192        if ((ret = SSCANF (int_tests[i].str, int_tests[i].fmt,
     193  			 &dummy)) != int_tests[i].retval)
     194  	{
     195  	  printf ("int_tests[%d] returned %d != %d\n",
     196  		  i, ret, int_tests[i].retval);
     197  	  result = 1;
     198  	}
     199      }
     200  
     201    for (i = 0; i < array_length (double_tests); ++i)
     202      {
     203        double dummy;
     204        int ret;
     205  
     206        if ((ret = SSCANF (double_tests[i].str, double_tests[i].fmt,
     207  			 &dummy)) != double_tests[i].retval)
     208  	{
     209  	  printf ("double_tests[%d] returned %d != %d\n",
     210  		  i, ret, double_tests[i].retval);
     211  	  result = 1;
     212  	}
     213      }
     214  
     215    for (i = 0; i < array_length (double_tests2); ++i)
     216      {
     217        double dummy;
     218        int ret;
     219        char c = 0;
     220  
     221        if ((ret = SSCANF (double_tests2[i].str, double_tests2[i].fmt,
     222  			 &dummy, &c)) != double_tests2[i].retval)
     223  	{
     224  	  printf ("double_tests2[%d] returned %d != %d\n",
     225  		  i, ret, double_tests2[i].retval);
     226  	  result = 1;
     227  	}
     228        else if (ret == 2 && c != double_tests2[i].residual)
     229  	{
     230  	  printf ("double_tests2[%d] stopped at '%c' != '%c'\n",
     231  		  i, c, double_tests2[i].residual);
     232  	  result = 1;
     233  	}
     234      }
     235  
     236    /* BZ #16618
     237       The test will segfault during SSCANF if the buffer overflow
     238       is not fixed.  The size of `s` is such that it forces the use
     239       of malloc internally and this triggers the incorrect computation.
     240       Thus the value for SIZE is arbitrarily high enough that malloc
     241       is used.  */
     242    {
     243  #define SIZE 131072
     244      CHAR *s = malloc ((SIZE + 1) * sizeof (*s));
     245      if (s == NULL)
     246        abort ();
     247      for (size_t i = 0; i < SIZE; i++)
     248        s[i] = L('0');
     249      s[SIZE] = L('\0');
     250      int i = 42;
     251      /* Scan multi-digit zero into `i`.  */
     252      if (SSCANF (s, L("%d"), &i) != 1)
     253        {
     254  	printf ("FAIL: bug16618: SSCANF did not read one input item.\n");
     255  	result = 1;
     256        }
     257      if (i != 0)
     258        {
     259  	printf ("FAIL: bug16618: Value of `i` was not zero as expected.\n");
     260  	result = 1;
     261        }
     262      free (s);
     263      if (result != 1)
     264        printf ("PASS: bug16618: Did not crash.\n");
     265  #undef SIZE
     266    }
     267  
     268  
     269    return result;
     270  }
     271  
     272  #define TEST_FUNCTION do_test ()
     273  #include "../test-skeleton.c"