From: Karel Zak Date: Mon, 8 Apr 2019 11:33:04 +0000 (+0200) Subject: libmount: don't use sscanf() for swaps parsing X-Git-Tag: v2.34-rc1~38 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Futil-linux.git;a=commitdiff_plain;h=6c9ab254aefb6ce7e0e032690791ad451f6b9408 libmount: don't use sscanf() for swaps parsing Addresses: https://github.com/karelzak/util-linux/issues/780 Signed-off-by: Karel Zak --- diff --git a/include/pathnames.h b/include/pathnames.h index 2e877cf324..bd29b640a5 100644 --- a/include/pathnames.h +++ b/include/pathnames.h @@ -16,7 +16,6 @@ /* used by kernel in /proc (e.g. /proc/swaps) for deleted files */ #define PATH_DELETED_SUFFIX " (deleted)" -#define PATH_DELETED_SUFFIX_SZ (sizeof(PATH_DELETED_SUFFIX) - 1) /* DEFPATHs from don't include /usr/local */ #undef _PATH_DEFPATH diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c index a4bef20790..16e7956af8 100644 --- a/libmount/src/tab_parse.c +++ b/libmount/src/tab_parse.c @@ -43,25 +43,35 @@ static void parser_cleanup(struct libmnt_parser *pa) memset(pa, 0, sizeof(*pa)); } -static const char *next_number(const char *s, int *num, int *rc) +static const char *next_s32(const char *s, int *num, int *rc) { char *end = NULL; if (!s || !*s) return s; - assert(num); - 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') *rc = 0; + return end; +} + +static const char *next_u64(const char *s, uint64_t *num, int *rc) +{ + char *end = NULL; + if (!s || !*s) + return s; + + *rc = -EINVAL; + *num = (uint64_t) strtoumax(s, &end, 10); + if (end == NULL || s == end) + return s; + if (*end == ' ' || *end == '\t' || *end == '\0') + *rc = 0; return end; } @@ -130,7 +140,7 @@ static int mnt_parse_table_line(struct libmnt_fs *fs, const char *s) goto done; /* (5) freq (optional) */ - s = next_number(s, &fs->freq, &rc); + s = next_s32(s, &fs->freq, &rc); if (s && *s && rc) { DBG(TAB, ul_debug("tab parse error: [freq]")); goto fail; @@ -141,7 +151,7 @@ static int mnt_parse_table_line(struct libmnt_fs *fs, const char *s) goto done; /* (6) freq (optional) */ - s = next_number(s, &fs->passno, &rc); + s = next_s32(s, &fs->passno, &rc); if (s && *s && rc) { DBG(TAB, ul_debug("tab parse error: [passno]")); goto fail; @@ -169,7 +179,7 @@ static int mnt_parse_mountinfo_line(struct libmnt_fs *fs, const char *s) fs->flags |= MNT_FS_KERNEL; /* (1) id */ - s = next_number(s, &fs->id, &rc); + s = next_s32(s, &fs->id, &rc); if (!s || !*s || rc) { DBG(TAB, ul_debug("tab parse error: [id]")); goto fail; @@ -178,7 +188,7 @@ static int mnt_parse_mountinfo_line(struct libmnt_fs *fs, const char *s) s = skip_separator(s); /* (2) parent */ - s = next_number(s, &fs->parent, &rc); + s = next_s32(s, &fs->parent, &rc); if (!s || !*s || rc) { DBG(TAB, ul_debug("tab parse error: [parent]")); goto fail; @@ -355,48 +365,66 @@ enomem: */ static int mnt_parse_swaps_line(struct libmnt_fs *fs, const char *s) { - uintmax_t fsz, usz; + uint64_t num; int rc; - char *src = NULL; - - rc = sscanf(s, UL_SCNsA" " /* (1) source */ - UL_SCNsA" " /* (2) type */ - "%ju" /* (3) size */ - "%ju" /* (4) used */ - "%d", /* priority */ - - &src, - &fs->swaptype, - &fsz, - &usz, - &fs->priority); - - if (rc == 5) { - size_t sz; - - fs->size = fsz; - fs->usedsize = usz; - - /* remove "\040(deleted)" suffix */ - sz = strlen(src); - if (sz > PATH_DELETED_SUFFIX_SZ) { - char *p = src + (sz - PATH_DELETED_SUFFIX_SZ); - if (strcmp(p, PATH_DELETED_SUFFIX) == 0) - *p = '\0'; - } + char *p; - unmangle_string(src); + /* (1) source */ + p = unmangle(s, &s); + if (p) { + char *x = (char *) endswith(p, PATH_DELETED_SUFFIX); + if (x && *x) + *x = '\0'; + } + if (!p || (rc = __mnt_fs_set_source_ptr(fs, p))) { + DBG(TAB, ul_debug("tab parse error: [source]")); + goto fail; + } - rc = mnt_fs_set_source(fs, src); - if (!rc) - mnt_fs_set_fstype(fs, "swap"); - } else { - DBG(TAB, ul_debug("tab parse error: [sscanf rc=%d]: '%s'", rc, s)); - rc = -EINVAL; + s = skip_separator(s); + + /* (2) type */ + fs->swaptype = unmangle(s, &s); + if (!fs->swaptype) { + DBG(TAB, ul_debug("tab parse error: [swaptype]")); + goto fail; + } + + s = skip_separator(s); + + /* (3) size */ + s = next_u64(s, &num, &rc); + if (!s || !*s || rc) { + DBG(TAB, ul_debug("tab parse error: [size]")); + goto fail; + } + fs->size = num; + + s = skip_separator(s); + + /* (4) size */ + s = next_u64(s, &num, &rc); + if (!s || !*s || rc) { + DBG(TAB, ul_debug("tab parse error: [used size]")); + goto fail; } + fs->usedsize = num; - free(src); + s = skip_separator(s); + /* (5) priority */ + s = next_s32(s, &fs->priority, &rc); + if (rc) { + DBG(TAB, ul_debug("tab parse error: [priority]")); + goto fail; + } + + mnt_fs_set_fstype(fs, "swap"); + return 0; +fail: + if (rc == 0) + rc = -EINVAL; + DBG(TAB, ul_debug("tab parse error on: '%s' [rc=%d]", s, rc)); return rc; }