Blame stdio-common/tst-sscanf.c

Packit 6c4009
/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Jakub Jelinek <jakub@redhat.com>, 2000.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <array_length.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <locale.h>
Packit 6c4009
Packit 6c4009
#ifndef CHAR
Packit 6c4009
# define CHAR char
Packit 6c4009
# define L(str) str
Packit 6c4009
# define SSCANF sscanf
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
const CHAR *str_double[] =
Packit 6c4009
{
Packit 6c4009
  L("-.10000E+020.20000E+020.25000E+010.40000E+010.50000E+010.12500E+01"),
Packit 6c4009
  L("0.10000E+020.20000E+020.25000E+010.40000E+010.50000E+010.12500E+01"),
Packit 6c4009
  L("-1234567E0198765432E0912345678901987654321091234567890198765432109"),
Packit 6c4009
  L("-0.1000E+020.20000E+020.25000E+010.40000E+010.50000E+010.12500E+01")
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
const double val_double[] =
Packit 6c4009
{
Packit 6c4009
  -.10000E+02, 0.20000E+02, 0.25000E+01, 0.40000E+01, 0.50000E+01, 0.12500E+01,
Packit 6c4009
  0.10000E+02, 0.20000E+02, 0.25000E+01, 0.40000E+01, 0.50000E+01, 0.12500E+01,
Packit 6c4009
  -1234567E01, 98765432E09, 12345678901.0, 98765432109.0, 12345678901.0,
Packit 6c4009
    98765432109.0,
Packit 6c4009
  -0.1000E+02, 0.20000E+02, 0.25000E+01, 0.40000E+01, 0.50000E+01, 0.12500E+01
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
const CHAR *str_long[] =
Packit 6c4009
{
Packit 6c4009
  L("-12345678987654321123456789987654321123456789987654321"),
Packit 6c4009
  L("-12345678987654321123456789987654321123456789987654321"),
Packit 6c4009
  L("-12,345,678987,654,321123,456,789987,654,321123,456,789987,654,321"),
Packit 6c4009
  L("-12,345,678987,654,321123,456,789987,654,321123,456,789987,654,321")
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
const CHAR *fmt_long[] =
Packit 6c4009
{
Packit 6c4009
  L("%9ld%9ld%9ld%9ld%9ld%9ld"),
Packit 6c4009
  L("%I9ld%I9ld%I9ld%I9ld%I9ld%I9ld"),
Packit 6c4009
  L("%'11ld%'11ld%'11ld%'11ld%'11ld%'11ld"),
Packit 6c4009
  L("%I'11ld%I'11ld%I'11ld%I'11ld%I'11ld%I'11ld")
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
const long int val_long[] =
Packit 6c4009
{
Packit 6c4009
  -12345678, 987654321, 123456789, 987654321, 123456789, 987654321
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
struct test
Packit 6c4009
{
Packit 6c4009
  const CHAR *str;
Packit 6c4009
  const CHAR *fmt;
Packit 6c4009
  int retval;
Packit 6c4009
} int_tests[] =
Packit 6c4009
{
Packit 6c4009
  { L("foo\n"), L("foo\nbar"), -1 },
Packit 6c4009
  { L("foo\n"), L("foo bar"), -1 },
Packit 6c4009
  { L("foo\n"), L("foo %d"), -1 },
Packit 6c4009
  { L("foo\n"), L("foo\n%d"), -1 },
Packit 6c4009
  { L("foon"), L("foonbar"), -1 },
Packit 6c4009
  { L("foon"), L("foon%d"), -1 },
Packit 6c4009
  { L("foo "), L("foo bar"), -1 },
Packit 6c4009
  { L("foo "), L("foo %d"), -1 },
Packit 6c4009
  { L("foo\t"), L("foo\tbar"), -1 },
Packit 6c4009
  { L("foo\t"), L("foo bar"), -1 },
Packit 6c4009
  { L("foo\t"), L("foo %d"), -1 },
Packit 6c4009
  { L("foo\t"), L("foo\t%d"), -1 },
Packit 6c4009
  { L("foo"), L("foo"), 0 },
Packit 6c4009
  { L("foon"), L("foo bar"), 0 },
Packit 6c4009
  { L("foon"), L("foo %d"), 0 },
Packit 6c4009
  { L("foo "), L("fooxbar"), 0 },
Packit 6c4009
  { L("foo "), L("foox%d"), 0 },
Packit 6c4009
  { L("foo bar"), L("foon"), 0 },
Packit 6c4009
  { L("foo bar"), L("foo bar"), 0 },
Packit 6c4009
  { L("foo bar"), L("foo %d"), 0 },
Packit 6c4009
  { L("foo bar"), L("foon%d"), 0 },
Packit 6c4009
  { L("foo (nil)"), L("foo %p"), 1},
Packit 6c4009
  { L("foo (nil)"), L("foo %4p"), 0},
Packit 6c4009
  { L("foo "), L("foo %n"), 0 },
Packit 6c4009
  { L("foo%bar1"), L("foo%%bar%d"), 1 },
Packit 6c4009
  /* Some OSes skip whitespace here while others don't.  */
Packit 6c4009
  { L("foo \t %bar1"), L("foo%%bar%d"), 1 }
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
struct test double_tests[] =
Packit 6c4009
{
Packit 6c4009
  { L("-1"), L("%1g"), 0 },
Packit 6c4009
  { L("-.1"), L("%2g"), 0 },
Packit 6c4009
  { L("-inf"), L("%3g"), 0 },
Packit 6c4009
  { L("+0"), L("%1g"),  },
Packit 6c4009
  { L("-0x1p0"), L("%2g"), 1 },
Packit 6c4009
  { L("-..1"), L("%g"), 0 },
Packit 6c4009
  { L("-inf"), L("%g"), 1 }
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
struct test2
Packit 6c4009
{
Packit 6c4009
  const CHAR *str;
Packit 6c4009
  const CHAR *fmt;
Packit 6c4009
  int retval;
Packit 6c4009
  char residual;
Packit 6c4009
} double_tests2[] =
Packit 6c4009
{
Packit 6c4009
  { L("0e+0"), L("%g%c"), 1, 0 },
Packit 6c4009
  { L("0xe+0"), L("%g%c"), 2, '+' },
Packit 6c4009
  { L("0x.e+0"), L("%g%c"), 2, '+' },
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
do_test (void)
Packit 6c4009
{
Packit 6c4009
  double d[6];
Packit 6c4009
  long l[6];
Packit 6c4009
  int i, j;
Packit 6c4009
  int tst_locale;
Packit 6c4009
  int result = 0;
Packit 6c4009
Packit 6c4009
  tst_locale = 1;
Packit 6c4009
  if (tst_locale)
Packit 6c4009
    if (setlocale (LC_ALL, "en_US.ISO-8859-1") == NULL)
Packit 6c4009
      {
Packit 6c4009
	puts ("Failed to set en_US locale, skipping locale related tests");
Packit 6c4009
	tst_locale = 0;
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < 4; ++i)
Packit 6c4009
    {
Packit 6c4009
      if (SSCANF (str_double[i], L("%11lf%11lf%11lf%11lf%11lf%11lf"),
Packit 6c4009
		  &d[0], &d[1], &d[2], &d[3], &d[4], &d[5]) != 6)
Packit 6c4009
	{
Packit 6c4009
	  printf ("Double sscanf test %d wrong number of "
Packit 6c4009
		  "assigned inputs\n", i);
Packit 6c4009
	  result = 1;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	for (j = 0; j < 6; ++j)
Packit 6c4009
	  if (d[j] != val_double[6 * i + j])
Packit 6c4009
	    {
Packit 6c4009
	      printf ("Double sscanf test %d failed (%g instead of %g)\n",
Packit 6c4009
		      i, d[j], val_double[6 * i + j]);
Packit 6c4009
	      result = 1;
Packit 6c4009
	      break;
Packit 6c4009
	    }
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < 4; ++i)
Packit 6c4009
    {
Packit 6c4009
      if (SSCANF (str_long[i], fmt_long[i],
Packit 6c4009
		  &l[0], &l[1], &l[2], &l[3], &l[4], &l[5]) != 6)
Packit 6c4009
	{
Packit 6c4009
	  printf ("Integer sscanf test %d wrong number of "
Packit 6c4009
		  "assigned inputs\n", i);
Packit 6c4009
	  result = 1;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	for (j = 0; j < 6; ++j)
Packit 6c4009
	  if (l[j] != val_long[j])
Packit 6c4009
	    {
Packit 6c4009
	      printf ("Integer sscanf test %d failed (%ld instead %ld)\n",
Packit 6c4009
		      i, l[j], val_long[j]);
Packit 6c4009
	      result = 1;
Packit 6c4009
	      break;
Packit 6c4009
	    }
Packit 6c4009
Packit 6c4009
      if (! tst_locale)
Packit 6c4009
	break;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < array_length (int_tests); ++i)
Packit 6c4009
    {
Packit 6c4009
      long dummy;
Packit 6c4009
      int ret;
Packit 6c4009
Packit 6c4009
      if ((ret = SSCANF (int_tests[i].str, int_tests[i].fmt,
Packit 6c4009
			 &dummy)) != int_tests[i].retval)
Packit 6c4009
	{
Packit 6c4009
	  printf ("int_tests[%d] returned %d != %d\n",
Packit 6c4009
		  i, ret, int_tests[i].retval);
Packit 6c4009
	  result = 1;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < array_length (double_tests); ++i)
Packit 6c4009
    {
Packit 6c4009
      double dummy;
Packit 6c4009
      int ret;
Packit 6c4009
Packit 6c4009
      if ((ret = SSCANF (double_tests[i].str, double_tests[i].fmt,
Packit 6c4009
			 &dummy)) != double_tests[i].retval)
Packit 6c4009
	{
Packit 6c4009
	  printf ("double_tests[%d] returned %d != %d\n",
Packit 6c4009
		  i, ret, double_tests[i].retval);
Packit 6c4009
	  result = 1;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (i = 0; i < array_length (double_tests2); ++i)
Packit 6c4009
    {
Packit 6c4009
      double dummy;
Packit 6c4009
      int ret;
Packit 6c4009
      char c = 0;
Packit 6c4009
Packit 6c4009
      if ((ret = SSCANF (double_tests2[i].str, double_tests2[i].fmt,
Packit 6c4009
			 &dummy, &c)) != double_tests2[i].retval)
Packit 6c4009
	{
Packit 6c4009
	  printf ("double_tests2[%d] returned %d != %d\n",
Packit 6c4009
		  i, ret, double_tests2[i].retval);
Packit 6c4009
	  result = 1;
Packit 6c4009
	}
Packit 6c4009
      else if (ret == 2 && c != double_tests2[i].residual)
Packit 6c4009
	{
Packit 6c4009
	  printf ("double_tests2[%d] stopped at '%c' != '%c'\n",
Packit 6c4009
		  i, c, double_tests2[i].residual);
Packit 6c4009
	  result = 1;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* BZ #16618
Packit 6c4009
     The test will segfault during SSCANF if the buffer overflow
Packit 6c4009
     is not fixed.  The size of `s` is such that it forces the use
Packit 6c4009
     of malloc internally and this triggers the incorrect computation.
Packit 6c4009
     Thus the value for SIZE is arbitrariy high enough that malloc
Packit 6c4009
     is used.  */
Packit 6c4009
  {
Packit 6c4009
#define SIZE 131072
Packit 6c4009
    CHAR *s = malloc ((SIZE + 1) * sizeof (*s));
Packit 6c4009
    if (s == NULL)
Packit 6c4009
      abort ();
Packit 6c4009
    for (size_t i = 0; i < SIZE; i++)
Packit 6c4009
      s[i] = L('0');
Packit 6c4009
    s[SIZE] = L('\0');
Packit 6c4009
    int i = 42;
Packit 6c4009
    /* Scan multi-digit zero into `i`.  */
Packit 6c4009
    if (SSCANF (s, L("%d"), &i) != 1)
Packit 6c4009
      {
Packit 6c4009
	printf ("FAIL: bug16618: SSCANF did not read one input item.\n");
Packit 6c4009
	result = 1;
Packit 6c4009
      }
Packit 6c4009
    if (i != 0)
Packit 6c4009
      {
Packit 6c4009
	printf ("FAIL: bug16618: Value of `i` was not zero as expected.\n");
Packit 6c4009
	result = 1;
Packit 6c4009
      }
Packit 6c4009
    free (s);
Packit 6c4009
    if (result != 1)
Packit 6c4009
      printf ("PASS: bug16618: Did not crash.\n");
Packit 6c4009
#undef SIZE
Packit 6c4009
  }
Packit 6c4009
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define TEST_FUNCTION do_test ()
Packit 6c4009
#include "../test-skeleton.c"