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