newlib: vf[w]scanf: add validity checks
POSIX requires that directive characters appear in a certain sequence: 1. '%' or '%<n>$' 2. optional '*' 3. optional field width digits 4. optional 'm' (not yet implemented) 5. optional length modifier ('l', 'L', 'll', 'h', 'hh', 'j', 't', 'z') 6. conversion specifier ('d', 's', etc) Add a few basic validity checks to that effect, otherwise reject directive as match failure. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
31f11d0572
commit
0fd2c9bd12
|
@ -564,9 +564,14 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case '*':
|
case '*':
|
||||||
|
if ((flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS))
|
||||||
|
|| width)
|
||||||
|
goto match_failure;
|
||||||
flags |= SUPPRESS;
|
flags |= SUPPRESS;
|
||||||
goto again;
|
goto again;
|
||||||
case 'l':
|
case 'l':
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
|
#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
|
||||||
if (*fmt == 'l') /* Check for 'll' = long long (SUSv3) */
|
if (*fmt == 'l') /* Check for 'll' = long long (SUSv3) */
|
||||||
{
|
{
|
||||||
|
@ -578,9 +583,13 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
flags |= LONG;
|
flags |= LONG;
|
||||||
goto again;
|
goto again;
|
||||||
case 'L':
|
case 'L':
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
flags |= LONGDBL;
|
flags |= LONGDBL;
|
||||||
goto again;
|
goto again;
|
||||||
case 'h':
|
case 'h':
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
#ifdef _WANT_IO_C99_FORMATS
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
if (*fmt == 'h') /* Check for 'hh' = char int (SUSv3) */
|
if (*fmt == 'h') /* Check for 'hh' = char int (SUSv3) */
|
||||||
{
|
{
|
||||||
|
@ -593,12 +602,16 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
goto again;
|
goto again;
|
||||||
#ifdef _WANT_IO_C99_FORMATS
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
case 'j': /* intmax_t */
|
case 'j': /* intmax_t */
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
if (sizeof (intmax_t) == sizeof (long))
|
if (sizeof (intmax_t) == sizeof (long))
|
||||||
flags |= LONG;
|
flags |= LONG;
|
||||||
else
|
else
|
||||||
flags |= LONGDBL;
|
flags |= LONGDBL;
|
||||||
goto again;
|
goto again;
|
||||||
case 't': /* ptrdiff_t */
|
case 't': /* ptrdiff_t */
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
if (sizeof (ptrdiff_t) < sizeof (int))
|
if (sizeof (ptrdiff_t) < sizeof (int))
|
||||||
/* POSIX states ptrdiff_t is 16 or more bits, as
|
/* POSIX states ptrdiff_t is 16 or more bits, as
|
||||||
is short. */
|
is short. */
|
||||||
|
@ -615,6 +628,8 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
flags |= LONGDBL;
|
flags |= LONGDBL;
|
||||||
goto again;
|
goto again;
|
||||||
case 'z': /* size_t */
|
case 'z': /* size_t */
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
if (sizeof (size_t) < sizeof (int))
|
if (sizeof (size_t) < sizeof (int))
|
||||||
/* POSIX states size_t is 16 or more bits, as is short. */
|
/* POSIX states size_t is 16 or more bits, as is short. */
|
||||||
flags |= SHORT;
|
flags |= SHORT;
|
||||||
|
@ -641,11 +656,15 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
case '7':
|
case '7':
|
||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
width = width * 10 + c - '0';
|
width = width * 10 + c - '0';
|
||||||
goto again;
|
goto again;
|
||||||
|
|
||||||
#ifndef _NO_POS_ARGS
|
#ifndef _NO_POS_ARGS
|
||||||
case '$':
|
case '$':
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS))
|
||||||
|
goto match_failure;
|
||||||
if (width <= MAX_POS_ARGS)
|
if (width <= MAX_POS_ARGS)
|
||||||
{
|
{
|
||||||
N = width - 1;
|
N = width - 1;
|
||||||
|
|
|
@ -518,9 +518,13 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case L'*':
|
case L'*':
|
||||||
|
if ((flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS))
|
||||||
|
|| width)
|
||||||
flags |= SUPPRESS;
|
flags |= SUPPRESS;
|
||||||
goto again;
|
goto again;
|
||||||
case L'l':
|
case L'l':
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
|
#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
|
||||||
if (*fmt == L'l') /* Check for 'll' = long long (SUSv3) */
|
if (*fmt == L'l') /* Check for 'll' = long long (SUSv3) */
|
||||||
{
|
{
|
||||||
|
@ -532,10 +536,14 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
flags |= LONG;
|
flags |= LONG;
|
||||||
goto again;
|
goto again;
|
||||||
case L'L':
|
case L'L':
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
flags |= LONGDBL;
|
flags |= LONGDBL;
|
||||||
goto again;
|
goto again;
|
||||||
case L'h':
|
case L'h':
|
||||||
#ifdef _WANT_IO_C99_FORMATS
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
if (*fmt == 'h') /* Check for 'hh' = char int (SUSv3) */
|
if (*fmt == 'h') /* Check for 'hh' = char int (SUSv3) */
|
||||||
{
|
{
|
||||||
++fmt;
|
++fmt;
|
||||||
|
@ -547,12 +555,16 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
goto again;
|
goto again;
|
||||||
#ifdef _WANT_IO_C99_FORMATS
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
case L'j': /* intmax_t */
|
case L'j': /* intmax_t */
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
if (sizeof (intmax_t) == sizeof (long))
|
if (sizeof (intmax_t) == sizeof (long))
|
||||||
flags |= LONG;
|
flags |= LONG;
|
||||||
else
|
else
|
||||||
flags |= LONGDBL;
|
flags |= LONGDBL;
|
||||||
goto again;
|
goto again;
|
||||||
case L't': /* ptrdiff_t */
|
case L't': /* ptrdiff_t */
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
if (sizeof (ptrdiff_t) < sizeof (int))
|
if (sizeof (ptrdiff_t) < sizeof (int))
|
||||||
/* POSIX states ptrdiff_t is 16 or more bits, as
|
/* POSIX states ptrdiff_t is 16 or more bits, as
|
||||||
is short. */
|
is short. */
|
||||||
|
@ -569,6 +581,8 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
flags |= LONGDBL;
|
flags |= LONGDBL;
|
||||||
goto again;
|
goto again;
|
||||||
case L'z': /* size_t */
|
case L'z': /* size_t */
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
if (sizeof (size_t) < sizeof (int))
|
if (sizeof (size_t) < sizeof (int))
|
||||||
/* POSIX states size_t is 16 or more bits, as is short. */
|
/* POSIX states size_t is 16 or more bits, as is short. */
|
||||||
flags |= SHORT;
|
flags |= SHORT;
|
||||||
|
@ -595,11 +609,15 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
|
||||||
case L'7':
|
case L'7':
|
||||||
case L'8':
|
case L'8':
|
||||||
case L'9':
|
case L'9':
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL))
|
||||||
|
goto match_failure;
|
||||||
width = width * 10 + c - L'0';
|
width = width * 10 + c - L'0';
|
||||||
goto again;
|
goto again;
|
||||||
|
|
||||||
#ifndef _NO_POS_ARGS
|
#ifndef _NO_POS_ARGS
|
||||||
case L'$':
|
case L'$':
|
||||||
|
if (flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS))
|
||||||
|
goto match_failure;
|
||||||
if (width <= MAX_POS_ARGS)
|
if (width <= MAX_POS_ARGS)
|
||||||
{
|
{
|
||||||
N = width - 1;
|
N = width - 1;
|
||||||
|
|
Loading…
Reference in New Issue