[PATCH 11/15] stdio-common: Fix bad NaN crash in scanf input specifier tests [BZ #32857]

Maciej W. Rozycki macro@orcam.me.uk
Sat Apr 19 10:44:20 GMT 2025


From: Maciej W. Rozycki <macro@redhat.com>

Fix a null pointer dereference causing a crash in 'read_real' when the 
terminating null character is written for use with the subsequent call 
to 'nan' for invalid NaN reference input, such as:

%a:nan:1:3:nanny:

by moving all the 'n-char-sequence' handling under the check for the 
opening parenthesis.

No test case added as it's a test case issue in the first place.
---
 stdio-common/tst-scanf-format-real.h |   68 ++++++++++++++++++-----------------
 1 file changed, 35 insertions(+), 33 deletions(-)

glibc-tst-scanf-format-all-bz32857-real-nan-arg-fix.diff
Index: glibc/stdio-common/tst-scanf-format-real.h
===================================================================
--- glibc.orig/stdio-common/tst-scanf-format-real.h
+++ glibc/stdio-common/tst-scanf-format-real.h
@@ -201,43 +201,45 @@ out:									\
 	    goto out;							\
 	  }								\
 									\
-	size_t seq_size = 0;						\
-	char *seq = NULL;						\
-	i = 0;								\
 	if (ch == '(')							\
-	  while (1)							\
-	    {								\
-	      if (i == seq_size)					\
-		{							\
-		  seq_size += SIZE_CHUNK;				\
-		  /* Add an extra byte for the terminating null		\
-		     character.  */					\
-		  seq = xrealloc (seq, seq_size + 1);			\
-		}							\
-	      ch = read_input ();					\
-	      if (ch == ')')						\
-		break;							\
-	      if (ch != '_' && !isdigit (ch)				\
-		  && !(ch >= 'A' && ch <= 'Z')				\
-		  && !(ch >= 'a' && ch <= 'z'))				\
-		{							\
-		  free (seq);						\
-		  err = ch < 0 ? ch : INPUT_FORMAT;			\
-		  v = NAN;						\
-		  goto out;						\
-		}							\
-	      seq[i++] = ch;						\
-	    }								\
-	seq[i] = '\0';							\
-									\
-	ch = read_input ();						\
-	if (ch == ':')							\
 	  {								\
-	    v = m ? -nan (v, seq) : nan (v, seq);			\
+	    size_t seq_size = 0;					\
+	    char *seq = NULL;						\
+	    i = 0;							\
+	    while (1)							\
+	      {								\
+		if (i == seq_size)					\
+		  {							\
+		    seq_size += SIZE_CHUNK;				\
+		    /* Add an extra byte for the terminating null	\
+		       character.  */					\
+		    seq = xrealloc (seq, seq_size + 1);			\
+		  }							\
+		ch = read_input ();					\
+		if (ch == ')')						\
+		  break;						\
+		if (ch != '_' && !isdigit (ch)				\
+		    && !(ch >= 'A' && ch <= 'Z')			\
+		    && !(ch >= 'a' && ch <= 'z'))			\
+		  {							\
+		    free (seq);						\
+		    err = ch < 0 ? ch : INPUT_FORMAT;			\
+		    v = NAN;						\
+		    goto out;						\
+		  }							\
+		seq[i++] = ch;						\
+	      }								\
+	    seq[i] = '\0';						\
+									\
+	    ch = read_input ();						\
+	    if (ch == ':')						\
+	      {								\
+		v = m ? -nan (v, seq) : nan (v, seq);			\
+		free (seq);						\
+		goto out;						\
+	      }								\
 	    free (seq);							\
-	    goto out;							\
 	  }								\
-	free (seq);							\
       }									\
       err = ch < 0 ? ch : INPUT_FORMAT;					\
       v = NAN;								\


More information about the Libc-alpha mailing list