emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Preventing stack overflows with alloca.


From: Kim F. Storm
Subject: Preventing stack overflows with alloca.
Date: 18 Jun 2004 12:14:41 +0200
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3.50

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 <address@hidden> http://www.cua.dk





reply via email to

[Prev in Thread] Current Thread [Next in Thread]