summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2008-09-24 22:02:45 -0600
committerEric Blake <ebb9@byu.net>2008-09-25 15:56:41 -0600
commit4a5040d239a6afca25f52b4fc8e37c0aa020eb6a (patch)
treec5c81764bb326809e068a8de108475d0d3963968
parentd46d4cdd7e8c0edef237818f7f254130d346cc97 (diff)
downloadm4-4a5040d239a6afca25f52b4fc8e37c0aa020eb6a.tar.gz
Unify error handling for reading directories.
* m4/path.c (m4_path_search): Factor open attempts... (m4_fopen): ...into new function, to reject directories. * tests/others.at (directory): Enhance test. * doc/m4.texinfo (Include): Document that directories cannot be input files. Signed-off-by: Eric Blake <ebb9@byu.net> (cherry picked from commit eed62f0d2729c243d7c081c48d789f9d86fa340f)
-rw-r--r--ChangeLog7
-rw-r--r--doc/m4.texinfo3
-rw-r--r--m4/path.c34
-rw-r--r--tests/others.at12
4 files changed, 46 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 8b0f04a8..fd85259a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2008-09-25 Eric Blake <ebb9@byu.net>
+ Unify error handling for reading directories.
+ * m4/path.c (m4_path_search): Factor open attempts...
+ (m4_fopen): ...into new function, to reject directories.
+ * tests/others.at (directory): Enhance test.
+ * doc/m4.texinfo (Include): Document that directories cannot be
+ input files.
+
Avoid bugs on platforms that mishandle trailing /.
* ltdl/m4/gnulib-cache.m4: Import fopen module.
* tests/others.at (directory): New test.
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index ad0b2d47..9f523e5e 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -5729,7 +5729,8 @@ the previous input file.
The expansion of @code{include} and @code{sinclude} is therefore the
contents of @var{file}.
-If @var{file} does not exist (or cannot be read), the expansion is void,
+If @var{file} does not exist, is a directory, or cannot otherwise be
+read, the expansion is void,
and @code{include} will fail with an error while @code{sinclude} is
silent. The empty string counts as a file that does not exist.
diff --git a/m4/path.c b/m4/path.c
index 91991e00..bf151935 100644
--- a/m4/path.c
+++ b/m4/path.c
@@ -123,6 +123,29 @@ m4_add_include_directory (m4 *context, const char *dir, bool prepend)
#endif
}
+/* Attempt to open FILE; if it opens, verify that it is not a
+ directory, and ensure it does not leak across execs. */
+static FILE *
+m4_fopen (m4 *context, const char *file, const char *mode)
+{
+ FILE *fp = fopen (file, "r");
+ if (fp)
+ {
+ struct stat st;
+ int fd = fileno (fp);
+ if (fstat (fd, &st) == 0 && S_ISDIR (st.st_mode))
+ {
+ fclose (fp);
+ errno = EISDIR;
+ return NULL;
+ }
+ if (set_cloexec_flag (fileno (fp), true) != 0)
+ m4_error (context, 0, errno, NULL,
+ _("cannot protect input file across forks"));
+ }
+ return fp;
+}
+
/* Search for FILE according to -B options, `.', -I options, then
M4PATH environment. If successful, return the open file, and if
RESULT is not NULL, set *RESULT to a malloc'd string that
@@ -152,12 +175,9 @@ m4_path_search (m4 *context, const char *file, char **expanded_name)
lookup will do the trick. */
if (IS_ABSOLUTE_FILE_NAME (file) || m4_get_posixly_correct_opt (context))
{
- fp = fopen (file, "r");
+ fp = m4_fopen (context, file, "r");
if (fp != NULL)
{
- if (set_cloexec_flag (fileno (fp), true) != 0)
- m4_error (context, 0, errno, NULL,
- _("cannot protect input file across forks"));
if (expanded_name != NULL)
*expanded_name = xstrdup (file);
return fp;
@@ -174,16 +194,12 @@ m4_path_search (m4 *context, const char *file, char **expanded_name)
xfprintf (stderr, "path_search (%s) -- trying %s\n", file, name);
#endif
- fp = fopen (name, "r");
+ fp = m4_fopen (context, name, "r");
if (fp != NULL)
{
m4_debug_message (context, M4_DEBUG_TRACE_PATH,
_("path search for `%s' found `%s'"),
file, name);
- if (set_cloexec_flag (fileno (fp), true) != 0)
- m4_error (context, 0, errno, NULL,
- _("cannot protect input file across forks"));
-
if (expanded_name != NULL)
*expanded_name = name;
else
diff --git a/tests/others.at b/tests/others.at
index 666409ee..71a1ee05 100644
--- a/tests/others.at
+++ b/tests/others.at
@@ -135,6 +135,10 @@ AT_DATA([in1.m4],
]])
AT_DATA([in2.m4],
[[sinclude(`in2.m4/')
+sinclude(`.')
+]])
+AT_DATA([in3.m4],
+[[include(`.')
]])
AT_CHECK_M4([in1.m4/], [1], [], [stderr])
@@ -151,6 +155,14 @@ AT_CHECK([sed 's/Invalid argument/Not a directory/' stderr], [0],
]])
AT_CHECK_M4([in2.m4], [0], [[
+
+]])
+
+AT_CHECK_M4([in3.m4], [1], [[
+]], [stderr])
+dnl mingw fails with EACCES rather than the expected EISDIR
+AT_CHECK([sed 's/Permission denied/Is a directory/' stderr], [0],
+[[m4:in3.m4:1: include: cannot open `.': Is a directory
]])
AT_CLEANUP