sscanf() problems

Jeff Johnston jjohnstn@redhat.com
Tue Dec 2 20:28:00 GMT 2014


I believe I know what is happening.

The SCNu8 macro expands to be hhu

The vfscanf.c code only supports hh if the flag _WANT_IO_C99_FORMATS is set
to true.  By default it is false in newlib/configure.host and for a few select
platforms, it is set to true.

If you did not configure your library with --enable-newlib-io-c99-formats, then
it is false as arm doesn't set it to true.

Now, the second part of the problem.  The code in vfscanf.c sees the first 'h' and sets
a flag to indicate a short value and then reads the next format character since h is a modifier
for a format.  It reads the second 'h' and processes it the same as it did for the first 
(sets the short value flag again to true).

So, the code thinks you are reading a short value and this sets the upper-byte to 0x00.  So,
each of a, b, c, d are stepped on in order (ok, since they are being read in that order) and 
the final read of d steps on the next byte after it on the stack, which in your case is the str pointer.

-- Jeff J.

----- Original Message -----
> From: "Steffen Wolfer" <wolfer@weiss-robotics.de>
> To: newlib@sourceware.org
> Sent: Tuesday, December 2, 2014 6:21:20 AM
> Subject: sscanf() problems
> 
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Dear all,
> 
> I'm having the following, interesting problem using Newlib's sscanf().
> Trying to read an IP address from a string with the following code
> snippet:
> 
> void read_ipaddr()
> {
>   char *str;
>   uint8_t a, b, c, d;
>   int res;
> 
>   // This function returns a pointer to the
>   // string that represents the IP address
>   get_str( &str );
> 
>   res = sscanf( str, "%" SCNu8 ".%" SCNu8 ".%" SCNu8 ".%" SCNu8,
>                 &a, &b, &c, &d );
> 
>   ...
> }
> 
> The thing is that *str, i.e. the address value that is stored in the
> *str pointer, seems to be corrupted by sscanf().
> Dumping the memory shows that the variables a, b, c and d are located
> first in memory (stack area growing downwards) - let's say at byte
> addresses 10, 11, 12 and 13. After that, the 4-byte pointer *str is
> placed at address 14 to 17.
> Before the call of sscanf(), *str has a value of 0xa14af968. After the
> call to sscanf(), the value is 0xa14af900, meaning that the least
> significant byte of the value, which is located at byte address 14
> (little endian), is overwritten by sscanf(). The bytes at addresses 10
> to 13 represent the correct numbers of the scanned IP address string.
> 
> I'm running a bare metal ARM Cortex-M4 based microcontroller, using
> the compiler toolchain 2014q2 from here:
> https://launchpad.net/gcc-arm-embedded
> This includes GCC 4.8.4 and a Newlib snapshot from 2013-10-16 (at
> least the changelog says so).
> 
> Now do you think this is a problem in Newlib or am I doing something
> wrong?
> 
> 
> Thanks,
> Steffen
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1
> 
> iQEcBAEBAgAGBQJUfaCvAAoJEK3fUcGRI2ncGcAIAKyybaNyem8xcwKl5u8N9nLr
> 7EHi3hjmoQ8Y5Z0N3QiAWWvoDnduqfLfm3AWE9pS6TUtfhP14OuUbYs2bjDjIuhM
> bBu5ooi9iT/9BLodMNDdHxRWm6hyRhDZSzlGuQD+ozJASI22T5a5IqfH40TV5rNG
> K77wPnGs2gLAdC8x0TorUIvS68q6kC8v8DGOXMh0jpzCtq0r57KwxooV9IvJaxcp
> jEMkDBviKiixHT83PSo0A+08oMvKFLJu5LHvTyGOJV6JRvqWdwqhxJxqF4BBj7TW
> sK990l3jM5tpwj1iuKJ2TKLfnEbgKW3KkjzVpSxWY7wsXjuzSo6OIgpHg+96muk=
> =pano
> -----END PGP SIGNATURE-----
> 



More information about the Newlib mailing list