public inbox for newlib-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] newlib: vf[w]scanf: add validity checks
@ 2017-11-30 10:56 Corinna Vinschen
  0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2017-11-30 10:56 UTC (permalink / raw)
  To: newlib-cvs

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=0fd2c9bd1290c84d2160191d105147bf75629411

commit 0fd2c9bd1290c84d2160191d105147bf75629411
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Thu Nov 30 11:55:27 2017 +0100

    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>

Diff:
---
 newlib/libc/stdio/vfscanf.c  | 19 +++++++++++++++++++
 newlib/libc/stdio/vfwscanf.c | 18 ++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/newlib/libc/stdio/vfscanf.c b/newlib/libc/stdio/vfscanf.c
index a81ebd5..9d6f124 100644
--- a/newlib/libc/stdio/vfscanf.c
+++ b/newlib/libc/stdio/vfscanf.c
@@ -564,9 +564,14 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
 	  continue;
 
 	case '*':
+	  if ((flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS))
+	      || width)
+	    goto match_failure;
 	  flags |= SUPPRESS;
 	  goto again;
 	case 'l':
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
 	  if (*fmt == 'l')	/* Check for 'll' = long long (SUSv3) */
 	    {
@@ -578,9 +583,13 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
 	    flags |= LONG;
 	  goto again;
 	case 'L':
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 	  flags |= LONGDBL;
 	  goto again;
 	case 'h':
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 #ifdef _WANT_IO_C99_FORMATS
 	  if (*fmt == 'h')	/* Check for 'hh' = char int (SUSv3) */
 	    {
@@ -593,12 +602,16 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
 	  goto again;
 #ifdef _WANT_IO_C99_FORMATS
 	case 'j': /* intmax_t */
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 	  if (sizeof (intmax_t) == sizeof (long))
 	    flags |= LONG;
 	  else
 	    flags |= LONGDBL;
 	  goto again;
 	case 't': /* ptrdiff_t */
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 	  if (sizeof (ptrdiff_t) < sizeof (int))
 	    /* POSIX states ptrdiff_t is 16 or more bits, as
 	       is short.  */
@@ -615,6 +628,8 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
 	    flags |= LONGDBL;
 	  goto again;
 	case 'z': /* size_t */
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 	  if (sizeof (size_t) < sizeof (int))
 	    /* POSIX states size_t is 16 or more bits, as is short.  */
 	    flags |= SHORT;
@@ -641,11 +656,15 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
 	case '7':
 	case '8':
 	case '9':
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 	  width = width * 10 + c - '0';
 	  goto again;
 
 #ifndef _NO_POS_ARGS
 	case '$':
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS))
+	    goto match_failure;
 	  if (width <= MAX_POS_ARGS)
 	    {
 	      N = width - 1;
diff --git a/newlib/libc/stdio/vfwscanf.c b/newlib/libc/stdio/vfwscanf.c
index 0d34fb1..54bbb09 100644
--- a/newlib/libc/stdio/vfwscanf.c
+++ b/newlib/libc/stdio/vfwscanf.c
@@ -518,9 +518,13 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
 	  continue;
 
 	case L'*':
+	  if ((flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS))
+	      || width)
 	  flags |= SUPPRESS;
 	  goto again;
 	case L'l':
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
 	  if (*fmt == L'l')	/* Check for 'll' = long long (SUSv3) */
 	    {
@@ -532,10 +536,14 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
 	    flags |= LONG;
 	  goto again;
 	case L'L':
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 	  flags |= LONGDBL;
 	  goto again;
 	case L'h':
 #ifdef _WANT_IO_C99_FORMATS
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 	  if (*fmt == 'h')	/* Check for 'hh' = char int (SUSv3) */
 	    {
 	      ++fmt;
@@ -547,12 +555,16 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
 	  goto again;
 #ifdef _WANT_IO_C99_FORMATS
 	case L'j': /* intmax_t */
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 	  if (sizeof (intmax_t) == sizeof (long))
 	    flags |= LONG;
 	  else
 	    flags |= LONGDBL;
 	  goto again;
 	case L't': /* ptrdiff_t */
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 	  if (sizeof (ptrdiff_t) < sizeof (int))
 	    /* POSIX states ptrdiff_t is 16 or more bits, as
 	       is short.  */
@@ -569,6 +581,8 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
 	    flags |= LONGDBL;
 	  goto again;
 	case L'z': /* size_t */
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 	  if (sizeof (size_t) < sizeof (int))
 	    /* POSIX states size_t is 16 or more bits, as is short.  */
 	    flags |= SHORT;
@@ -595,11 +609,15 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap),
 	case L'7':
 	case L'8':
 	case L'9':
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL))
+	    goto match_failure;
 	  width = width * 10 + c - L'0';
 	  goto again;
 
 #ifndef _NO_POS_ARGS
 	case L'$':
+	  if (flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS))
+	    goto match_failure;
 	  if (width <= MAX_POS_ARGS)
 	    {
 	      N = width - 1;


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2017-11-30 10:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-30 10:56 [newlib-cygwin] newlib: vf[w]scanf: add validity checks Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).