[PATCH 02/15] stdio-common: Reject significands w/o digits in scanf [BZ #12701]

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


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

Reject invalid formatted scanf real input data the significand part of 
which is comprised of a hexadecimal prefix followed by a decimal point 
only, optionally preceded by a sign.  Such data is a prefix of, but not 
a matching input sequence and it is required by ISO C to cause a 
matching failure.

Currently a matching success is instead incorrectly produced along with 
the conversion result of zero, with data up to and including the decimal 
point consumed from input.

Technically this change also causes lone . to be rejected early, though 
it doesn't change semantics, because unlike 0x. it's not valid input to 
'strtod', etc. so it gets rejected at actual conversion time later on 
anyway.

Test cases follow as separate changes.
---
 stdio-common/vfscanf-internal.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

glibc-scanf-bz12701-real-nodigit.diff
Index: glibc/stdio-common/vfscanf-internal.c
===================================================================
--- glibc.orig/stdio-common/vfscanf-internal.c
+++ glibc/stdio-common/vfscanf-internal.c
@@ -2556,15 +2556,15 @@ __vfscanf_internal (FILE *s, const char
 	      goto errout;
 	    }
 
-	  /* Have we read any character?  If we try to read a number
-	     in hexadecimal notation and we have read only the `0x'
-	     prefix this is an error.  Also it is an error where we
-	     have read no digits after the exponent character.  */
+	  /* Have we read any character?  If we try to read a number in
+	     hexadecimal notation and we have read only the `0x' prefix,
+	     this is an error.  Also it is an error where we have read
+	     no digits (before or after the exponent character).  */
 	  if (__glibc_unlikely (char_buffer_size (&charbuf) == got_sign
 				|| ((flags & HEXA_FLOAT)
 				    && (char_buffer_size (&charbuf)
 					== 2 + got_sign)))
-				|| (got_e && !got_digit))
+				|| !got_digit)
 	    conv_error ();
 
 	scan_float:


More information about the Libc-alpha mailing list