From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: storm@cua.dk (Kim F. Storm) Newsgroups: gmane.emacs.devel Subject: Re: Preventing stack overflows with alloca. Date: 18 Jun 2004 14:02:00 +0200 Sender: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Message-ID: References: <200406181113.UAA03743@etlken.m17n.org> NNTP-Posting-Host: deer.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1087560187 3826 80.91.224.253 (18 Jun 2004 12:03:07 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Fri, 18 Jun 2004 12:03:07 +0000 (UTC) Cc: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Fri Jun 18 14:02:57 2004 Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 1BbI5A-0003DF-00 for ; Fri, 18 Jun 2004 14:02:56 +0200 Original-Received: from lists.gnu.org ([199.232.76.165]) by quimby.gnus.org with esmtp (Exim 3.35 #1 (Debian)) id 1BbI5A-0006JY-00 for ; Fri, 18 Jun 2004 14:02:56 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1BbI6G-0001PH-CT for emacs-devel@quimby.gnus.org; Fri, 18 Jun 2004 08:04:04 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.33) id 1BbI5r-0001IV-Fl for emacs-devel@gnu.org; Fri, 18 Jun 2004 08:03:40 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.33) id 1BbI5o-0001Gu-2O for emacs-devel@gnu.org; Fri, 18 Jun 2004 08:03:37 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1BbI5n-0001Gh-9S for emacs-devel@gnu.org; Fri, 18 Jun 2004 08:03:35 -0400 Original-Received: from [212.88.64.25] (helo=mail-relay.sonofon.dk) by monty-python.gnu.org with smtp (Exim 4.34) id 1BbI48-0000Ex-QC for emacs-devel@gnu.org; Fri, 18 Jun 2004 08:01:53 -0400 Original-Received: (qmail 73866 invoked from network); 18 Jun 2004 12:01:50 -0000 Original-Received: from unknown (HELO kfs-l.imdomain.dk.cua.dk) (213.83.150.2) by 0 with SMTP; 18 Jun 2004 12:01:50 -0000 Original-To: Kenichi Handa In-Reply-To: <200406181113.UAA03743@etlken.m17n.org> Original-Lines: 106 User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3.50 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.4 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:25082 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:25082 Kenichi Handa 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 http://www.cua.dk