gbranden pushed a commit to branch master
in repository groff.
commit 834afa4e0d80ff8b27b25e6aaee7ed17bcadf1fb
Author: G. Branden Robinson <[email protected]>
AuthorDate: Sat Jul 13 13:09:21 2024 -0500
[libgroff]: Fix Savannah #65980 (open directory).
* src/libs/libgroff/searchpath.cpp (is_directory): New function uses
stat(2) to check file name argument to see if it's a directory, and
returns a Boolean.
(search_path::open_file):
(search_path::open_file_cautious): Use `is_directory()` before
attempting to `fopen()` a file specification; fail and set `errno` to
`EISDIR` if it's a directory so that the caller reports a useful
diagnostic.
* bootstrap.conf: Add gnulib `stat` module, because the story of
POSIX and non-POSIX systems alike trying and failing to sensibly
implement the fundamental Unix file system model is a sorry tale of
indifference and self-owns by rock star programmers. (Seriously, read
the "sys/stat.h" and "stat" sections of the gnulib manual.)
Fixes <https://savannah.gnu.org/bugs/?65980>. Thanks to Dave Kemper for
the report.
---
ChangeLog | 21 +++++++++++++++++++++
bootstrap.conf | 1 +
src/libs/libgroff/searchpath.cpp | 34 +++++++++++++++++++++++++++++++++-
3 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/ChangeLog b/ChangeLog
index 59b7091e0..38817d964 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2024-07-13 G. Branden Robinson <[email protected]>
+
+ * src/libs/libgroff/searchpath.cpp (is_directory): New function
+ uses stat(2) to check file name argument to see if it's a
+ directory, and returns a Boolean.
+ (search_path::open_file):
+ (search_path::open_file_cautious): Use `is_directory()` before
+ attempting to `fopen()` a file specification; fail and set
+ `errno` to `EISDIR` if it's a directory so that the caller
+ reports a useful diagnostic.
+
+ * bootstrap.conf: Add gnulib `stat` module, because the story of
+ POSIX and non-POSIX systems alike trying and failing to sensibly
+ implement the fundamental Unix file system model is a sorry tale
+ of indifference and self-owns by rock star programmers.
+ {Seriously, read the "sys/stat.h" and "stat" sections of the
+ gnulib manual.}
+
+ Fixes <https://savannah.gnu.org/bugs/?65980>. Thanks to Dave
+ Kemper for the report.
+
2024-07-13 G. Branden Robinson <[email protected]>
* tmac/an-ext.tmac: Fix incomplete changes to support `YS` with
diff --git a/bootstrap.conf b/bootstrap.conf
index aa96ac6df..20bee83f1 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -43,6 +43,7 @@ gnulib_modules="
fprintf-posix
snprintf
vsnprintf
+ stat
stdbool-c99
stdint
sys_wait
diff --git a/src/libs/libgroff/searchpath.cpp b/src/libs/libgroff/searchpath.cpp
index 0fc465b28..f11ef2295 100644
--- a/src/libs/libgroff/searchpath.cpp
+++ b/src/libs/libgroff/searchpath.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989-2020 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2024 Free Software Foundation, Inc.
Written by James Clark ([email protected])
This file is part of groff.
@@ -26,6 +26,11 @@ along with this program. If not, see
<http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <stdlib.h>
+// for stat(2)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
#include "searchpath.h"
#include "nonposix.h"
@@ -35,6 +40,17 @@ along with this program. If not, see
<http://www.gnu.org/licenses/>. */
# define relocate(path) strsave(path)
#endif
+static bool is_directory(const char *name)
+{
+ struct stat statbuf;
+ // If stat() fails, a later fopen() will fail anyway (he said
+ // TOCTTOUishly).
+ if ((stat(name, &statbuf) == 0)
+ && ((statbuf.st_mode & S_IFMT) == S_IFDIR))
+ return true;
+ return false;
+}
+
search_path::search_path(const char *envvar, const char *standard,
int add_home, int add_current)
{
@@ -99,6 +115,10 @@ FILE *search_path::open_file(const char *name, char **pathp)
{
assert(name != 0 /* nullptr */);
if (IS_ABSOLUTE(name) || *dirs == '\0') {
+ if (is_directory(name)) {
+ errno = EISDIR;
+ return 0 /* nullptr */;
+ }
FILE *fp = fopen(name, "r");
if (fp != 0 /* nullptr */) {
if (pathp != 0 /* nullptr */)
@@ -128,6 +148,10 @@ FILE *search_path::open_file(const char *name, char
**pathp)
#if 0
fprintf(stderr, "trying '%s'\n", path);
#endif
+ if (is_directory(name)) {
+ errno = EISDIR;
+ return 0 /* nullptr */;
+ }
FILE *fp = fopen(path, "r");
int err = errno;
if (fp != 0 /* nullptr */) {
@@ -160,6 +184,10 @@ FILE *search_path::open_file_cautious(const char *name,
char **pathp,
return (reading ? stdin : stdout);
}
if (!reading || IS_ABSOLUTE(name) || *dirs == '\0') {
+ if (is_directory(name)) {
+ errno = EISDIR;
+ return 0 /* nullptr */;
+ }
FILE *fp = fopen(name, mode);
if (fp != 0 /* nullptr */) {
if (pathp != 0 /* nullptr */)
@@ -190,6 +218,10 @@ FILE *search_path::open_file_cautious(const char *name,
char **pathp,
#if 0
fprintf(stderr, "trying '%s'\n", path);
#endif
+ if (is_directory(name)) {
+ errno = EISDIR;
+ return 0 /* nullptr */;
+ }
FILE *fp = fopen(path, mode);
int err = errno;
if (fp != 0 /* nullptr */) {
_______________________________________________
Groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit