From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Paul Eggert Newsgroups: gmane.emacs.bugs Subject: bug#27585: segfault when evaluating a file containing only backticks Date: Fri, 14 Jul 2017 05:09:34 -0700 Organization: UCLA Computer Science Department Message-ID: <070206be-9f8b-a324-0650-fd21b37a4132@cs.ucla.edu> References: <1499235670.28433.1@ssh.steve.org.uk> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------F10835463FC78717B7C06DF8" X-Trace: blaine.gmane.org 1500034228 31996 195.159.176.226 (14 Jul 2017 12:10:28 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Fri, 14 Jul 2017 12:10:28 +0000 (UTC) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 Cc: 27585-done@debbugs.gnu.org To: Steve Kemp Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Fri Jul 14 14:10:22 2017 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dVzQH-0007p7-PZ for geb-bug-gnu-emacs@m.gmane.org; Fri, 14 Jul 2017 14:10:17 +0200 Original-Received: from localhost ([::1]:37544 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dVzQN-0007Su-8X for geb-bug-gnu-emacs@m.gmane.org; Fri, 14 Jul 2017 08:10:23 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:44385) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dVzQ8-0007KS-C4 for bug-gnu-emacs@gnu.org; Fri, 14 Jul 2017 08:10:09 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dVzQ3-0000Xs-C4 for bug-gnu-emacs@gnu.org; Fri, 14 Jul 2017 08:10:08 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:35152) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dVzQ3-0000Xe-6W for bug-gnu-emacs@gnu.org; Fri, 14 Jul 2017 08:10:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1dVzQ2-0006pH-O4 for bug-gnu-emacs@gnu.org; Fri, 14 Jul 2017 08:10:02 -0400 In-Reply-To: <1499235670.28433.1@ssh.steve.org.uk> Resent-From: Paul Eggert Original-Sender: "Debbugs-submit" Resent-To: bug-gnu-emacs@gnu.org Resent-Date: Fri, 14 Jul 2017 12:10:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: cc-closed 27585 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Mail-Followup-To: 27585@debbugs.gnu.org, eggert@cs.ucla.edu, steve@steve.org.uk Original-Received: via spool by 27585-done@debbugs.gnu.org id=D27585.150003418426207 (code D ref 27585); Fri, 14 Jul 2017 12:10:02 +0000 Original-Received: (at 27585-done) by debbugs.gnu.org; 14 Jul 2017 12:09:44 +0000 Original-Received: from localhost ([127.0.0.1]:37829 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dVzPj-0006od-Mn for submit@debbugs.gnu.org; Fri, 14 Jul 2017 08:09:44 -0400 Original-Received: from zimbra.cs.ucla.edu ([131.179.128.68]:33030) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dVzPh-0006oN-Sb for 27585-done@debbugs.gnu.org; Fri, 14 Jul 2017 08:09:42 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 071EB1601EA; Fri, 14 Jul 2017 05:09:36 -0700 (PDT) Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id 8LVoba2Z6IK9; Fri, 14 Jul 2017 05:09:34 -0700 (PDT) Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id E0E76160182; Fri, 14 Jul 2017 05:09:34 -0700 (PDT) X-Virus-Scanned: amavisd-new at zimbra.cs.ucla.edu Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id GBr3Xqxo-tNr; Fri, 14 Jul 2017 05:09:34 -0700 (PDT) Original-Received: from [192.168.1.9] (unknown [47.153.184.153]) by zimbra.cs.ucla.edu (Postfix) with ESMTPSA id BD63A1600D7; Fri, 14 Jul 2017 05:09:34 -0700 (PDT) Content-Language: en-US X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:134547 Archived-At: This is a multi-part message in MIME format. --------------F10835463FC78717B7C06DF8 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable Thanks for reporting the bug. I reproduced the problem on Fedora 26 x86-6= 4,=20 fixed it in master by applying the attached patch, and am boldly marking = the bug=20 as fixed. As Eli and Daniel mentioned, this area of Emacs cannot be 100% reliable a= nd to=20 some extent is indeed a "ticking time bomb". That being said, the problem= in=20 this particular case was that Emacs had a bad heuristic for guessing whet= her a=20 segmentation violation address was due to stack overflow on GNU/Linux. Th= is bad=20 heuristic has been in place for years without anybody reporting it. It's = good=20 that we fixed this bug (though I hope "normal" users never notice the bug= fix :-). --------------F10835463FC78717B7C06DF8 Content-Type: text/x-patch; name="0001-Improve-stack-overflow-heuristic-on-GNU-Linux.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0001-Improve-stack-overflow-heuristic-on-GNU-Linux.patch" =46rom 9dee1c884eb50ba282eb9dd2495c5269add25963 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 14 Jul 2017 04:54:05 -0700 Subject: [PATCH] Improve stack-overflow heuristic on GNU/Linux Problem reported by Steve Kemp (Bug#27585). * src/eval.c (near_C_stack_top): Remove. All uses replaced by current_thread->stack_top. (record_in_backtrace): Set current_thread->stack_top. This is for when the Lisp interpreter calls itself. * src/lread.c (read1): Set current_thread->stack_top. This is for recursive s-expression reads. * src/print.c (print_object): Set current_thread->stack_top. This is for recursive s-expression printing. * src/thread.c (mark_one_thread): Get stack top first. * src/thread.h (struct thread_state.stack_top): Now void *, not char *. --- src/eval.c | 9 +-------- src/lisp.h | 1 - src/lread.c | 1 + src/print.c | 2 +- src/sysdep.c | 2 +- src/thread.c | 10 ++++++---- src/thread.h | 10 ++++++++-- 7 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/eval.c b/src/eval.c index 8f293c9..e590038 100644 --- a/src/eval.c +++ b/src/eval.c @@ -213,13 +213,6 @@ backtrace_next (union specbinding *pdl) return pdl; } =20 -/* Return a pointer to somewhere near the top of the C stack. */ -void * -near_C_stack_top (void) -{ - return backtrace_args (backtrace_top ()); -} - void init_eval_once (void) { @@ -2090,7 +2083,7 @@ record_in_backtrace (Lisp_Object function, Lisp_Obj= ect *args, ptrdiff_t nargs) specpdl_ptr->bt.kind =3D SPECPDL_BACKTRACE; specpdl_ptr->bt.debug_on_exit =3D false; specpdl_ptr->bt.function =3D function; - specpdl_ptr->bt.args =3D args; + current_thread->stack_top =3D specpdl_ptr->bt.args =3D args; specpdl_ptr->bt.nargs =3D nargs; grow_specpdl (); =20 diff --git a/src/lisp.h b/src/lisp.h index f5cb6c7..1e8ef7a 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3874,7 +3874,6 @@ extern Lisp_Object vformat_string (const char *, va= _list) ATTRIBUTE_FORMAT_PRINTF (1, 0); extern void un_autoload (Lisp_Object); extern Lisp_Object call_debugger (Lisp_Object arg); -extern void *near_C_stack_top (void); extern void init_eval_once (void); extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...); extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object); diff --git a/src/lread.c b/src/lread.c index fe5de38..901e40b 100644 --- a/src/lread.c +++ b/src/lread.c @@ -2676,6 +2676,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool firs= t_in_list) bool uninterned_symbol =3D false; bool multibyte; char stackbuf[MAX_ALLOCA]; + current_thread->stack_top =3D stackbuf; =20 *pch =3D 0; =20 diff --git a/src/print.c b/src/print.c index b6ea3ff..12edf01 100644 --- a/src/print.c +++ b/src/print.c @@ -1748,7 +1748,7 @@ print_object (Lisp_Object obj, Lisp_Object printcha= rfun, bool escapeflag) char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT= ), max (sizeof " . #" + INT_STRLEN_BOUND (printmax_t), 40))]; - + current_thread->stack_top =3D buf; maybe_quit (); =20 /* Detect circularities and truncate them. */ diff --git a/src/sysdep.c b/src/sysdep.c index b522367..db99f53 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -1772,7 +1772,7 @@ stack_overflow (siginfo_t *siginfo) /* The known top and bottom of the stack. The actual stack may extend a bit beyond these boundaries. */ char *bot =3D stack_bottom; - char *top =3D near_C_stack_top (); + char *top =3D current_thread->stack_top; =20 /* Log base 2 of the stack heuristic ratio. This ratio is the size of the known stack divided by the size of the guard area past the diff --git a/src/thread.c b/src/thread.c index e378797..1f7ced3 100644 --- a/src/thread.c +++ b/src/thread.c @@ -595,14 +595,15 @@ thread_select (select_func *func, int max_fds, fd_s= et *rfds, static void mark_one_thread (struct thread_state *thread) { - struct handler *handler; - Lisp_Object tem; + /* Get the stack top now, in case mark_specpdl changes it. */ + void *stack_top =3D thread->stack_top; =20 mark_specpdl (thread->m_specpdl, thread->m_specpdl_ptr); =20 - mark_stack (thread->m_stack_bottom, thread->stack_top); + mark_stack (thread->m_stack_bottom, stack_top); =20 - for (handler =3D thread->m_handlerlist; handler; handler =3D handler->= next) + for (struct handler *handler =3D thread->m_handlerlist; + handler; handler =3D handler->next) { mark_object (handler->tag_or_ch); mark_object (handler->val); @@ -610,6 +611,7 @@ mark_one_thread (struct thread_state *thread) =20 if (thread->m_current_buffer) { + Lisp_Object tem; XSETBUFFER (tem, thread->m_current_buffer); mark_object (tem); } diff --git a/src/thread.h b/src/thread.h index 9e94de5..52b16f1 100644 --- a/src/thread.h +++ b/src/thread.h @@ -62,8 +62,14 @@ struct thread_state char *m_stack_bottom; #define stack_bottom (current_thread->m_stack_bottom) =20 - /* An address near the top of the stack. */ - char *stack_top; + /* The address of an object near the C stack top, used to determine + which words need to be scanned by the garbage collector. This is + also used to detect heuristically whether segmentation violation + address indicates stack overflow, as opposed to some internal + error in Emacs. If the C function F calls G which calls H which + calls ... F, then at least one of the functions in the chain + should set this to the address of a local variable. */ + void *stack_top; =20 struct catchtag *m_catchlist; #define catchlist (current_thread->m_catchlist) --=20 2.7.4 --------------F10835463FC78717B7C06DF8--