preprocessor/556: cpplib uses freed file descriptors
Neil Booth
NeilB@earthling.net
Wed Sep 20 23:39:00 GMT 2000
This bootstraps and no new regressions. OK to commit?
Neil.
* cppfiles.c (lookup_include_file): Rename to open_file.
Always create a splay tree value, even on syscall failures.
Negative entries indicated by fd == -2.
Re-open files closed in the meantime.
(_cpp_fake_include): Create a negative splay tree entry.
(find_include_file, cpp_read_file): Update for function name
change.
* gcc.gd/cpp/mi4.c: Testcase.
Index: cppfiles.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cppfiles.c,v
retrieving revision 1.81
diff -c -p -r1.81 cppfiles.c
*** cppfiles.c 2000/09/19 17:28:46 1.81
--- cppfiles.c 2000/09/20 22:24:11
*************** static struct file_name_list *actual_dir
*** 73,80 ****
static struct include_file *find_include_file
PARAMS ((cpp_reader *, const char *,
struct file_name_list *));
! static struct include_file *lookup_include_file
! PARAMS ((cpp_reader *, const char *));
static int read_include_file PARAMS ((cpp_reader *, struct include_file *));
static int stack_include_file PARAMS ((cpp_reader *, struct include_file *));
static void purge_cache PARAMS ((struct include_file *));
--- 73,79 ----
static struct include_file *find_include_file
PARAMS ((cpp_reader *, const char *,
struct file_name_list *));
! static struct include_file *open_file PARAMS ((cpp_reader *, const char *));
static int read_include_file PARAMS ((cpp_reader *, struct include_file *));
static int stack_include_file PARAMS ((cpp_reader *, struct include_file *));
static void purge_cache PARAMS ((struct include_file *));
*************** destroy_include_file_node (v)
*** 98,104 ****
if (f)
{
purge_cache (f);
! free (f);
}
}
--- 97,103 ----
if (f)
{
purge_cache (f);
! free (f); /* The tree is registered with free to free f->name. */
}
}
*************** _cpp_cleanup_includes (pfile)
*** 120,142 ****
}
/* Given a file name, look it up in the cache; if there is no entry,
! create one. Returns 0 if the file doesn't exist or is
! inaccessible, otherwise the cache entry. */
static struct include_file *
! lookup_include_file (pfile, filename)
cpp_reader *pfile;
const char *filename;
! {
splay_tree_node nd;
! struct include_file *file = 0;
! int fd;
! struct stat st;
nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) filename);
if (nd)
! return (struct include_file *)nd->value;
/* We used to open files in nonblocking mode, but that caused more
problems than it solved. Do take care not to acquire a
--- 119,162 ----
}
/* Given a file name, look it up in the cache; if there is no entry,
! create one (regardless of success in opening the file). If the
! file doesn't exist or is inaccessible, this entry is flagged so we
! don't attempt to open it again in the future. If the file isn't
! open, open it.
+ Returns an include_file structure with an open file descriptor on
+ success, or NULL on failure. */
+
static struct include_file *
! open_file (pfile, filename)
cpp_reader *pfile;
const char *filename;
! {
splay_tree_node nd;
! struct include_file *file;
nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) filename);
if (nd)
! {
! file = (struct include_file *) nd->value;
!
! /* Don't retry opening if we failed previously. */
! if (file->fd == -2)
! return 0;
!
! /* -1 indicates a file we've opened previously, and since closed. */
! if (file->fd != -1)
! return file;
! }
! else
! {
! file = xcnew (struct include_file);
! file->name = xstrdup (filename);
! splay_tree_insert (pfile->all_include_files,
! (splay_tree_key) file->name,
! (splay_tree_value) file);
! }
/* We used to open files in nonblocking mode, but that caused more
problems than it solved. Do take care not to acquire a
*************** lookup_include_file (pfile, filename)
*** 153,189 ****
Special case: the empty string is translated to stdin. */
if (filename[0] == '\0')
! fd = 0;
else
! fd = open (filename, O_RDONLY|O_NOCTTY|O_BINARY, 0666);
! if (fd == -1)
! goto fail;
! if (fstat (fd, &st) < 0)
! goto fail;
!
! file = xcnew (struct include_file);
! file->name = xstrdup (filename);
! file->st = st;
! file->fd = fd;
!
! /* If the file is plain and zero length, mark it never-reread now. */
! if (S_ISREG (st.st_mode) && st.st_size == 0)
! file->cmacro = NEVER_REREAD;
!
! splay_tree_insert (pfile->all_include_files,
! (splay_tree_key) file->name, (splay_tree_value) file);
! return file;
! fail:
/* Don't issue an error message if the file doesn't exist. */
if (errno != ENOENT && errno != ENOTDIR)
cpp_error_from_errno (pfile, filename);
- /* Create a negative node for this path. */
- splay_tree_insert (pfile->all_include_files,
- (splay_tree_key) xstrdup (filename), 0);
return 0;
}
--- 173,198 ----
Special case: the empty string is translated to stdin. */
if (filename[0] == '\0')
! file->fd = 0;
else
! file->fd = open (filename, O_RDONLY | O_NOCTTY | O_BINARY, 0666);
! if (file->fd != -1 && fstat (file->fd, &file->st) == 0)
! {
! /* Mark a regular, zero-length file never-reread now. */
! if (S_ISREG (file->st.st_mode) && file->st.st_size == 0)
! file->cmacro = NEVER_REREAD;
! return file;
! }
/* Don't issue an error message if the file doesn't exist. */
if (errno != ENOENT && errno != ENOTDIR)
cpp_error_from_errno (pfile, filename);
+
+ /* Create a negative node for this path, and return null. */
+ file->fd = -2;
return 0;
}
*************** find_include_file (pfile, fname, search_
*** 419,425 ****
struct include_file *file;
if (fname[0] == '/')
! return lookup_include_file (pfile, fname);
/* Search directory path for the file. */
name = (char *) alloca (strlen (fname) + pfile->max_include_len
--- 428,434 ----
struct include_file *file;
if (fname[0] == '/')
! return open_file (pfile, fname);
/* Search directory path for the file. */
name = (char *) alloca (strlen (fname) + pfile->max_include_len
*************** find_include_file (pfile, fname, search_
*** 433,439 ****
if (CPP_OPTION (pfile, remap))
name = remap_filename (pfile, name, path);
! file = lookup_include_file (pfile, name);
if (file)
{
file->sysp = path->sysp;
--- 442,448 ----
if (CPP_OPTION (pfile, remap))
name = remap_filename (pfile, name, path);
! file = open_file (pfile, name);
if (file)
{
file->sysp = path->sysp;
*************** _cpp_fake_include (pfile, fname)
*** 478,486 ****
free (name);
return (const char *) nd->key;
}
! splay_tree_insert (pfile->all_include_files, (splay_tree_key) name, 0);
! return (const char *)name;
}
/* Not everyone who wants to set system-header-ness on a buffer can
--- 487,500 ----
free (name);
return (const char *) nd->key;
}
+
+ file = xcnew (struct include_file);
+ file->name = name;
+ file->fd = -2;
+ splay_tree_insert (pfile->all_include_files, (splay_tree_key) name,
+ (splay_tree_value) file);
! return file->name;
}
/* Not everyone who wants to set system-header-ness on a buffer can
*************** cpp_read_file (pfile, fname)
*** 701,707 ****
if (fname == NULL)
fname = "";
! f = lookup_include_file (pfile, fname);
if (f == NULL)
{
--- 715,721 ----
if (fname == NULL)
fname = "";
! f = open_file (pfile, fname);
if (f == NULL)
{
Index: testsuite/gcc.dg/cpp/mi4.c
===================================================================
RCS file: mi4.c
diff -N mi4.c
*** /dev/null Tue May 5 13:32:27 1998
--- mi4.c Wed Sep 20 15:24:29 2000
***************
*** 0 ****
--- 1,10 ----
+ /* Copyright (C) 2000 Free Software Foundation, Inc. */
+
+ /* { dg-do preprocess } */
+
+ /* Undefining a macro guard and re-including the file used to confuse
+ file caching in cppfiles.c, and attempt to open a bad fd. */
+
+ #include "mi1c.h"
+ #undef CPP_MIC_H
+ #include "mi1c.h"
More information about the Gcc-patches
mailing list