Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri, 27 Aug 2021 12:27:36 -0300
From: Érico Nogueira <ericonr@...root.org>
To: <musl@...ts.openwall.com>
Cc: "Alyssa Ross" <hi@...ssa.is>
Subject: Re: [PATCH musl 3/3] mntent: fix parsing lines with optional
 fields

On Sat Aug 21, 2021 at 5:54 AM -03, Alyssa Ross wrote:
> According to fstab(5), the last two fields are optional, but this
> wasn't accepted by Musl. After this change, only the first field is
> required, which matches Glibc's behaviour.
>
> Using sscanf as before, it would have been impossible to differentiate
> between 0 fields and 4 fields, because sscanf would have returned 0 in
> both cases due to the use of assignment suppression and %n for the
> string fields (which is important to avoid copying any strings). So
> instead, before calling sscanf, initialize every string to the empty
> string, and then we can check which strings are empty afterwards to
> know how many fields were matched.

Besides typing change noted below, the change sounds reasonable.

If you want to fix another issue around mntent, hasmntopts has some
troubles too :p

> ---
>
> We could also be stricter about it, and enforce that the first four
> fields are present, since the man page says only the last two are
> optional. Doing that would be a simple change of checking for the
> presence of mnt_opts instead of mnt_fsname at the end of my patch.
>
> src/misc/mntent.c | 18 +++++++++++++-----
> 1 file changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/src/misc/mntent.c b/src/misc/mntent.c
> index eabb8200..5a68f0b9 100644
> --- a/src/misc/mntent.c
> +++ b/src/misc/mntent.c
> @@ -21,7 +21,8 @@ int endmntent(FILE *f)
>  
> struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf,
> int buflen)
> {
> - int cnt, n[8], use_internal = (linebuf == SENTINEL);
> + int use_internal = (linebuf == SENTINEL);
> + size_t len, i, n[8];

Try avoiding unrelated changes in the commit, since they can introduce
subtle bugs. In this case, making n size_t[] instead of int[] will lead
to pointer type mismatches in the sscanf call, given that %n expects an
int*.

I don't know if *scanf guarantees it won't read enough to go past
INT_MAX, though, so making a change to size_t[] and using %ln might make
sense. Deferring to someone else to answer that.

>  
> mnt->mnt_freq = 0;
> mnt->mnt_passno = 0;
> @@ -39,10 +40,14 @@ struct mntent *getmntent_r(FILE *f, struct mntent
> *mnt, char *linebuf, int bufle
> errno = ERANGE;
> return 0;
> }
> - cnt = sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
> - n, n+1, n+2, n+3, n+4, n+5, n+6, n+7,
> - &mnt->mnt_freq, &mnt->mnt_passno);
> - } while (cnt < 2 || linebuf[n[0]] == '#');
> +
> + len = strlen(linebuf);
> + for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len;
> + if (sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
> + n, n+1, n+2, n+3, n+4, n+5, n+6, n+7,
> + &mnt->mnt_freq, &mnt->mnt_passno) == EOF && ferror(f))
> + return 0;
> + } while (linebuf[n[0]] == '#');
>  
> linebuf[n[1]] = 0;
> linebuf[n[3]] = 0;
> @@ -54,6 +60,9 @@ struct mntent *getmntent_r(FILE *f, struct mntent
> *mnt, char *linebuf, int bufle
> mnt->mnt_type = linebuf+n[4];
> mnt->mnt_opts = linebuf+n[6];
>  
> + if (!*mnt->mnt_fsname)
> + return 0;
> +
> return mnt;
> }
>  
> --
> 2.32.0

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.