192 lines
6.3 KiB
Diff
192 lines
6.3 KiB
Diff
|
commit b0e805fa0d6fea33745952df7b7f5442ca4c374f
|
||
|
Author: Mike Frysinger <vapier@gentoo.org>
|
||
|
Date: Fri Aug 28 17:08:49 2015 -0400
|
||
|
|
||
|
getmntent: fix memory corruption w/blank lines [BZ #18887]
|
||
|
|
||
|
The fix for BZ #17273 introduced a single byte of memory corruption when
|
||
|
the line is entirely blank. It would walk back past the start of the
|
||
|
buffer if the heap happened to be 0x20 or 0x09 and then write a NUL byte.
|
||
|
buffer = '\n';
|
||
|
end_ptr = buffer;
|
||
|
while (end_ptr[-1] == ' ' || end_ptr[-1] == '\t')
|
||
|
end_ptr--;
|
||
|
*end_ptr = '\0';
|
||
|
|
||
|
Fix that and rework the tests. Adding the testcase for BZ #17273 to the
|
||
|
existing \040 parser does not really make sense as it's unrelated, and
|
||
|
leads to confusing behavior: it implicitly relies on the new entry being
|
||
|
longer than the previous entry (since it just rewinds the FILE*). Split
|
||
|
it out into its own dedicated testcase instead.
|
||
|
|
||
|
diff --git a/misc/Makefile b/misc/Makefile
|
||
|
index aecb0da..2f5edf6 100644
|
||
|
--- a/misc/Makefile
|
||
|
+++ b/misc/Makefile
|
||
|
@@ -76,7 +76,8 @@ install-lib := libg.a
|
||
|
gpl2lgpl := error.c error.h
|
||
|
|
||
|
tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
|
||
|
- tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1
|
||
|
+ tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 \
|
||
|
+ tst-mntent-blank-corrupt tst-mntent-blank-passno
|
||
|
ifeq ($(run-built-tests),yes)
|
||
|
tests-special += $(objpfx)tst-error1-mem.out
|
||
|
endif
|
||
|
diff --git a/misc/mntent_r.c b/misc/mntent_r.c
|
||
|
index 6159873..4f26998 100644
|
||
|
--- a/misc/mntent_r.c
|
||
|
+++ b/misc/mntent_r.c
|
||
|
@@ -136,7 +136,9 @@ __getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
|
||
|
end_ptr = strchr (buffer, '\n');
|
||
|
if (end_ptr != NULL) /* chop newline */
|
||
|
{
|
||
|
- while (end_ptr[-1] == ' ' || end_ptr[-1] == '\t')
|
||
|
+ /* Do not walk past the start of buffer if it's all whitespace. */
|
||
|
+ while (end_ptr != buffer
|
||
|
+ && (end_ptr[-1] == ' ' || end_ptr[-1] == '\t'))
|
||
|
end_ptr--;
|
||
|
*end_ptr = '\0';
|
||
|
}
|
||
|
diff --git a/misc/tst-mntent-blank-corrupt.c b/misc/tst-mntent-blank-corrupt.c
|
||
|
new file mode 100644
|
||
|
index 0000000..92266a3
|
||
|
--- /dev/null
|
||
|
+++ b/misc/tst-mntent-blank-corrupt.c
|
||
|
@@ -0,0 +1,45 @@
|
||
|
+/* Make sure blank lines does not cause memory corruption BZ #18887.
|
||
|
+
|
||
|
+ Copyright (C) 2009-2015 Free Software Foundation, Inc.
|
||
|
+ This file is part of the GNU C Library.
|
||
|
+
|
||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||
|
+ modify it under the terms of the GNU Lesser General Public
|
||
|
+ License as published by the Free Software Foundation; either
|
||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||
|
+
|
||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
+ Lesser General Public License for more details.
|
||
|
+
|
||
|
+ You should have received a copy of the GNU Lesser General Public
|
||
|
+ License along with the GNU C Library; if not, see
|
||
|
+ <http://www.gnu.org/licenses/>. */
|
||
|
+
|
||
|
+#include <mntent.h>
|
||
|
+#include <stdio.h>
|
||
|
+#include <string.h>
|
||
|
+
|
||
|
+/* Make sure blank lines don't trigger memory corruption. This doesn't happen
|
||
|
+ for all targets though, so it's a best effort test BZ #18887. */
|
||
|
+static int
|
||
|
+do_test (void)
|
||
|
+{
|
||
|
+ FILE *fp;
|
||
|
+
|
||
|
+ fp = tmpfile ();
|
||
|
+ fputs ("\n \n/foo\\040dir /bar\\040dir auto bind \t \n", fp);
|
||
|
+ rewind (fp);
|
||
|
+
|
||
|
+ /* The corruption happens here ... */
|
||
|
+ getmntent (fp);
|
||
|
+ /* ... but trigers here. */
|
||
|
+ endmntent (fp);
|
||
|
+
|
||
|
+ /* If the test failed, we would crash, and not hit this point. */
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+#define TEST_FUNCTION do_test ()
|
||
|
+#include "../test-skeleton.c"
|
||
|
diff --git a/misc/tst-mntent-blank-passno.c b/misc/tst-mntent-blank-passno.c
|
||
|
new file mode 100644
|
||
|
index 0000000..fc04291
|
||
|
--- /dev/null
|
||
|
+++ b/misc/tst-mntent-blank-passno.c
|
||
|
@@ -0,0 +1,53 @@
|
||
|
+/* Make sure trailing whitespace is handled properly BZ #17273.
|
||
|
+
|
||
|
+ Copyright (C) 2009-2015 Free Software Foundation, Inc.
|
||
|
+ This file is part of the GNU C Library.
|
||
|
+
|
||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
||
|
+ modify it under the terms of the GNU Lesser General Public
|
||
|
+ License as published by the Free Software Foundation; either
|
||
|
+ version 2.1 of the License, or (at your option) any later version.
|
||
|
+
|
||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
+ Lesser General Public License for more details.
|
||
|
+
|
||
|
+ You should have received a copy of the GNU Lesser General Public
|
||
|
+ License along with the GNU C Library; if not, see
|
||
|
+ <http://www.gnu.org/licenses/>. */
|
||
|
+
|
||
|
+#include <mntent.h>
|
||
|
+#include <stdio.h>
|
||
|
+#include <string.h>
|
||
|
+
|
||
|
+/* Check entries to make sure trailing whitespace is ignored and we return the
|
||
|
+ correct passno value BZ #17273. */
|
||
|
+static int
|
||
|
+do_test (void)
|
||
|
+{
|
||
|
+ int result = 0;
|
||
|
+ FILE *fp;
|
||
|
+ struct mntent *mnt;
|
||
|
+
|
||
|
+ fp = tmpfile ();
|
||
|
+ fputs ("/foo\\040dir /bar\\040dir auto bind \t \n", fp);
|
||
|
+ rewind (fp);
|
||
|
+
|
||
|
+ mnt = getmntent (fp);
|
||
|
+ if (strcmp (mnt->mnt_fsname, "/foo dir") != 0
|
||
|
+ || strcmp (mnt->mnt_dir, "/bar dir") != 0
|
||
|
+ || strcmp (mnt->mnt_type, "auto") != 0
|
||
|
+ || strcmp (mnt->mnt_opts, "bind") != 0
|
||
|
+ || mnt->mnt_freq != 0
|
||
|
+ || mnt->mnt_passno != 0)
|
||
|
+ {
|
||
|
+ puts ("Error while reading entry with trailing whitespaces");
|
||
|
+ result = 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ return result;
|
||
|
+}
|
||
|
+
|
||
|
+#define TEST_FUNCTION do_test ()
|
||
|
+#include "../test-skeleton.c"
|
||
|
diff --git a/misc/tst-mntent.c b/misc/tst-mntent.c
|
||
|
index 932fd3f..b6ad8af 100644
|
||
|
--- a/misc/tst-mntent.c
|
||
|
+++ b/misc/tst-mntent.c
|
||
|
@@ -73,26 +73,6 @@ do_test (void)
|
||
|
puts ("Error while reading written entry back in");
|
||
|
result = 1;
|
||
|
}
|
||
|
-
|
||
|
- /* Part III: Entry with whitespaces at the end of a line. */
|
||
|
- rewind (fp);
|
||
|
-
|
||
|
- fputs ("/foo\\040dir /bar\\040dir auto bind \t \n", fp);
|
||
|
-
|
||
|
- rewind (fp);
|
||
|
-
|
||
|
- mnt = getmntent (fp);
|
||
|
-
|
||
|
- if (strcmp (mnt->mnt_fsname, "/foo dir") != 0
|
||
|
- || strcmp (mnt->mnt_dir, "/bar dir") != 0
|
||
|
- || strcmp (mnt->mnt_type, "auto") != 0
|
||
|
- || strcmp (mnt->mnt_opts, "bind") != 0
|
||
|
- || mnt->mnt_freq != 0
|
||
|
- || mnt->mnt_passno != 0)
|
||
|
- {
|
||
|
- puts ("Error while reading entry with trailing whitespaces");
|
||
|
- result = 1;
|
||
|
- }
|
||
|
}
|
||
|
|
||
|
return result;
|