diff options
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/src/eval.c b/src/eval.c index 93da7799bec..0f9e012b823 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -18,6 +18,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | #include <config.h> | 20 | #include <config.h> |
| 21 | #include <limits.h> | ||
| 21 | #include <setjmp.h> | 22 | #include <setjmp.h> |
| 22 | #include "lisp.h" | 23 | #include "lisp.h" |
| 23 | #include "blockinput.h" | 24 | #include "blockinput.h" |
| @@ -30,6 +31,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 30 | #include "xterm.h" | 31 | #include "xterm.h" |
| 31 | #endif | 32 | #endif |
| 32 | 33 | ||
| 34 | #ifndef SIZE_MAX | ||
| 35 | # define SIZE_MAX ((size_t) -1) | ||
| 36 | #endif | ||
| 37 | |||
| 33 | /* This definition is duplicated in alloc.c and keyboard.c. */ | 38 | /* This definition is duplicated in alloc.c and keyboard.c. */ |
| 34 | /* Putting it in lisp.h makes cc bomb out! */ | 39 | /* Putting it in lisp.h makes cc bomb out! */ |
| 35 | 40 | ||
| @@ -1401,7 +1406,7 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform, | |||
| 1401 | || (CONSP (tem) | 1406 | || (CONSP (tem) |
| 1402 | && (SYMBOLP (XCAR (tem)) | 1407 | && (SYMBOLP (XCAR (tem)) |
| 1403 | || CONSP (XCAR (tem)))))) | 1408 | || CONSP (XCAR (tem)))))) |
| 1404 | error ("Invalid condition handler", tem); | 1409 | error ("Invalid condition handler"); |
| 1405 | } | 1410 | } |
| 1406 | 1411 | ||
| 1407 | c.tag = Qnil; | 1412 | c.tag = Qnil; |
| @@ -1976,33 +1981,39 @@ find_handler_clause (Lisp_Object handlers, Lisp_Object conditions, | |||
| 1976 | void | 1981 | void |
| 1977 | verror (const char *m, va_list ap) | 1982 | verror (const char *m, va_list ap) |
| 1978 | { | 1983 | { |
| 1979 | char buf[200]; | 1984 | char buf[4000]; |
| 1980 | EMACS_INT size = 200; | 1985 | size_t size = sizeof buf; |
| 1981 | int mlen; | 1986 | size_t size_max = |
| 1987 | min (MOST_POSITIVE_FIXNUM, min (INT_MAX, SIZE_MAX - 1)) + 1; | ||
| 1982 | char *buffer = buf; | 1988 | char *buffer = buf; |
| 1983 | int allocated = 0; | 1989 | int used; |
| 1984 | Lisp_Object string; | 1990 | Lisp_Object string; |
| 1985 | 1991 | ||
| 1986 | mlen = strlen (m); | ||
| 1987 | |||
| 1988 | while (1) | 1992 | while (1) |
| 1989 | { | 1993 | { |
| 1990 | EMACS_INT used; | 1994 | used = vsnprintf (buffer, size, m, ap); |
| 1991 | used = doprnt (buffer, size, m, m + mlen, ap); | 1995 | |
| 1992 | if (used < size) | 1996 | if (used < 0) |
| 1993 | break; | ||
| 1994 | size *= 2; | ||
| 1995 | if (allocated) | ||
| 1996 | buffer = (char *) xrealloc (buffer, size); | ||
| 1997 | else | ||
| 1998 | { | 1997 | { |
| 1999 | buffer = (char *) xmalloc (size); | 1998 | /* Non-C99 vsnprintf, such as w32, returns -1 when SIZE is too small. |
| 2000 | allocated = 1; | 1999 | Guess a larger USED to work around the incompatibility. */ |
| 2000 | used = (size <= size_max / 2 ? 2 * size | ||
| 2001 | : size < size_max ? size_max - 1 | ||
| 2002 | : size_max); | ||
| 2001 | } | 2003 | } |
| 2004 | else if (used < size) | ||
| 2005 | break; | ||
| 2006 | if (size_max <= used) | ||
| 2007 | memory_full (); | ||
| 2008 | size = used + 1; | ||
| 2009 | |||
| 2010 | if (buffer != buf) | ||
| 2011 | xfree (buffer); | ||
| 2012 | buffer = (char *) xmalloc (size); | ||
| 2002 | } | 2013 | } |
| 2003 | 2014 | ||
| 2004 | string = build_string (buffer); | 2015 | string = make_string (buffer, used); |
| 2005 | if (allocated) | 2016 | if (buffer != buf) |
| 2006 | xfree (buffer); | 2017 | xfree (buffer); |
| 2007 | 2018 | ||
| 2008 | xsignal1 (Qerror, string); | 2019 | xsignal1 (Qerror, string); |