mirror of
https://https.git.savannah.gnu.org/git/groff.git
synced 2026-01-26 15:39:07 +00:00
[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.
This commit is contained in:
parent
f680c55d38
commit
834afa4e0d
21
ChangeLog
21
ChangeLog
@ -1,3 +1,24 @@
|
||||
2024-07-13 G. Branden Robinson <g.branden.robinson@gmail.com>
|
||||
|
||||
* 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 <g.branden.robinson@gmail.com>
|
||||
|
||||
* tmac/an-ext.tmac: Fix incomplete changes to support `YS` with
|
||||
|
||||
@ -43,6 +43,7 @@ gnulib_modules="
|
||||
fprintf-posix
|
||||
snprintf
|
||||
vsnprintf
|
||||
stat
|
||||
stdbool-c99
|
||||
stdint
|
||||
sys_wait
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1989-2020 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2024 Free Software Foundation, Inc.
|
||||
Written by James Clark (jjc@jclark.com)
|
||||
|
||||
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 */) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user