summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2019-04-08 13:33:04 +0200
committerKarel Zak2019-04-08 15:16:23 +0200
commit6c9ab254aefb6ce7e0e032690791ad451f6b9408 (patch)
treec707dbeb4fa27c9e66a902ff94e98464d8df4816
parentlibmount: don't use sscanf() for mountinfo parsing (diff)
downloadkernel-qcow2-util-linux-6c9ab254aefb6ce7e0e032690791ad451f6b9408.tar.gz
kernel-qcow2-util-linux-6c9ab254aefb6ce7e0e032690791ad451f6b9408.tar.xz
kernel-qcow2-util-linux-6c9ab254aefb6ce7e0e032690791ad451f6b9408.zip
libmount: don't use sscanf() for swaps parsing
Addresses: https://github.com/karelzak/util-linux/issues/780 Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--include/pathnames.h1
-rw-r--r--libmount/src/tab_parse.c120
2 files changed, 74 insertions, 47 deletions
diff --git a/include/pathnames.h b/include/pathnames.h
index 2e877cf32..bd29b640a 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 <paths.h> don't include /usr/local */
#undef _PATH_DEFPATH
diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c
index a4bef2079..16e7956af 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;
}