sscanf("-1", "%d", &i) fails, returns 0

sscanf("-1", "%d", &i) fails, returns 0

Post by Douglas Gilber » Sat, 09 Nov 2002 15:40:09



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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

sscanf("-1", "%d", &i) fails, returns 0

Post by Randy.Dunla » Sat, 09 Nov 2002 21:30:13


| 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

 {
        const char *str = buf;
        char *next;
+       char *dig;
        int num = 0;
        int qualifier;

                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':

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

sscanf("-1", "%d", &i) fails, returns 0

Post by Richard B. Johnso » Sat, 09 Nov 2002 21:50:09




> | 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

>  {
>    const char *str = buf;
>    char *next;
> +  char *dig;
>    int num = 0;
>    int qualifier;
>    int base;

>            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,
* Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
   Bush : The Fourth Reich of America

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://www.veryComputer.com/
Please read the FAQ at  http://www.veryComputer.com/

 
 
 

sscanf("-1", "%d", &i) fails, returns 0

Post by Randy.Dunla » Sat, 09 Nov 2002 22:10:08



|

| >
| > | 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

 {
        const char *str = buf;
        char *next;
+       char *dig, onedig;
        int num = 0;
        int qualifier;

                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':

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

sscanf("-1", "%d", &i) fails, returns 0

Post by Richard B. Johnso » Sat, 09 Nov 2002 22:30:05





> |

> | >
> | > | 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

>  {
>    const char *str = buf;
>    char *next;
> +  char *dig, onedig;
>    int num = 0;
>    int qualifier;
>    int base;

>            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,
* Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
   Bush : The Fourth Reich of America

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://www.veryComputer.com/
Please read the FAQ at  http://www.veryComputer.com/

 
 
 

sscanf("-1", "%d", &i) fails, returns 0

Post by Linus Torvald » Sat, 09 Nov 2002 22:30:09


?

Quote:> 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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

sscanf("-1", "%d", &i) fails, returns 0

Post by Randy.Dunla » Sun, 10 Nov 2002 00:20:07


|

| ?
| > 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

 {
        const char *str = buf;
        char *next;
+       char digit;
        int num = 0;
        int qualifier;

                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':

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

1. sscanf("-1", "%d", &i) fails, returns 0

|
| >+         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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

2. Pcmcia vs Cardbus Questions

3. GETSERVBYNAME()????????????????????"""""""""""""

4. GeForce2 MX (Creative) Linux Problem

5. PAM pam_chauthtok function fails with "-1" invalid return code

6. BOCA 16 port not working?

7. """"""""My SoundBlast 16 pnp isn't up yet""""""""""""

8. Diary program to run in Xwindows?

9. Do you check for errors with "< 0" or "== -1"?

10. Help: use SED to move or replace "New-line" & "return" char

11. Help: Remove or Replace "New-line" & "Return" characters

12. Type "(", ")" and "{", "}" in X...