diff options
author | Eric Blake <ebb9@byu.net> | 2008-09-24 22:02:45 -0600 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2008-09-25 15:56:41 -0600 |
commit | 4a5040d239a6afca25f52b4fc8e37c0aa020eb6a (patch) | |
tree | c5c81764bb326809e068a8de108475d0d3963968 | |
parent | d46d4cdd7e8c0edef237818f7f254130d346cc97 (diff) | |
download | m4-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-- | ChangeLog | 7 | ||||
-rw-r--r-- | doc/m4.texinfo | 3 | ||||
-rw-r--r-- | m4/path.c | 34 | ||||
-rw-r--r-- | tests/others.at | 12 |
4 files changed, 46 insertions, 10 deletions
@@ -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. @@ -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 |