summaryrefslogtreecommitdiff
path: root/builtins/evalfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtins/evalfile.c')
-rw-r--r--builtins/evalfile.c73
1 files changed, 52 insertions, 21 deletions
diff --git a/builtins/evalfile.c b/builtins/evalfile.c
index d05bc7b..972d039 100644
--- a/builtins/evalfile.c
+++ b/builtins/evalfile.c
@@ -1,20 +1,22 @@
-/* Copyright (C) 1996-2003 Free Software Foundation, Inc.
+/* evalfile.c - read and evaluate commands from a file or file descriptor */
+
+/* Copyright (C) 1996-2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
- Bash is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 2, or (at your option) any later
- version.
+ Bash is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bash is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
- Bash is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License along
- with Bash; see the file COPYING. If not, write to the Free Software
- Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+ You should have received a copy of the GNU General Public License
+ along with Bash. If not, see <http://www.gnu.org/licenses/>.
+*/
#include <config.h>
@@ -45,6 +47,8 @@
# include "../bashhist.h"
#endif
+#include <typemax.h>
+
#include "common.h"
#if !defined (errno)
@@ -77,7 +81,8 @@ _evalfile (filename, flags)
{
volatile int old_interactive;
procenv_t old_return_catch;
- int return_val, fd, result, pflags;
+ int return_val, fd, result, pflags, i, nnull;
+ ssize_t nr; /* return value from read(2) */
char *string;
struct stat finfo;
size_t file_size;
@@ -147,34 +152,60 @@ file_error_and_exit:
setmode (fd, O_TEXT);
#endif
- string = (char *)xmalloc (1 + file_size);
- result = read (fd, string, file_size);
- string[result] = '\0';
+ if (S_ISREG (finfo.st_mode) && file_size <= SSIZE_MAX)
+ {
+ string = (char *)xmalloc (1 + file_size);
+ nr = read (fd, string, file_size);
+ if (nr >= 0)
+ string[nr] = '\0';
+ }
+ else
+ nr = zmapfd (fd, &string, 0);
return_val = errno;
close (fd);
errno = return_val;
- if (result < 0) /* XXX was != file_size, not < 0 */
+ if (nr < 0) /* XXX was != file_size, not < 0 */
{
free (string);
goto file_error_and_exit;
}
- if (result == 0)
+ if (nr == 0)
{
free (string);
return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1);
}
if ((flags & FEVAL_CHECKBINARY) &&
- check_binary_file (string, (result > 80) ? 80 : result))
+ check_binary_file (string, (nr > 80) ? 80 : nr))
{
free (string);
- (*errfunc) ("%s: cannot execute binary file", filename);
+ (*errfunc) (_("%s: cannot execute binary file"), filename);
return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
}
+ i = strlen (string);
+ if (i < nr)
+ {
+ for (nnull = i = 0; i < nr; i++)
+ if (string[i] == '\0')
+ {
+ memmove (string+i, string+i+1, nr - i);
+ nr--;
+ /* Even if the `check binary' flag is not set, we want to avoid
+ sourcing files with more than 256 null characters -- that
+ probably indicates a binary file. */
+ if ((flags & FEVAL_BUILTIN) && ++nnull > 256)
+ {
+ free (string);
+ (*errfunc) (_("%s: cannot execute binary file"), filename);
+ return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
+ }
+ }
+ }
+
if (flags & FEVAL_UNWINDPROT)
{
begin_unwind_frame ("_evalfile");