unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Kenichi Handa <handa@m17n.org>
Cc: emacs-devel@gnu.org
Subject: Re: Preventing stack overflows with alloca.
Date: Fri, 18 Jun 2004 20:13:24 +0900 (JST)	[thread overview]
Message-ID: <200406181113.UAA03743@etlken.m17n.org> (raw)
In-Reply-To: <m3smctxje6.fsf@kfs-l.imdomain.dk> (storm@cua.dk)

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

  reply	other threads:[~2004-06-18 11:13 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-06-18 10:14 Preventing stack overflows with alloca Kim F. Storm
2004-06-18 11:13 ` Kenichi Handa [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200406181113.UAA03743@etlken.m17n.org \
    --to=handa@m17n.org \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).