From a325cb9f0de6b005b31ce2ded230efdd953ec893 Mon Sep 17 00:00:00 2001 From: Gregory Nutt <gnutt@nuttx.org> Date: Mon, 18 Aug 2014 07:33:17 -0600 Subject: [PATCH] sscanf(): NuttX libc tried to guess how many characters to parse, extracted them into a buffer, then ran strtol() on that buffer. That guess is often wrong. A better approach would be to call strtol() directly on the input data, using the endptr return value to determine how many characters to skip after parsing. From Kosma Moczek --- libc/stdio/lib_sscanf.c | 47 +++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/libc/stdio/lib_sscanf.c b/libc/stdio/lib_sscanf.c index a4802b2c5d..611a0edc0c 100644 --- a/libc/stdio/lib_sscanf.c +++ b/libc/stdio/lib_sscanf.c @@ -405,6 +405,10 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) if (*buf) { + FAR char *endptr; + int errsave; + long tmplong; + /* Skip over any white space before the integer string */ while (isspace(*buf)) @@ -459,35 +463,32 @@ int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) lvdbg("vsscanf: tmp[]=\"%s\"\n", tmp); /* Perform the integer conversion */ + /* Preserve the errno value */ - buf += width; - if (!noassign) + errsave = get_errno(); + set_errno(0); + if (sign) { - FAR char *endptr; - int errsave; - long tmplong; - - /* Preserve the errno value */ + tmplong = strtol(tmp, &endptr, base); + } + else + { + tmplong = strtoul(tmp, &endptr, base); + } - errsave = get_errno(); - set_errno(0); - if (sign) - { - tmplong = strtol(tmp, &endptr, base); - } - else - { - tmplong = strtoul(tmp, &endptr, base); - } + /* Check if the number was successfully converted */ - /* Check if the number was successfully converted */ + if (tmp == endptr || get_errno() == ERANGE) + { + return count; + } - if (tmp == endptr || get_errno() == ERANGE) - { - return count; - } + /* Move by the actual number of characters converted */ - set_errno(errsave); + buf += (endptr - tmp); + set_errno(errsave); + if (!noassign) + { /* We have to check whether we need to return a long * or an int. -- GitLab