]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: don't use sscanf() for fstab parsing
authorKarel Zak <kzak@redhat.com>
Mon, 8 Apr 2019 11:33:04 +0000 (13:33 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 8 Apr 2019 11:34:47 +0000 (13:34 +0200)
Addresses: https://github.com/karelzak/util-linux/issues/780
Signed-off-by: Karel Zak <kzak@redhat.com>
lib/mangle.c
libmount/src/tab_parse.c

index b61c57fcf0eb968c11d1f0a819382570fe15d93b..b514cd8d350ac5894196cd19585a85e2b7d449cb 100644 (file)
@@ -96,7 +96,7 @@ size_t unhexmangle_to_buffer(const char *s, char *buf, size_t len)
 
 static inline const char *skip_nonspaces(const char *s)
 {
-       while (*s && !(*s == ' ' || *s == '\t'))
+       while (s && *s && !(*s == ' ' || *s == '\t'))
                s++;
        return s;
 }
index 45ca45966d25fe732e2ce9281e3bfcd42f036dac..6eec8ba3536c41773074625d8985527ae0d93152 100644 (file)
@@ -43,110 +43,111 @@ static void parser_cleanup(struct libmnt_parser *pa)
        memset(pa, 0, sizeof(*pa));
 }
 
-static const char *next_number(const char *s, int *num, int *ok)
+static const char *next_number(const char *s, int *num, int *rc)
 {
        char *end = NULL;
 
        assert(num);
        assert(s);
-       assert(ok);
-
-       *ok = 0;
-       s = skip_blank(s);
-       if (!s || !*s)
-               return s;
+       assert(rc);
 
+       *rc = -EINVAL;
        *num = strtol(s, &end, 10);
        if (end == NULL || s == end)
               return s;
 
        /* valid end of number is a space or a terminator */
        if (*end == ' ' || *end == '\t' || *end == '\0')
-               *ok = 1;
+               *rc = 0;
 
        return end;
 }
 
+static inline const char *skip_separator(const char *p)
+{
+       while (p && (*p == ' ' || *p == '\t'))
+               ++p;
+       return p;
+}
+
 /*
  * Parses one line from {fs,m}tab
  */
 static int mnt_parse_table_line(struct libmnt_fs *fs, const char *s)
 {
-       int rc, n = 0, xrc;
-       char *src = NULL, *fstype = NULL, *optstr = NULL;
+       int rc = 0;
+       char *p;
 
-       rc = sscanf(s,  UL_SCNsA" "     /* (1) source */
-                       UL_SCNsA" "     /* (2) target */
-                       UL_SCNsA" "     /* (3) FS type */
-                       UL_SCNsA" "     /* (4) options */
-                       "%n",           /* byte count */
+       fs->passno = fs->freq = 0;
 
-                       &src,
-                       &fs->target,
-                       &fstype,
-                       &optstr,
-                       &n);
-       xrc = rc;
+       /* (1) source */
+       p = unmangle(s, &s);
+               if (!p || (rc = __mnt_fs_set_source_ptr(fs, p))) {
+               DBG(TAB, ul_debug("tab parse error: [source]"));
+               goto fail;
+       }
 
-       if (rc == 3 || rc == 4) {                       /* options are optional */
-               unmangle_string(src);
-               unmangle_string(fs->target);
-               unmangle_string(fstype);
+       s = skip_separator(s);
 
-               if (optstr && *optstr)
-                       unmangle_string(optstr);
+       /* (2) target */
+       fs->target = unmangle(s, &s);
+       if (!fs->target) {
+               DBG(TAB, ul_debug("tab parse error: [target]"));
+               goto fail;
+       }
 
-               /* note that __foo functions do not reallocate the string
-                */
-               rc = __mnt_fs_set_source_ptr(fs, src);
-               if (!rc) {
-                       src = NULL;
-                       rc = __mnt_fs_set_fstype_ptr(fs, fstype);
-                       if (!rc)
-                               fstype = NULL;
-               }
-               if (!rc && optstr)
-                       rc = mnt_fs_set_options(fs, optstr);
-               free(optstr);
-               optstr = NULL;
-       } else {
-               DBG(TAB, ul_debug("tab parse error: [sscanf rc=%d]: '%s'", rc, s));
-               rc = -EINVAL;
+       s = skip_separator(s);
+
+       /* (3) FS type */
+       p = unmangle(s, &s);
+       if (!p || (rc = __mnt_fs_set_fstype_ptr(fs, p))) {
+               DBG(TAB, ul_debug("tab parse error: [fstype]"));
+               goto fail;
        }
 
-       if (rc) {
-               free(src);
-               free(fstype);
-               free(optstr);
-               DBG(TAB, ul_debug("tab parse error: [set vars, rc=%d]\n", rc));
-               return rc;      /* error */
+       s = skip_separator(s);
+
+       /* (4) options (optional) */
+       p = unmangle(s, &s);
+       if (p && (rc = mnt_fs_set_options(fs, p))) {
+               DBG(TAB, ul_debug("tab parse error: [options]"));
+               goto fail;
        }
 
-       fs->passno = fs->freq = 0;
+       if (!p)
+               goto done;
+       s = skip_separator(s);
+       if (!s || !*s)
+               goto done;
 
-       if (xrc == 4 && n)
-               s = skip_blank(s + n);
-       if (xrc == 4 && *s) {
-               int ok = 0;
+       /* (5) freq (optional) */
+       s = next_number(s, &fs->freq, &rc);
+       if (s && *s && rc) {
+               DBG(TAB, ul_debug("tab parse error: [freq]"));
+               goto fail;
+       }
 
-               s = next_number(s, &fs->freq, &ok);
-               if (!ok) {
-                       if (s && *s) {
-                               DBG(TAB, ul_debug("tab parse error: [freq]"));
-                               rc = -EINVAL;
-                       }
-               } else {
-                       s = next_number(s, &fs->passno, &ok);
-                       if (!ok && s && *s) {
-                               DBG(TAB, ul_debug("tab parse error: [passno]"));
-                               rc = -EINVAL;
-                       }
-               }
+       s = skip_separator(s);
+       if (!s || !*s)
+               goto done;
+
+       /* (6) freq (optional) */
+       s = next_number(s, &fs->passno, &rc);
+       if (s && *s && rc) {
+               DBG(TAB, ul_debug("tab parse error: [passno]"));
+               goto fail;
        }
 
+done:
+       return 0;
+fail:
+       if (rc == 0)
+               rc = -EINVAL;
+       DBG(TAB, ul_debug("tab parse error on: '%s' [rc=%d]", s, rc));
        return rc;
 }
 
+
 /*
  * Parses one line from a mountinfo file
  */