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