libs/libc/stdio/lib_sscanf.c: Fix conversion for format specifiers that appear right after a floating point format specifier
When performing a floating point conversion the parsing code could consume more than required characters from the input buffer. This made impossible to convert input of form "1.1K" using format "%f%c". Fix the issue by advancing the input buffer with the actual characters converted as a float point number. Signed-off-by: Mihai Serban <mihai.serban@gmail.com>
This commit is contained in:
parent
300b26d1d8
commit
b01e6e5f2a
@ -778,6 +778,13 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
|
|||||||
|
|
||||||
if (*buf)
|
if (*buf)
|
||||||
{
|
{
|
||||||
|
FAR char *endptr;
|
||||||
|
int errsave;
|
||||||
|
#ifdef CONFIG_HAVE_DOUBLE
|
||||||
|
double dvalue;
|
||||||
|
#endif
|
||||||
|
float fvalue;
|
||||||
|
|
||||||
/* Skip over any white space before the real string */
|
/* Skip over any white space before the real string */
|
||||||
|
|
||||||
while (isspace(*buf))
|
while (isspace(*buf))
|
||||||
@ -791,30 +798,49 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
|
|||||||
{
|
{
|
||||||
/* No... Guess a field width using some heuristics */
|
/* No... Guess a field width using some heuristics */
|
||||||
|
|
||||||
width = findwidth(buf, fmt);
|
int tmpwidth = findwidth(buf, fmt);
|
||||||
|
width = MIN(sizeof(tmp) - 1, tmpwidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the real string into a temporary working buffer. */
|
/* Copy the real string into a temporary working buffer. */
|
||||||
|
|
||||||
strncpy(tmp, buf, width);
|
strncpy(tmp, buf, width);
|
||||||
tmp[width] = '\0';
|
tmp[width] = '\0';
|
||||||
buf += width;
|
|
||||||
|
|
||||||
linfo("vsscanf: tmp[]=\"%s\"\n", tmp);
|
linfo("vsscanf: tmp[]=\"%s\"\n", tmp);
|
||||||
|
|
||||||
/* Perform the floating point conversion */
|
/* Perform the floating point conversion */
|
||||||
|
/* Preserve the errno value */
|
||||||
|
|
||||||
|
errsave = get_errno();
|
||||||
|
set_errno(0);
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_DOUBLE
|
||||||
|
if (lflag)
|
||||||
|
{
|
||||||
|
/* Get the converted double value */
|
||||||
|
|
||||||
|
dvalue = strtod(tmp, &endptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
fvalue = strtof(tmp, &endptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the number was successfully converted */
|
||||||
|
|
||||||
|
if (tmp == endptr || get_errno() == ERANGE)
|
||||||
|
{
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move by the actual number of characters converted */
|
||||||
|
|
||||||
|
buf += (endptr - tmp);
|
||||||
|
set_errno(errsave);
|
||||||
if (!noassign)
|
if (!noassign)
|
||||||
{
|
{
|
||||||
/* strtod always returns a double */
|
|
||||||
|
|
||||||
FAR char *endptr;
|
|
||||||
int errsave;
|
|
||||||
|
|
||||||
/* Preserve the errno value */
|
|
||||||
|
|
||||||
errsave = get_errno();
|
|
||||||
set_errno(0);
|
|
||||||
|
|
||||||
/* We have to check whether we need to return a float
|
/* We have to check whether we need to return a float
|
||||||
* or a double.
|
* or a double.
|
||||||
@ -823,18 +849,6 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
|
|||||||
#ifdef CONFIG_HAVE_DOUBLE
|
#ifdef CONFIG_HAVE_DOUBLE
|
||||||
if (lflag)
|
if (lflag)
|
||||||
{
|
{
|
||||||
/* Get the converted double value */
|
|
||||||
|
|
||||||
double dvalue = strtod(tmp, &endptr);
|
|
||||||
|
|
||||||
/* Check if the number was successfully converted */
|
|
||||||
|
|
||||||
if (tmp == endptr || get_errno() == ERANGE)
|
|
||||||
{
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_errno(errsave);
|
|
||||||
|
|
||||||
/* Return the double value */
|
/* Return the double value */
|
||||||
|
|
||||||
@ -844,18 +858,6 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/* Get the converted float value */
|
|
||||||
|
|
||||||
float fvalue = strtof(tmp, &endptr);
|
|
||||||
|
|
||||||
/* Check if the number was successfully converted */
|
|
||||||
|
|
||||||
if (tmp == endptr || get_errno() == ERANGE)
|
|
||||||
{
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_errno(errsave);
|
|
||||||
|
|
||||||
/* Return the float value */
|
/* Return the float value */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user