Skip to content

Commit

Permalink
libmount: don't use sscanf() for swaps parsing
Browse files Browse the repository at this point in the history
Addresses: #780
Signed-off-by: Karel Zak <kzak@redhat.com>
  • Loading branch information
karelzak committed Apr 8, 2019
1 parent ab8738e commit e902609
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 47 deletions.
1 change: 0 additions & 1 deletion include/pathnames.h
Expand Up @@ -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
Expand Down
120 changes: 74 additions & 46 deletions libmount/src/tab_parse.c
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -355,48 +365,66 @@ static int mnt_parse_utab_line(struct libmnt_fs *fs, const char *s)
*/
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;
}

Expand Down

0 comments on commit e902609

Please sign in to comment.