unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Preventing stack overflows with alloca.
@ 2004-06-18 10:14 Kim F. Storm
  2004-06-18 11:13 ` Kenichi Handa
  0 siblings, 1 reply; 11+ messages in thread
From: Kim F. Storm @ 2004-06-18 10:14 UTC (permalink / raw)



Jan just installed a change to fns.c to use xmalloc instead of
alloca in string_to_multibyte.

Always using xmalloc seems a bit expensive, so I suggest
only using it if the size is > MAX_ALLOCA (already defined
in fns.c).

But there are other risky uses of alloca, so I suggest the 
patch below which takes care of the problems in fns.c.  


It might be necessary to unwind protect the xfree calls,
but in any case, a memory leak is better than a trap ...

An simple alternative to unwind protect would be to link such
temporary xmalloc blocks on a global xfree_temp_list around the
problematic code (if the code runs ok, we remove the pointer again)
then the main interpreter loop could free such temporary memory
blocks.


Something like this (untested):

void *xfree_temp_list = 0;

void *xmalloc_temp(int size)
{
  void **ptr;
  ptr = (void **)xmalloc(size + sizeof(void *));
  *ptr = xfree_temp_list;
  xfree_temp_list = (void *)ptr;
  return (void *)(ptr+1);
}

void xfree_temp(void *ptr)
{
  assert(xfree_temp_list == ptr);

  xfree_temp_list = *--(void **)ptr;
  xfree(ptr);
}


and then in the main loop something like this:

while (xfree_temp_list)
  {
    void *ptr = xfree_temp_list;
    xfree_temp_list = *(void **)ptr;
    xfree(ptr);
  }


Here is the patch without using xmalloc_temp/xfree_temp:


*** fns.c	18 Jun 2004 10:05:47 +0200	1.364
--- fns.c	18 Jun 2004 10:29:46 +0200	
***************
*** 75,80 ****
--- 75,84 ----
  
  extern Lisp_Object Qinput_method_function;
  
+ /* Don't use alloca for regions larger than this, lest we overflow
+    their stack.  */
+ #define MAX_ALLOCA 16*1024
+ 
  static int internal_equal ();
  
  extern long get_random ();
***************
*** 994,999 ****
--- 998,1004 ----
  {
    unsigned char *buf;
    int nbytes;
+   Lisp_Object ret;
  
    if (STRING_MULTIBYTE (string))
      return string;
***************
*** 1005,1015 ****
    if (nbytes == SBYTES (string))
      return string;
  
!   buf = (unsigned char *) alloca (nbytes);
    copy_text (SDATA (string), buf, SBYTES (string),
  	     0, 1);
  
!   return make_multibyte_string (buf, SCHARS (string), nbytes);
  }
  
  
--- 1010,1029 ----
    if (nbytes == SBYTES (string))
      return string;
  
!   if (nbytes > MAX_ALLOCA)
!     buf = (unsigned char *) xmalloc (nbytes);
!   else
!     buf = (unsigned char *) alloca (nbytes);
! 
    copy_text (SDATA (string), buf, SBYTES (string),
  	     0, 1);
  
!   ret = make_multibyte_string (buf, SCHARS (string), nbytes);
! 
!   if (nbytes > MAX_ALLOCA)
!     xfree (buf);
! 
!   return ret;
  }
  
  
***************
*** 1024,1029 ****
--- 1038,1044 ----
  {
    unsigned char *buf;
    int nbytes;
+   Lisp_Object ret;
  
    if (STRING_MULTIBYTE (string))
      return string;
***************
*** 1034,1044 ****
    if (nbytes == SBYTES (string))
      return make_multibyte_string (SDATA (string), nbytes, nbytes);
  
!   buf = (unsigned char *) alloca (nbytes);
    bcopy (SDATA (string), buf, SBYTES (string));
    str_to_multibyte (buf, nbytes, SBYTES (string));
  
!   return make_multibyte_string (buf, SCHARS (string), nbytes);
  }
  
  
--- 1049,1067 ----
    if (nbytes == SBYTES (string))
      return make_multibyte_string (SDATA (string), nbytes, nbytes);
  
!   if (nbytes > MAX_ALLOCA)
!     buf = (unsigned char *) xmalloc (nbytes);
!   else
!     buf = (unsigned char *) alloca (nbytes);
! 
    bcopy (SDATA (string), buf, SBYTES (string));
    str_to_multibyte (buf, nbytes, SBYTES (string));
+   ret = make_multibyte_string (buf, SCHARS (string), nbytes);
  
!   if (nbytes > MAX_ALLOCA)
!     xfree (buf);
! 
!   return ret;
  }
  
  
***************
*** 1049,1070 ****
       Lisp_Object string;
  {
    unsigned char *buf;
    Lisp_Object ret;
  
    if (! STRING_MULTIBYTE (string))
      return string;
  
!   /* We can not use alloca here, because string might be very long.
       For example when selecting megabytes of text and then pasting it to
       another application.  */
!   buf = (unsigned char *) xmalloc (SCHARS (string));
  
    copy_text (SDATA (string), buf, SBYTES (string),
  	     1, 0);
  
    ret = make_unibyte_string (buf, SCHARS (string));
  
!   xfree (buf);
  
    return ret;
  }
--- 1072,1100 ----
       Lisp_Object string;
  {
    unsigned char *buf;
+   int nbytes;
    Lisp_Object ret;
  
    if (! STRING_MULTIBYTE (string))
      return string;
  
!   /* We can not just use alloca here, because string might be very long.
       For example when selecting megabytes of text and then pasting it to
       another application.  */
! 
!   nbytes = SCHARS (string);
!   if (nbytes > MAX_ALLOCA)
!     buf = (unsigned char *) xmalloc (nbytes);
!   else
!     buf = (unsigned char *) alloca (nbytes);
  
    copy_text (SDATA (string), buf, SBYTES (string),
  	     1, 0);
  
    ret = make_unibyte_string (buf, SCHARS (string));
  
!   if (nbytes > MAX_ALLOCA)
!     xfree (buf);
  
    return ret;
  }
***************
*** 2985,2993 ****
       (function, sequence, separator)
       Lisp_Object function, sequence, separator;
  {
!   Lisp_Object len;
    register int leni;
!   int nargs;
    register Lisp_Object *args;
    register int i;
    struct gcpro gcpro1;
--- 3015,3023 ----
       (function, sequence, separator)
       Lisp_Object function, sequence, separator;
  {
!   Lisp_Object len, ret;
    register int leni;
!   int nargs, nbytes;
    register Lisp_Object *args;
    register int i;
    struct gcpro gcpro1;
***************
*** 2997,3003 ****
    nargs = leni + leni - 1;
    if (nargs < 0) return build_string ("");
  
!   args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
  
    GCPRO1 (separator);
    mapcar1 (leni, args, function, sequence);
--- 3027,3037 ----
    nargs = leni + leni - 1;
    if (nargs < 0) return build_string ("");
  
!   nbytes = nargs * sizeof (Lisp_Object);
!   if (nbytes > MAX_ALLOCA)
!     args = (Lisp_Object *) xmalloc (nbytes);
!   else
!     args = (Lisp_Object *) alloca (nbytes);
  
    GCPRO1 (separator);
    mapcar1 (leni, args, function, sequence);
***************
*** 3009,3015 ****
    for (i = 1; i < nargs; i += 2)
      args[i] = separator;
  
!   return Fconcat (nargs, args);
  }
  
  DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
--- 3043,3054 ----
    for (i = 1; i < nargs; i += 2)
      args[i] = separator;
  
!   ret = Fconcat (nargs, args);
! 
!   if (nbytes > MAX_ALLOCA)
!     xfree (args);
! 
!   return ret;
  }
  
  DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
***************
*** 3019,3035 ****
       (function, sequence)
       Lisp_Object function, sequence;
  {
!   register Lisp_Object len;
!   register int leni;
!   register Lisp_Object *args;
  
    len = Flength (sequence);
    leni = XFASTINT (len);
!   args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
  
    mapcar1 (leni, args, function, sequence);
  
!   return Flist (leni, args);
  }
  
  DEFUN ("mapc", Fmapc, Smapc, 2, 2, 0,
--- 3058,3084 ----
       (function, sequence)
       Lisp_Object function, sequence;
  {
!   Lisp_Object len, ret;
!   int leni, nbytes;
!   Lisp_Object *args;
  
    len = Flength (sequence);
    leni = XFASTINT (len);
! 
!   nbytes = leni * sizeof (Lisp_Object);
!   if (nbytes > MAX_ALLOCA)
!     args = (Lisp_Object *) xmalloc (nbytes);
!   else
!     args = (Lisp_Object *) alloca (nbytes);
  
    mapcar1 (leni, args, function, sequence);
  
!   ret = Flist (leni, args);
! 
!   if (nbytes > MAX_ALLOCA)
!     xfree (args);
! 
!   return ret;
  }
  
  DEFUN ("mapc", Fmapc, Smapc, 2, 2, 0,
***************
*** 3644,3653 ****
      }					\
    while (IS_BASE64_IGNORABLE (c))
  
- /* Don't use alloca for regions larger than this, lest we overflow
-    their stack.  */
- #define MAX_ALLOCA 16*1024
- 
  /* Table of characters coding the 64 values.  */
  static char base64_value_to_char[64] =
  {
--- 3693,3698 ----

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preventing stack overflows with alloca.
  2004-06-18 10:14 Preventing stack overflows with alloca Kim F. Storm
@ 2004-06-18 11:13 ` Kenichi Handa
  2004-06-18 12:02   ` Kim F. Storm
  2004-10-25 17:11   ` Yoichi NAKAYAMA
  0 siblings, 2 replies; 11+ messages in thread
From: Kenichi Handa @ 2004-06-18 11:13 UTC (permalink / raw)
  Cc: emacs-devel

In article <m3smctxje6.fsf@kfs-l.imdomain.dk>, storm@cua.dk (Kim F. Storm) writes:

> Jan just installed a change to fns.c to use xmalloc instead of
> alloca in string_to_multibyte.

> Always using xmalloc seems a bit expensive, so I suggest
> only using it if the size is > MAX_ALLOCA (already defined
> in fns.c).

> But there are other risky uses of alloca, so I suggest the 
> patch below which takes care of the problems in fns.c.  

Oops, I have completely forgotten about this problem.
Actually I noticed it last year and sent the attached mail,
but haven't worked on it any further.  I remember Richard
agreed with having the macro SAFE_ALLOCA.  Of course we need
the pairing SAFE_FREE which frees `address' and calls
unbind_to if necessary.

---
Ken'ichi HANDA
handa@m17n.org

Date: Thu, 20 Nov 2003 22:01:20 +0900 (JST)
From: Kenichi Handa <handa@m17n.org>
To: emacs-devel@gnu.org
Subject: dangerous alloca calls
Sender: emacs-devel-bounces+handa=m17n.org@gnu.org

With CVS HEAD emacs on GNU/Linux,
   (mapcar 'car (make-list #x400000 nil))
causes segfault.

The attached patch fixes it.  But, I found such dangerous
alloca calls in several other places.

E.g. (format (make-string #x1000000 32))
     (apply 'car (make-list #x100000 nil))

It seems that it is better that we use a macro something
like this consitently.  What do you think?

#define SAFE_ALLOCA(address, size, unwind_function)		\
  do {								\
    if (size < MAX_ALLOCA)					\
      address = alloca (size);					\
    else							\
      {								\
	address = xmalloc (size);				\
	if (unwind_function)					\
	  record_unwind_protect (unwind_function, Qnil);	\
      }								\
  } while (0)

---
Ken'ichi HANDA
handa@m17n.org

*** fns.c.~1.346.~	Wed Nov 19 20:06:32 2003
--- fns.c	Thu Nov 20 21:26:50 2003
***************
*** 79,84 ****
--- 79,88 ----
  #ifndef HAVE_UNISTD_H
  extern long time ();
  #endif
+ 
+ /* Don't use alloca for bytes larger than this, lest we overflow
+    their stack.  */
+ #define MAX_ALLOCA 16*1024
  \f
  DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
         doc: /* Return the argument unchanged.  */)
***************
*** 2937,2942 ****
--- 2941,2956 ----
    UNGCPRO;
  }
  
+ static Lisp_Object *mapcar_args;
+ 
+ static Lisp_Object
+ mapcar_unwind (arg)
+      Lisp_Object arg;
+ {
+   xfree (mapcar_args);
+   return Qnil;
+ }
+ 
  DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
         doc: /* Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.
  In between each pair of results, stick in SEPARATOR.  Thus, " " as
***************
*** 2951,2963 ****
    register Lisp_Object *args;
    register int i;
    struct gcpro gcpro1;
  
    len = Flength (sequence);
    leni = XINT (len);
    nargs = leni + leni - 1;
    if (nargs < 0) return build_string ("");
  
!   args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
  
    GCPRO1 (separator);
    mapcar1 (leni, args, function, sequence);
--- 2965,2986 ----
    register Lisp_Object *args;
    register int i;
    struct gcpro gcpro1;
+   int nbytes;
+   int count = SPECPDL_INDEX ();
  
    len = Flength (sequence);
    leni = XINT (len);
    nargs = leni + leni - 1;
    if (nargs < 0) return build_string ("");
  
!   nbytes = nargs * sizeof (Lisp_Object);
!   if (nbytes < MAX_ALLOCA)
!     args = (Lisp_Object *) alloca (nbytes);
!   else
!     {
!       args = mapcar_args = (Lisp_Object *) xmalloc (nbytes);
!       record_unwind_protect (mapcar_unwind, Qnil);
!     }
  
    GCPRO1 (separator);
    mapcar1 (leni, args, function, sequence);
***************
*** 2969,2975 ****
    for (i = 1; i < nargs; i += 2)
      args[i] = separator;
  
!   return Fconcat (nargs, args);
  }
  
  DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
--- 2992,3001 ----
    for (i = 1; i < nargs; i += 2)
      args[i] = separator;
  
!   if (nbytes < MAX_ALLOCA)
!     return Fconcat (nargs, args);
!   else
!     return unbind_to (count, Fconcat (nargs, args));
  }
  
  DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
***************
*** 2982,2995 ****
    register Lisp_Object len;
    register int leni;
    register Lisp_Object *args;
  
    len = Flength (sequence);
    leni = XFASTINT (len);
!   args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
  
    mapcar1 (leni, args, function, sequence);
  
!   return Flist (leni, args);
  }
  
  DEFUN ("mapc", Fmapc, Smapc, 2, 2, 0,
--- 3008,3035 ----
    register Lisp_Object len;
    register int leni;
    register Lisp_Object *args;
+   int nbytes;
+   int count = SPECPDL_INDEX ();
  
    len = Flength (sequence);
    leni = XFASTINT (len);
!   if (leni < 0) return Qnil;
! 
!   nbytes = leni * sizeof (Lisp_Object);
!   if (nbytes < MAX_ALLOCA)
!     args = (Lisp_Object *) alloca (nbytes);
!   else
!     {
!       args = mapcar_args = (Lisp_Object *) xmalloc (nbytes);
!       record_unwind_protect (mapcar_unwind, Qnil);
!     }
  
    mapcar1 (leni, args, function, sequence);
  
!   if (nbytes < MAX_ALLOCA)
!     return Flist (leni, args);
!   else
!     return unbind_to (count, Flist (leni, args));
  }
  
  DEFUN ("mapc", Fmapc, Smapc, 2, 2, 0,
***************
*** 3603,3612 ****
        c = from[i++];			\
      }					\
    while (IS_BASE64_IGNORABLE (c))
- 
- /* Don't use alloca for regions larger than this, lest we overflow
-    their stack.  */
- #define MAX_ALLOCA 16*1024
  
  /* Table of characters coding the 64 values.  */
  static char base64_value_to_char[64] =
--- 3643,3648 ----


_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preventing stack overflows with alloca.
  2004-06-18 11:13 ` Kenichi Handa
@ 2004-06-18 12:02   ` Kim F. Storm
  2004-06-19  0:19     ` Kenichi Handa
  2004-06-19  3:19     ` Richard Stallman
  2004-10-25 17:11   ` Yoichi NAKAYAMA
  1 sibling, 2 replies; 11+ messages in thread
From: Kim F. Storm @ 2004-06-18 12:02 UTC (permalink / raw)
  Cc: emacs-devel

Kenichi Handa <handa@m17n.org> writes:

> > But there are other risky uses of alloca, so I suggest the
> > patch below which takes care of the problems in fns.c.
>
> Oops, I have completely forgotten about this problem.
> Actually I noticed it last year and sent the attached mail,
> but haven't worked on it any further.  I remember Richard
> agreed with having the macro SAFE_ALLOCA.  Of course we need
> the pairing SAFE_FREE which frees `address' and calls
> unbind_to if necessary.


Actually, now that you mention it, I remember your mail.

I think your approach is ok, but we can make it a bit
more generic with the following approach:


/* Define this in alloc.c */

Lisp_Object
safe_alloca_unwind (arg)
     Lisp_Object arg;
{
  xfree ((void *)arg);
  return Qnil;
}


/* Add this to lisp.h */

extern Lisp_Object safe_alloca_unwind (Lisp_Object *);


#define USE_SAFE_ALLOCA                                 \
  int sa_count = SPECPDL_INDEX ()

#define SAFE_ALLOCA(buf, size)                          \
  do {							\
    if (size < MAX_ALLOCA)				\
      buf = alloca (size);				\
    else						\
      record_unwind_protect (safe_alloca_unwind,        \
              (Lisp_Object)(buf = xmalloc (size)));     \
  } while (0)

#define SAFE_FREE(size)                                 \
  do {                                                  \
    if (size >= MAX_ALLOCA)                             \
      unbind_to (sa_count, Qnil);                       \
  } while (0)


Of course, if a function already uses unwind protect,
it doesn't need USE_SAFE_ALLOCA and SAFE_FREE.


Since old_value is not a lisp object here,
we would need to fix (hack) GC like this:

  for (bind = specpdl; bind != specpdl_ptr; bind++)
    {
      mark_object (bind->symbol);
      if (bind->func != safe_alloca_unwind)
        mark_object (bind->old_value);
    }



A sample use would look like this:

Lisp_Object
string_make_multibyte (string)
     Lisp_Object string;
{
  unsigned char *buf;
  int nbytes;
  Lisp_Object ret;
  USE_SAFE_ALLOCA;

  if (STRING_MULTIBYTE (string))
    return string;

  nbytes = count_size_as_multibyte (SDATA (string),
				    SCHARS (string));
  /* If all the chars are ASCII, they won't need any more bytes
     once converted.  In that case, we can return STRING itself.  */
  if (nbytes == SBYTES (string))
    return string;

  SAFE_ALLOCA (buf, nbytes);

  copy_text (SDATA (string), buf, SBYTES (string),
	     0, 1);

  ret = make_multibyte_string (buf, SCHARS (string), nbytes);

  SAFE_FREE (nbytes);

  return ret;
}


--
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preventing stack overflows with alloca.
  2004-06-18 12:02   ` Kim F. Storm
@ 2004-06-19  0:19     ` Kenichi Handa
  2004-06-19  3:19     ` Richard Stallman
  1 sibling, 0 replies; 11+ messages in thread
From: Kenichi Handa @ 2004-06-19  0:19 UTC (permalink / raw)
  Cc: emacs-devel

In article <m3k6y5xefb.fsf@kfs-l.imdomain.dk>, storm@cua.dk (Kim F. Storm) writes:

> Since old_value is not a lisp object here,
> we would need to fix (hack) GC like this:

>   for (bind = specpdl; bind != specpdl_ptr; bind++)
>     {
>       mark_object (bind->symbol);
>       if (bind->func != safe_alloca_unwind)
>         mark_object (bind->old_value);
>     }

I now remembered why I didn't work on it further.  That's
because I didn't find the above simple solution!  So, I was
going to change `unused' of struct specbinding to void *val,
make record_unwind_protect_c which accepts void * instead of
Lisp_Object as ARG, make unbind_to to call func with val
instead of old_value of val is not NULL, etc... and noticed
that it's a too big change for the current rather simple
problem.  :-(

> A sample use would look like this:

> Lisp_Object
> string_make_multibyte (string)
>      Lisp_Object string;
> {
>   unsigned char *buf;
>   int nbytes;
>   Lisp_Object ret;
>   USE_SAFE_ALLOCA;

>   if (STRING_MULTIBYTE (string))
>     return string;

>   nbytes = count_size_as_multibyte (SDATA (string),
> 				    SCHARS (string));
>   /* If all the chars are ASCII, they won't need any more bytes
>      once converted.  In that case, we can return STRING itself.  */
>   if (nbytes == SBYTES (string))
>     return string;

>   SAFE_ALLOCA (buf, nbytes);

>   copy_text (SDATA (string), buf, SBYTES (string),
> 	     0, 1);

>   ret = make_multibyte_string (buf, SCHARS (string), nbytes);

>   SAFE_FREE (nbytes);

>   return ret;
> }

I like it.

---
Ken'ichi HANDA
handa@m17n.org

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preventing stack overflows with alloca.
  2004-06-18 12:02   ` Kim F. Storm
  2004-06-19  0:19     ` Kenichi Handa
@ 2004-06-19  3:19     ` Richard Stallman
  2004-06-20 18:56       ` Kim F. Storm
  2004-06-21 22:01       ` Kim F. Storm
  1 sibling, 2 replies; 11+ messages in thread
From: Richard Stallman @ 2004-06-19  3:19 UTC (permalink / raw)
  Cc: emacs-devel, handa

    Since old_value is not a lisp object here,
    we would need to fix (hack) GC like this:

      for (bind = specpdl; bind != specpdl_ptr; bind++)
	{
	  mark_object (bind->symbol);
	  if (bind->func != safe_alloca_unwind)
	    mark_object (bind->old_value);
	}

Or else use make_save_value to convert it to a clean Lisp object.
Then GC won't need changing.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preventing stack overflows with alloca.
  2004-06-19  3:19     ` Richard Stallman
@ 2004-06-20 18:56       ` Kim F. Storm
  2004-06-21 22:01       ` Kim F. Storm
  1 sibling, 0 replies; 11+ messages in thread
From: Kim F. Storm @ 2004-06-20 18:56 UTC (permalink / raw)
  Cc: emacs-devel, handa

Richard Stallman <rms@gnu.org> writes:

>     Since old_value is not a lisp object here,
>     we would need to fix (hack) GC like this:
> 
>       for (bind = specpdl; bind != specpdl_ptr; bind++)
> 	{
> 	  mark_object (bind->symbol);
> 	  if (bind->func != safe_alloca_unwind)
> 	    mark_object (bind->old_value);
> 	}
> 
> Or else use make_save_value to convert it to a clean Lisp object.
> Then GC won't need changing.

I had forgot about make_save_value.  Yes, we should use that.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preventing stack overflows with alloca.
  2004-06-19  3:19     ` Richard Stallman
  2004-06-20 18:56       ` Kim F. Storm
@ 2004-06-21 22:01       ` Kim F. Storm
  2004-06-22 23:17         ` Richard Stallman
  1 sibling, 1 reply; 11+ messages in thread
From: Kim F. Storm @ 2004-06-21 22:01 UTC (permalink / raw)
  Cc: emacs-devel, handa

Richard Stallman <rms@gnu.org> writes:

>     Since old_value is not a lisp object here,
>     we would need to fix (hack) GC like this:
> 
>       for (bind = specpdl; bind != specpdl_ptr; bind++)
> 	{
> 	  mark_object (bind->symbol);
> 	  if (bind->func != safe_alloca_unwind)
> 	    mark_object (bind->old_value);
> 	}
> 
> Or else use make_save_value to convert it to a clean Lisp object.
> Then GC won't need changing.

I installed the SAFE_ALLOCA macros, using the make_save_value approach.
I also fixed the alloca uses that looked suspicious to me.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preventing stack overflows with alloca.
  2004-06-21 22:01       ` Kim F. Storm
@ 2004-06-22 23:17         ` Richard Stallman
  0 siblings, 0 replies; 11+ messages in thread
From: Richard Stallman @ 2004-06-22 23:17 UTC (permalink / raw)
  Cc: emacs-devel, handa

    I installed the SAFE_ALLOCA macros, using the make_save_value approach.
    I also fixed the alloca uses that looked suspicious to me.

Thanks.

It seems like a good optimization to make safe_alloca_unwind explicitly
free the save-value object.  Want to do that?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preventing stack overflows with alloca.
  2004-06-18 11:13 ` Kenichi Handa
  2004-06-18 12:02   ` Kim F. Storm
@ 2004-10-25 17:11   ` Yoichi NAKAYAMA
  2004-10-26 14:04     ` Kim F. Storm
  1 sibling, 1 reply; 11+ messages in thread
From: Yoichi NAKAYAMA @ 2004-10-25 17:11 UTC (permalink / raw)


At Fri, 18 Jun 2004 20:13:24 +0900 (JST),
Kenichi Handa wrote:
> Date: Thu, 20 Nov 2003 22:01:20 +0900 (JST)
> From: Kenichi Handa <handa@m17n.org>
> To: emacs-devel@gnu.org
> Subject: dangerous alloca calls
> Sender: emacs-devel-bounces+handa=m17n.org@gnu.org
> 
> With CVS HEAD emacs on GNU/Linux,
>    (mapcar 'car (make-list #x400000 nil))
> causes segfault.
> 
> The attached patch fixes it.  But, I found such dangerous
> alloca calls in several other places.
> 
> E.g. (format (make-string #x1000000 32))
>      (apply 'car (make-list #x100000 nil))

With CVS HEAD emacs on GNU/Linux,
   (format (make-string #x1000000 32))
still causes segfault.

Regards,
-- 
Yoichi NAKAYAMA

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preventing stack overflows with alloca.
  2004-10-25 17:11   ` Yoichi NAKAYAMA
@ 2004-10-26 14:04     ` Kim F. Storm
  2004-10-27 17:34       ` Richard Stallman
  0 siblings, 1 reply; 11+ messages in thread
From: Kim F. Storm @ 2004-10-26 14:04 UTC (permalink / raw)
  Cc: emacs-devel

Yoichi NAKAYAMA <yoichi@geiin.org> writes:

> At Fri, 18 Jun 2004 20:13:24 +0900 (JST),
> Kenichi Handa wrote:
>> Date: Thu, 20 Nov 2003 22:01:20 +0900 (JST)
>> From: Kenichi Handa <handa@m17n.org>
>> To: emacs-devel@gnu.org
>> Subject: dangerous alloca calls
>> Sender: emacs-devel-bounces+handa=m17n.org@gnu.org
>> 
>> With CVS HEAD emacs on GNU/Linux,
>>    (mapcar 'car (make-list #x400000 nil))
>> causes segfault.
>> 
>> The attached patch fixes it.  But, I found such dangerous
>> alloca calls in several other places.
>> 
>> E.g. (format (make-string #x1000000 32))
>>      (apply 'car (make-list #x100000 nil))
>
> With CVS HEAD emacs on GNU/Linux,
>    (format (make-string #x1000000 32))
> still causes segfault.


Calling format with a 16M format string is not a normal
thing to do, but I will fix this.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Preventing stack overflows with alloca.
  2004-10-26 14:04     ` Kim F. Storm
@ 2004-10-27 17:34       ` Richard Stallman
  0 siblings, 0 replies; 11+ messages in thread
From: Richard Stallman @ 2004-10-27 17:34 UTC (permalink / raw)
  Cc: yoichi, emacs-devel

    > With CVS HEAD emacs on GNU/Linux,
    >    (format (make-string #x1000000 32))
    > still causes segfault.


    Calling format with a 16M format string is not a normal
    thing to do, but I will fix this.

Thanks for reporting it, and thanks in advance for fixing it.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2004-10-27 17:34 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-06-18 10:14 Preventing stack overflows with alloca Kim F. Storm
2004-06-18 11:13 ` Kenichi Handa
2004-06-18 12:02   ` Kim F. Storm
2004-06-19  0:19     ` Kenichi Handa
2004-06-19  3:19     ` Richard Stallman
2004-06-20 18:56       ` Kim F. Storm
2004-06-21 22:01       ` Kim F. Storm
2004-06-22 23:17         ` Richard Stallman
2004-10-25 17:11   ` Yoichi NAKAYAMA
2004-10-26 14:04     ` Kim F. Storm
2004-10-27 17:34       ` Richard Stallman

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).