public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* sscanf("-1", "%d", &i) fails, returns 0
@ 2002-11-08 13:32 Douglas Gilbert
  2002-11-08 19:22 ` [PATCH] " Randy.Dunlap
  0 siblings, 1 reply; 12+ messages in thread
From: Douglas Gilbert @ 2002-11-08 13:32 UTC (permalink / raw)
  To: linux-kernel

In lk 2.5.46-bk3 the expression in the subject line
fails to write into "i" and returns 0. Drop the minus
sign and it works.

Doug Gilbert


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
  2002-11-08 13:32 sscanf("-1", "%d", &i) fails, returns 0 Douglas Gilbert
@ 2002-11-08 19:22 ` Randy.Dunlap
  2002-11-08 19:41   ` Richard B. Johnson
  0 siblings, 1 reply; 12+ messages in thread
From: Randy.Dunlap @ 2002-11-08 19:22 UTC (permalink / raw)
  To: Douglas Gilbert; +Cc: linux-kernel, torvalds

On Sat, 9 Nov 2002, Douglas Gilbert wrote:

| In lk 2.5.46-bk3 the expression in the subject line
| fails to write into "i" and returns 0. Drop the minus
| sign and it works.

Here's an unobstrusive patch to correct that.
Please apply.

-- 
~Randy



--- ./lib/vsprintf.c%signed	Mon Nov  4 14:30:49 2002
+++ ./lib/vsprintf.c	Fri Nov  8 11:20:03 2002
@@ -517,6 +517,7 @@
 {
 	const char *str = buf;
 	char *next;
+	char *dig;
 	int num = 0;
 	int qualifier;
 	int base;
@@ -638,12 +639,13 @@
 		while (isspace(*str))
 			str++;

-		if (!*str
-                    || (base == 16 && !isxdigit(*str))
-                    || (base == 10 && !isdigit(*str))
-                    || (base == 8 && (!isdigit(*str) || *str > '7'))
-                    || (base == 0 && !isdigit(*str)))
-			break;
+		dig = (*str == '-') ? (str + 1) : str;
+		if (!*dig
+                    || (base == 16 && !isxdigit(*dig))
+                    || (base == 10 && !isdigit(*dig))
+                    || (base == 8 && (!isdigit(*dig) || *dig > '7'))
+                    || (base == 0 && !isdigit(*dig)))
+				break;

 		switch(qualifier) {
 		case 'h':


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
  2002-11-08 19:22 ` [PATCH] " Randy.Dunlap
@ 2002-11-08 19:41   ` Richard B. Johnson
  2002-11-08 19:59     ` Randy.Dunlap
  0 siblings, 1 reply; 12+ messages in thread
From: Richard B. Johnson @ 2002-11-08 19:41 UTC (permalink / raw)
  To: Randy.Dunlap; +Cc: Douglas Gilbert, linux-kernel, torvalds

On Fri, 8 Nov 2002, Randy.Dunlap wrote:

> On Sat, 9 Nov 2002, Douglas Gilbert wrote:
> 
> | In lk 2.5.46-bk3 the expression in the subject line
> | fails to write into "i" and returns 0. Drop the minus
> | sign and it works.
> 
> Here's an unobstrusive patch to correct that.
> Please apply.
> 
> -- 
> ~Randy
> 
> 
> 
> --- ./lib/vsprintf.c%signed	Mon Nov  4 14:30:49 2002
> +++ ./lib/vsprintf.c	Fri Nov  8 11:20:03 2002
> @@ -517,6 +517,7 @@
>  {
>  	const char *str = buf;
>  	char *next;
> +	char *dig;
>  	int num = 0;
>  	int qualifier;
>  	int base;
> @@ -638,12 +639,13 @@
>  		while (isspace(*str))
>  			str++;
> 
> -		if (!*str
> -                    || (base == 16 && !isxdigit(*str))
> -                    || (base == 10 && !isdigit(*str))
> -                    || (base == 8 && (!isdigit(*str) || *str > '7'))
> -                    || (base == 0 && !isdigit(*str)))
> -			break;
> +		dig = (*str == '-') ? (str + 1) : str;
> +		if (!*dig
> +                    || (base == 16 && !isxdigit(*dig))
> +                    || (base == 10 && !isdigit(*dig))
> +                    || (base == 8 && (!isdigit(*dig) || *dig > '7'))
> +                    || (base == 0 && !isdigit(*dig)))
> +				break;
> 
>  		switch(qualifier) {
>  		case 'h':
> 
> -

I was thinking that if anybody ever had to change any of this
stuff, it might be a good idea to do the indirection only once?
All those "splats" over and over again are costly.

Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
   Bush : The Fourth Reich of America



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
  2002-11-08 19:41   ` Richard B. Johnson
@ 2002-11-08 19:59     ` Randy.Dunlap
  2002-11-08 20:19       ` Linus Torvalds
  2002-11-08 20:23       ` Richard B. Johnson
  0 siblings, 2 replies; 12+ messages in thread
From: Randy.Dunlap @ 2002-11-08 19:59 UTC (permalink / raw)
  To: Richard B. Johnson; +Cc: Douglas Gilbert, linux-kernel, torvalds

On Fri, 8 Nov 2002, Richard B. Johnson wrote:

| On Fri, 8 Nov 2002, Randy.Dunlap wrote:
|
| > On Sat, 9 Nov 2002, Douglas Gilbert wrote:
| >
| > | In lk 2.5.46-bk3 the expression in the subject line
| > | fails to write into "i" and returns 0. Drop the minus
| > | sign and it works.
| >
| > Here's an unobstrusive patch to correct that.
| > Please apply.
| >
| > --
| > ~Randy
| > -
|
| I was thinking that if anybody ever had to change any of this
| stuff, it might be a good idea to do the indirection only once?
| All those "splats" over and over again are costly.

Sure, it looks cleaner that way, although gcc has already put <*dig>
in a local register; i.e., it's not pulled from memory for each test.
Here's a (tested) version that does that.

-- 
~Randy



--- ./lib/vsprintf.c%signed	Mon Nov  4 14:30:49 2002
+++ ./lib/vsprintf.c	Fri Nov  8 12:03:15 2002
@@ -517,6 +517,7 @@
 {
 	const char *str = buf;
 	char *next;
+	char *dig, onedig;
 	int num = 0;
 	int qualifier;
 	int base;
@@ -638,12 +639,14 @@
 		while (isspace(*str))
 			str++;

-		if (!*str
-                    || (base == 16 && !isxdigit(*str))
-                    || (base == 10 && !isdigit(*str))
-                    || (base == 8 && (!isdigit(*str) || *str > '7'))
-                    || (base == 0 && !isdigit(*str)))
-			break;
+		dig = (*str == '-') ? (str + 1) : str;
+		onedig = *dig;
+		if (!onedig
+                    || (base == 16 && !isxdigit(onedig))
+                    || (base == 10 && !isdigit(onedig))
+                    || (base == 8 && (!isdigit(onedig) || onedig > '7'))
+                    || (base == 0 && !isdigit(onedig)))
+				break;

 		switch(qualifier) {
 		case 'h':


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
  2002-11-08 19:59     ` Randy.Dunlap
@ 2002-11-08 20:19       ` Linus Torvalds
  2002-11-08 22:09         ` Randy.Dunlap
  2002-11-08 20:23       ` Richard B. Johnson
  1 sibling, 1 reply; 12+ messages in thread
From: Linus Torvalds @ 2002-11-08 20:19 UTC (permalink / raw)
  To: Randy.Dunlap; +Cc: Richard B. Johnson, Douglas Gilbert, linux-kernel


On Fri, 8 Nov 2002, Randy.Dunlap wrote:
?
> Sure, it looks cleaner that way, although gcc has already put <*dig>
> in a local register; i.e., it's not pulled from memory for each test.
> Here's a (tested) version that does that.

Why do you have that "dig" pointer at all? It's not really used.

Why not just do

	+	char digit;
	...

	+	digit = str;
	+	if (digit == '-')
	+		digit = str[1];


(and maybe it should also test for whether signed stuff is even alloed or 
not, ie maybe the test should be "if (is_sign && digit == '-')" instead)

		Linus


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
  2002-11-08 19:59     ` Randy.Dunlap
  2002-11-08 20:19       ` Linus Torvalds
@ 2002-11-08 20:23       ` Richard B. Johnson
  1 sibling, 0 replies; 12+ messages in thread
From: Richard B. Johnson @ 2002-11-08 20:23 UTC (permalink / raw)
  To: Randy.Dunlap; +Cc: Douglas Gilbert, linux-kernel, torvalds

On Fri, 8 Nov 2002, Randy.Dunlap wrote:

> On Fri, 8 Nov 2002, Richard B. Johnson wrote:
> 
> | On Fri, 8 Nov 2002, Randy.Dunlap wrote:
> |
> | > On Sat, 9 Nov 2002, Douglas Gilbert wrote:
> | >
> | > | In lk 2.5.46-bk3 the expression in the subject line
> | > | fails to write into "i" and returns 0. Drop the minus
> | > | sign and it works.
> | >
> | > Here's an unobstrusive patch to correct that.
> | > Please apply.
> | >
> | > --
> | > ~Randy
> | > -
> |
> | I was thinking that if anybody ever had to change any of this
> | stuff, it might be a good idea to do the indirection only once?
> | All those "splats" over and over again are costly.
> 
> Sure, it looks cleaner that way, although gcc has already put <*dig>
> in a local register; i.e., it's not pulled from memory for each test.
> Here's a (tested) version that does that.
> 
> -- 
> ~Randy
> 
> 
> 
> --- ./lib/vsprintf.c%signed	Mon Nov  4 14:30:49 2002
> +++ ./lib/vsprintf.c	Fri Nov  8 12:03:15 2002
> @@ -517,6 +517,7 @@
>  {
>  	const char *str = buf;
>  	char *next;
> +	char *dig, onedig;
>  	int num = 0;
>  	int qualifier;
>  	int base;
> @@ -638,12 +639,14 @@
>  		while (isspace(*str))
>  			str++;
> 
> -		if (!*str
> -                    || (base == 16 && !isxdigit(*str))
> -                    || (base == 10 && !isdigit(*str))
> -                    || (base == 8 && (!isdigit(*str) || *str > '7'))
> -                    || (base == 0 && !isdigit(*str)))
> -			break;
> +		dig = (*str == '-') ? (str + 1) : str;
> +		onedig = *dig;
> +		if (!onedig
> +                    || (base == 16 && !isxdigit(onedig))
> +                    || (base == 10 && !isdigit(onedig))
> +                    || (base == 8 && (!isdigit(onedig) || onedig > '7'))
> +                    || (base == 0 && !isdigit(onedig)))
> +				break;
> 
>  		switch(qualifier) {
>  		case 'h':
> 

I like it much better.

Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
   Bush : The Fourth Reich of America



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
  2002-11-08 20:19       ` Linus Torvalds
@ 2002-11-08 22:09         ` Randy.Dunlap
  2002-11-10 13:41           ` Henning P. Schmiedehausen
  0 siblings, 1 reply; 12+ messages in thread
From: Randy.Dunlap @ 2002-11-08 22:09 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Richard B. Johnson, Douglas Gilbert, linux-kernel

On Fri, 8 Nov 2002, Linus Torvalds wrote:

|
| On Fri, 8 Nov 2002, Randy.Dunlap wrote:
| ?
| > Sure, it looks cleaner that way, although gcc has already put <*dig>
| > in a local register; i.e., it's not pulled from memory for each test.
| > Here's a (tested) version that does that.
|
| Why do you have that "dig" pointer at all? It's not really used.
|
| Why not just do
|
| 	+	char digit;
| 	...
|
| 	+	digit = str;
| 	+	if (digit == '-')
| 	+		digit = str[1];
|
|
| (and maybe it should also test for whether signed stuff is even alloed or
| not, ie maybe the test should be "if (is_sign && digit == '-')" instead)

OK, I've cleaned it up as suggested...

-- 
~Randy



--- ./lib/vsprintf.c%signed	Mon Nov  4 14:30:49 2002
+++ ./lib/vsprintf.c	Fri Nov  8 13:54:33 2002
@@ -517,6 +517,7 @@
 {
 	const char *str = buf;
 	char *next;
+	char digit;
 	int num = 0;
 	int qualifier;
 	int base;
@@ -638,12 +639,16 @@
 		while (isspace(*str))
 			str++;

-		if (!*str
-                    || (base == 16 && !isxdigit(*str))
-                    || (base == 10 && !isdigit(*str))
-                    || (base == 8 && (!isdigit(*str) || *str > '7'))
-                    || (base == 0 && !isdigit(*str)))
-			break;
+		digit = *str;
+		if (is_sign && digit == '-')
+			digit = *(str + 1);
+
+		if (!digit
+                    || (base == 16 && !isxdigit(digit))
+                    || (base == 10 && !isdigit(digit))
+                    || (base == 8 && (!isdigit(digit) || digit > '7'))
+                    || (base == 0 && !isdigit(digit)))
+				break;

 		switch(qualifier) {
 		case 'h':


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
  2002-11-08 22:09         ` Randy.Dunlap
@ 2002-11-10 13:41           ` Henning P. Schmiedehausen
  2002-11-11  3:05             ` Randy.Dunlap
  0 siblings, 1 reply; 12+ messages in thread
From: Henning P. Schmiedehausen @ 2002-11-10 13:41 UTC (permalink / raw)
  To: linux-kernel

"Randy.Dunlap" <rddunlap@osdl.org> writes:

>+		digit = *str;
>+		if (is_sign && digit == '-')
>+			digit = *(str + 1);

If signed is not allowed and you get a "-", you're in an error case
again...

	Regards
		Henning

-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen       -- Geschaeftsfuehrer
INTERMETA - Gesellschaft fuer Mehrwertdienste mbH     hps@intermeta.de

Am Schwabachgrund 22  Fon.: 09131 / 50654-0   info@intermeta.de
D-91054 Buckenhof     Fax.: 09131 / 50654-20   

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
  2002-11-10 13:41           ` Henning P. Schmiedehausen
@ 2002-11-11  3:05             ` Randy.Dunlap
  2002-11-11  4:19               ` Randy.Dunlap
                                 ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Randy.Dunlap @ 2002-11-11  3:05 UTC (permalink / raw)
  To: Henning P. Schmiedehausen; +Cc: linux-kernel

On Sun, 10 Nov 2002, Henning P. Schmiedehausen wrote:

| "Randy.Dunlap" <rddunlap@osdl.org> writes:
|
| >+		digit = *str;
| >+		if (is_sign && digit == '-')
| >+			digit = *(str + 1);
|
| If signed is not allowed and you get a "-", you're in an error case
| again...

Yes, and a 0 value is returned.
IOW, asking for an unsigned number (in the format string)
and getting "-123" does return 0.

What should it do?
This function can't return -EINPUTERROR or -EILSEQ.
(since it's after feature-freeze :)
And the original problem was that a leading '-' sign on a
signed number (!) caused a return of 0.  At least that is fixed.

So now the problem (?) is that a '-' sign on an unsigned number
returns 0.  We can always add a big printk() there that
something is foul.  Other ideas?

-- 
~Randy


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
  2002-11-11  3:05             ` Randy.Dunlap
@ 2002-11-11  4:19               ` Randy.Dunlap
  2002-11-11  9:27               ` Henning Schmiedehausen
  2002-11-11 14:38               ` Andreas Schwab
  2 siblings, 0 replies; 12+ messages in thread
From: Randy.Dunlap @ 2002-11-11  4:19 UTC (permalink / raw)
  To: Henning P. Schmiedehausen; +Cc: linux-kernel

On Sun, 10 Nov 2002, Randy.Dunlap wrote:

| On Sun, 10 Nov 2002, Henning P. Schmiedehausen wrote:
|
| | "Randy.Dunlap" <rddunlap@osdl.org> writes:
| |
| | >+		digit = *str;
| | >+		if (is_sign && digit == '-')
| | >+			digit = *(str + 1);
| |
| | If signed is not allowed and you get a "-", you're in an error case
| | again...
|
| Yes, and a 0 value is returned.
| IOW, asking for an unsigned number (in the format string)
| and getting "-123" does return 0.
|
| What should it do?
| This function can't return -EINPUTERROR or -EILSEQ.
| (since it's after feature-freeze :)
| And the original problem was that a leading '-' sign on a
| signed number (!) caused a return of 0.  At least that is fixed.
|
| So now the problem (?) is that a '-' sign on an unsigned number
| returns 0.  We can always add a big printk() there that
| something is foul.  Other ideas?

It's noteworthy that vsscanf() completely gives up on scanning
the rest of the input data at this point.  E.g.:
	count = sscanf (input, "%x %i %i", &level, &next, &other);
with <input> = "-42 -86 -99" gives up on "-42" and returns 0
(as number of items scanned/converted).

-- 
~Randy


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
  2002-11-11  3:05             ` Randy.Dunlap
  2002-11-11  4:19               ` Randy.Dunlap
@ 2002-11-11  9:27               ` Henning Schmiedehausen
  2002-11-11 14:38               ` Andreas Schwab
  2 siblings, 0 replies; 12+ messages in thread
From: Henning Schmiedehausen @ 2002-11-11  9:27 UTC (permalink / raw)
  To: Randy.Dunlap; +Cc: linux-kernel

Hi,

On Mon, 2002-11-11 at 04:05, Randy.Dunlap wrote:
> On Sun, 10 Nov 2002, Henning P. Schmiedehausen wrote:
> 
> | "Randy.Dunlap" <rddunlap@osdl.org> writes:
> |
> | >+		digit = *str;
> | >+		if (is_sign && digit == '-')
> | >+			digit = *(str + 1);
> |
> | If signed is not allowed and you get a "-", you're in an error case
> | again...
> 
> Yes, and a 0 value is returned.
> IOW, asking for an unsigned number (in the format string)
> and getting "-123" does return 0.
> 
> What should it do?

I would model this after user space. (Which does strange things:

--- cut ---
#include <stdio.h>

main()
{
  char *scan = "-100";
  unsigned int foo;
  int bar;

  int res = sscanf(scan, "%ud", &foo);

  printf("%s = %ud = %d\n", scan, foo, res);

  res = sscanf(scan, "%ud", &bar);

  printf("%s = %d = %d\n", scan, bar, res);

}
--- cut ---

% gcc -o xxx xxx.c
./xxx 
-100 = 4294967196d = 1
-100 = -100 = 1

Hm, so I guess, yes, a warning message would be nice IMHO. Returning an
error code would IMHO moot, because noone is checking these codes
anyway.

	Regards
		Henning



> This function can't return -EINPUTERROR or -EILSEQ.
> (since it's after feature-freeze :)
> And the original problem was that a leading '-' sign on a
> signed number (!) caused a return of 0.  At least that is fixed.
> 
> So now the problem (?) is that a '-' sign on an unsigned number
> returns 0.  We can always add a big printk() there that
> something is foul.  Other ideas?


-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen       -- Geschaeftsfuehrer
INTERMETA - Gesellschaft fuer Mehrwertdienste mbH     hps@intermeta.de

Am Schwabachgrund 22  Fon.: 09131 / 50654-0   info@intermeta.de
D-91054 Buckenhof     Fax.: 09131 / 50654-20   


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Re: sscanf("-1", "%d", &i) fails, returns 0
  2002-11-11  3:05             ` Randy.Dunlap
  2002-11-11  4:19               ` Randy.Dunlap
  2002-11-11  9:27               ` Henning Schmiedehausen
@ 2002-11-11 14:38               ` Andreas Schwab
  2 siblings, 0 replies; 12+ messages in thread
From: Andreas Schwab @ 2002-11-11 14:38 UTC (permalink / raw)
  To: Randy.Dunlap; +Cc: Henning P. Schmiedehausen, linux-kernel

"Randy.Dunlap" <rddunlap@osdl.org> writes:

|> On Sun, 10 Nov 2002, Henning P. Schmiedehausen wrote:
|> 
|> | "Randy.Dunlap" <rddunlap@osdl.org> writes:
|> |
|> | >+		digit = *str;
|> | >+		if (is_sign && digit == '-')
|> | >+			digit = *(str + 1);
|> |
|> | If signed is not allowed and you get a "-", you're in an error case
|> | again...
|> 
|> Yes, and a 0 value is returned.
|> IOW, asking for an unsigned number (in the format string)
|> and getting "-123" does return 0.

Not in C.  According to the standard scanf is supposed to convert the
value to unsinged and return that.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2002-11-11 14:31 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-11-08 13:32 sscanf("-1", "%d", &i) fails, returns 0 Douglas Gilbert
2002-11-08 19:22 ` [PATCH] " Randy.Dunlap
2002-11-08 19:41   ` Richard B. Johnson
2002-11-08 19:59     ` Randy.Dunlap
2002-11-08 20:19       ` Linus Torvalds
2002-11-08 22:09         ` Randy.Dunlap
2002-11-10 13:41           ` Henning P. Schmiedehausen
2002-11-11  3:05             ` Randy.Dunlap
2002-11-11  4:19               ` Randy.Dunlap
2002-11-11  9:27               ` Henning Schmiedehausen
2002-11-11 14:38               ` Andreas Schwab
2002-11-08 20:23       ` Richard B. Johnson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox