MSVCRT: Fix reading of signed numbers with unsigned read types in scanf

H. Verbeet hverbeet at gmail.com
Sat Mar 25 20:10:28 CST 2006


Unsigned read types should still match signed input. Currently signed
values are skipped for those read types. This patch fixes a bug with
the C&C Generals INI parser.

Changelog:
  - Fix reading of signed numbers with unsigned read types in scanf
  - Extend the scanf test
-------------- next part --------------
diff --git a/dlls/msvcrt/scanf.h b/dlls/msvcrt/scanf.h
index 4c27c68..ad3245d 100644
--- a/dlls/msvcrt/scanf.h
+++ b/dlls/msvcrt/scanf.h
@@ -114,7 +114,7 @@ _FUNCTION_ {
 	 * the form %[*][width][{h | l | I64 | L}]type */
         else if (*format == '%') {
             int st = 0; int suppress = 0; int width = 0;
-	    int base, number_signed;
+	    int base;
 	    int h_prefix = 0;
 	    int l_prefix = 0;
 	    int L_prefix = 0;
@@ -157,19 +157,19 @@ _FUNCTION_ {
             switch(*format) {
 	    case 'x':
 	    case 'X': /* hexadecimal integer. */
-		base = 16; number_signed = 0;
+		base = 16;
 		goto number;
 	    case 'o': /* octal integer */
-		base = 8; number_signed = 0;
+		base = 8;
 		goto number;
 	    case 'u': /* unsigned decimal integer */
-		base = 10; number_signed = 0;
+		base = 10;
 		goto number;
 	    case 'd': /* signed decimal integer */
-		base = 10; number_signed = 1;
+		base = 10;
 		goto number;
 	    case 'i': /* generic integer */
-		base = 10; number_signed = 1;
+		base = 10;
 	    number: {
 		    /* read an integer */
 		    ULONGLONG cur = 0;
@@ -179,8 +179,7 @@ _FUNCTION_ {
                     while ((nch!=_EOF_) && _ISSPACE_(nch))
                         nch = _GETC_(file);
                     /* get sign */
-                    if (number_signed && (nch == '-' ||
-					  nch == '+')) {
+                    if (nch == '-' || nch == '+') {
 			negative = (nch=='-');
                         nch = _GETC_(file);
 			if (width>0) width--;
@@ -225,22 +224,10 @@ _FUNCTION_ {
                     st = 1;
                     if (!suppress) {
 #define _SET_NUMBER_(type) *va_arg(ap, type*) = negative ? -cur : cur
-			if (number_signed) {
-			    if (I64_prefix) _SET_NUMBER_(LONGLONG);
-			    else if (l_prefix) _SET_NUMBER_(long int);
-			    else if (h_prefix) _SET_NUMBER_(short int);
-			    else _SET_NUMBER_(int);
-			} else {
-			    if (negative) {
-				WARN("Dropping sign in reading a negative number into an unsigned value");
-				negative = 0;
-			    }
-			    if (I64_prefix) _SET_NUMBER_(ULONGLONG);
-			    else if (l_prefix) _SET_NUMBER_(unsigned long int);
-			    else if (h_prefix)
-				_SET_NUMBER_(unsigned short int);
-			    else _SET_NUMBER_(unsigned int);
-			}
+			if (I64_prefix) _SET_NUMBER_(LONGLONG);
+			else if (l_prefix) _SET_NUMBER_(long int);
+			else if (h_prefix) _SET_NUMBER_(short int);
+			else _SET_NUMBER_(int);
 		    }
                 }
                 break;
diff --git a/dlls/msvcrt/tests/scanf.c b/dlls/msvcrt/tests/scanf.c
index 2482825..d90a3bd 100644
--- a/dlls/msvcrt/tests/scanf.c
+++ b/dlls/msvcrt/tests/scanf.c
@@ -52,6 +52,11 @@ static void test_sscanf( void )
     ok( sscanf(buffer, "%x", &result) == 1, "sscanf failed\n" );
     ok( result == 0x51, "sscanf reads %x instead of %x\n", result, 0x51 );
 
+    result = 0;
+    ret = sscanf("-1", "%x", &result);
+    ok(ret == 1, "Wrong number of arguments read: %d (expected 1)\n", ret);
+    ok(result == -1, "Read %d, expected -1\n", result);
+
     /* check % followed by any char */
     strcpy(buffer,"\"%12@");
     strcpy(format,"%\"%%%d%@");  /* work around gcc format check */
@@ -93,9 +98,29 @@ static void test_sscanf( void )
     ret = sscanf(buffer, "%i", &result);
     ok(ret == 1, "Wrong number of arguments read: %d\n", ret);
     ok(result == 123, "Wrong number read\n");
+    result = 0;
+    ret = sscanf("-1", "%i", &result);
+    ok(ret == 1, "Wrong number of arguments read: %d (expected 1)\n", ret);
+    ok(result == -1, "Read %d, expected -1\n", result);
     ret = sscanf(buffer, "%d", &result);
     ok(ret == 1, "Wrong number of arguments read: %d\n", ret);
     ok(result == 123, "Wrong number read\n");
+    result = 0;
+    ret = sscanf("-1", "%d", &result);
+    ok(ret == 1, "Wrong number of arguments read: %d (expected 1)\n", ret);
+    ok(result == -1, "Read %d, expected -1\n", result);
+
+    /* %o */
+    result = 0;
+    ret = sscanf("-1", "%o", &result);
+    ok(ret == 1, "Wrong number of arguments read: %d (expected 1)\n", ret);
+    ok(result == -1, "Read %d, expected -1\n", result);
+
+    /* %u */
+    result = 0;
+    ret = sscanf("-1", "%u", &result);
+    ok(ret == 1, "Wrong number of arguments read: %d (expected 1)\n", ret);
+    ok(result == -1, "Read %d, expected -1\n", result);
 
     /* Check %c */
     strcpy(buffer,"a");






More information about the wine-patches mailing list