Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [day] [month] [year] [list]
Date: Wed, 31 May 2023 16:05:41 +0200
From: Jens Gustedt <Jens.Gustedt@...ia.fr>
To: musl@...ts.openwall.com
Subject: [C23 scanf 1/3] C23: Add the b specifier for scanf and allow 0b and 0B prefixes in integers

This affects all functions that read integers from strings or streams
such as scanf and strtoX.

This patch changes the behavior deep down inside, namely the __intscan
function. This is a semantic change. Parsing of integers that use base
0 (for the strtoX functions) or the "i" specifier (for scanf) may
observe different behavior when linked (statically or dynamically)
against this new version.

The C committtee did explicitly reject concerns about this
incompatibility, judging it as being only a minor risk.
---
 src/internal/intscan.c | 13 +++++++++++--
 src/stdio/vfscanf.c    |  5 ++++-
 src/stdio/vfwscanf.c   |  4 ++--
 3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/src/internal/intscan.c b/src/internal/intscan.c
index a4a5ae86..57424554 100644
--- a/src/internal/intscan.c
+++ b/src/internal/intscan.c
@@ -38,9 +38,9 @@ unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long
 		neg = -(c=='-');
 		c = shgetc(f);
 	}
-	if ((base == 0 || base == 16) && c=='0') {
+	if ((base == 0 || base == 2 || base == 16) && c=='0') {
 		c = shgetc(f);
-		if ((c|32)=='x') {
+		if ((c|32)=='x' && base != 2) {
 			c = shgetc(f);
 			if (val[c]>=16) {
 				shunget(f);
@@ -49,6 +49,15 @@ unsigned long long __intscan(FILE *f, unsigned base, int pok, unsigned long long
 				return 0;
 			}
 			base = 16;
+		} else if ((c|32)=='b' && base != 16) {
+			c = shgetc(f);
+			if (val[c]>=2) {
+				shunget(f);
+				if (pok) shunget(f);
+				else shlim(f, 0);
+				return 0;
+			}
+			base = 2;
 		} else if (base == 0) {
 			base = 8;
 		}
diff --git a/src/stdio/vfscanf.c b/src/stdio/vfscanf.c
index b78a374d..f72ac9c9 100644
--- a/src/stdio/vfscanf.c
+++ b/src/stdio/vfscanf.c
@@ -150,7 +150,7 @@ int vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap)
 		case 'L':
 			size = SIZE_L;
 			break;
-		case 'd': case 'i': case 'o': case 'u': case 'x':
+		case 'b': case 'd': case 'i': case 'o': case 'u': case 'x':
 		case 'a': case 'e': case 'f': case 'g':
 		case 'A': case 'E': case 'F': case 'G': case 'X':
 		case 's': case 'c': case '[':
@@ -286,6 +286,9 @@ int vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap)
 		case 'o':
 			base = 8;
 			goto int_common;
+		case 'b':
+			base = 2;
+			goto int_common;
 		case 'd':
 		case 'u':
 			base = 10;
diff --git a/src/stdio/vfwscanf.c b/src/stdio/vfwscanf.c
index 82f48604..17f5a2f9 100644
--- a/src/stdio/vfwscanf.c
+++ b/src/stdio/vfwscanf.c
@@ -173,7 +173,7 @@ int vfwscanf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap)
 		case 'L':
 			size = SIZE_L;
 			break;
-		case 'd': case 'i': case 'o': case 'u': case 'x':
+		case 'b': case 'd': case 'i': case 'o': case 'u': case 'x':
 		case 'a': case 'e': case 'f': case 'g':
 		case 'A': case 'E': case 'F': case 'G': case 'X':
 		case 's': case 'c': case '[':
@@ -294,7 +294,7 @@ int vfwscanf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap)
 			}
 			break;
 
-		case 'd': case 'i': case 'o': case 'u': case 'x':
+		case 'b': case 'd': case 'i': case 'o': case 'u': case 'x':
 		case 'a': case 'e': case 'f': case 'g':
 		case 'A': case 'E': case 'F': case 'G': case 'X':
 		case 'p':
-- 
2.34.1

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.