* bug#27585: segfault when evaluating a file containing only backticks @ 2017-07-05 6:21 Steve Kemp 2017-07-05 7:51 ` Andreas Schwab ` (2 more replies) 0 siblings, 3 replies; 25+ messages in thread From: Steve Kemp @ 2017-07-05 6:21 UTC (permalink / raw) To: 27585 I've recently started fuzzing GNU Emacs, using the current git sources. During the course of that work I stumbled upon this easily reproduced bug: deagol ~ $ perl -e 'print "`" x ( 1024 * 1024 * 12);' > t.el deagol ~ $ /usr/bin/emacs --batch --script ./t.el .. Segmentation fault (core dumped) (So I'm trying to call "emacs --batch --script $file" where the file contains thousands of repeated backtick-characters.) Because I've built from source I can see this backtrace: #5 handle_sigsegv (sig=11, siginfo=<optimized out>, arg=<optimized out>) at sysdep.c:1811 #6 <signal handler called> #7 read1 (readcharfun=readcharfun@entry=35581829, pch=pch@entry=0x7ffcc661e010, first_in_list=first_in_list@entry=false) at lread.c:2923 #8 0x0000000000ad8cda in read0 (readcharfun=35581829) at lread.c:2220 #9 read1 (readcharfun=readcharfun@entry=35581829, pch=pch@entry=0x7ffcc66220c0, first_in_list=first_in_list@entry=false) at lread.c:3149 #10 0x0000000000ad8cda in read0 (readcharfun=35581829) at lread.c:2220 #11 read1 (readcharfun=readcharfun@entry=35581829, pch=pch@entry=0x7ffcc6626170, first_in_list=first_in_list@entry=false) at lread.c:3149 #12 0x0000000000ad8cda in read0 (readcharfun=35581829) at lread.c:2220 #13 read1 (readcharfun=readcharfun@entry=35581829, pch=pch@entry=0x7ffcc662a220, first_in_list=first_in_list@entry=false) at lread.c:3149 #14 0x0000000000ad8cda in read0 (readcharfun=35581829) at lread.c:2220 #15 read1 (readcharfun=readcharfun@entry=35581829, pch=pch@entry=0x7ffcc662e2d0, first_in_list=first_in_list@entry=false) at lread.c:3149 #16 0x0000000000ad8cda in read0 (readcharfun=35581829) at lread.c:2220 #17 read1 (readcharfun=readcharfun@entry=35581829, pch=pch@entry=0x7ffcc6632380, first_in_list=first_in_list@entry=false) at lread.c:3149 #18 0x0000000000ad8cda in read0 (readcharfun=35581829) at lread.c:2220 #19 read1 (readcharfun=readcharfun@entry=35581829, pch=pch@entry=0x7ffcc6636430, first_in_list=first_in_list@entry=false) at lread.c:3149 #20 0x0000000000ad8cda in read0 (readcharfun=35581829) at lread.c:2220 #21 read1 (readcharfun=readcharfun@entry=35581829, pch=pch@entry=0x7ffcc663a4e0, first_in_list=first_in_list@entry=false) at lread.c:3149 .... I've replicated this upon the package of GNU Emacs as available to the old-stable/jessie release of Debian GNU/Linux, which identifies itself as: In GNU Emacs 24.5.1 (x86_64-pc-linux-gnu, GTK+ Version 3.14.5) of 2016-03-19 on trouble, modified by Debian Windowing system distributor `The X.Org Foundation', version 11.0.11604000 System Description: Debian GNU/Linux 8.8 (jessie) Configured using: `configure --build x86_64-linux-gnu --prefix=/usr --sharedstatedir=/var/lib --libexecdir=/usr/lib --localstatedir=/var/lib --infodir=/usr/share/info --mandir=/usr/share/man --with-pop=yes --enable-locallisppath=/etc/emacs24:/etc/emacs:/usr/local/share/emacs/24.5/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/24.5/site-lisp:/usr/share/emacs/site-lisp --build x86_64-linux-gnu --prefix=/usr --sharedstatedir=/var/lib --libexecdir=/usr/lib --localstatedir=/var/lib --infodir=/usr/share/info --mandir=/usr/share/man --with-pop=yes --enable-locallisppath=/etc/emacs24:/etc/emacs:/usr/local/share/emacs/24.5/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/24.5/site-lisp:/usr/share/emacs/site-lisp --with-x=yes --with-x-toolkit=gtk3 --with-toolkit-scroll-bars 'CFLAGS=-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wall' CPPFLAGS=-D_FORTIFY_SOURCE=2 LDFLAGS=-Wl,-z,relro' My current-git build reports as: In GNU Emacs 26.0.50 (build 1, x86_64-pc-linux-gnu) of 2017-07-05 built on kernel.default.skx.uk0.bigv.io Repository revision: 5d62247323f53f3ae9c7d9f51e951635887b2fb6 Recent messages: For information about GNU Emacs and the GNU system, type C-h C-a. Making completion list... Configured using: 'configure --prefix=/tmp/emacs/ --without-makeinfo --with-gnutls=no' Configured features: SOUND NOTIFY ZLIB Important settings: value of $LC_ALL: en_US.UTF8 value of $LANG: en_GB.UTF-8 locale-coding-system: utf-8-unix "Obviously" this same bug can be reproduced inside emacs: 1. Open Emacs. 2. Create a new buffer. 3. Fill the buffer with ` 4. Ctrl-x h 5. M-x eval-region Steve -- https://www.steve.org.uk/ ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-05 6:21 bug#27585: segfault when evaluating a file containing only backticks Steve Kemp @ 2017-07-05 7:51 ` Andreas Schwab 2017-07-05 8:26 ` Steve Kemp 2017-07-05 18:41 ` Eli Zaretskii 2017-07-14 12:09 ` Paul Eggert 2 siblings, 1 reply; 25+ messages in thread From: Andreas Schwab @ 2017-07-05 7:51 UTC (permalink / raw) To: Steve Kemp; +Cc: 27585 On Jul 05 2017, Steve Kemp <steve@steve.org.uk> wrote: > Because I've built from source I can see this backtrace: > > #5 handle_sigsegv (sig=11, siginfo=<optimized out>, arg=<optimized out>) > at sysdep.c:1811 > #6 <signal handler called> > #7 read1 (readcharfun=readcharfun@entry=35581829, > pch=pch@entry=0x7ffcc661e010, first_in_list=first_in_list@entry=false) > at lread.c:2923 Most likely just a stack overflow. Andreas. -- Andreas Schwab, SUSE Labs, schwab@suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different." ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-05 7:51 ` Andreas Schwab @ 2017-07-05 8:26 ` Steve Kemp 0 siblings, 0 replies; 25+ messages in thread From: Steve Kemp @ 2017-07-05 8:26 UTC (permalink / raw) To: 27585 > > #5 handle_sigsegv (sig=11, siginfo=<optimized out>, arg=<optimized out>) > > at sysdep.c:1811 > > #6 <signal handler called> > > #7 read1 (readcharfun=readcharfun@entry=35581829, > > pch=pch@entry=0x7ffcc661e010, first_in_list=first_in_list@entry=false) > > at lread.c:2923 > > Most likely just a stack overflow. Agreed, but still I think a segfault is unexpected and could be prevented. Steve -- https://www.steve.org.uk/ ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-05 6:21 bug#27585: segfault when evaluating a file containing only backticks Steve Kemp 2017-07-05 7:51 ` Andreas Schwab @ 2017-07-05 18:41 ` Eli Zaretskii 2017-07-05 18:55 ` Steve Kemp 2017-07-06 15:48 ` Daniel Colascione 2017-07-14 12:09 ` Paul Eggert 2 siblings, 2 replies; 25+ messages in thread From: Eli Zaretskii @ 2017-07-05 18:41 UTC (permalink / raw) To: Steve Kemp; +Cc: 27585 > From: Steve Kemp <steve@steve.org.uk> > Date: Wed, 05 Jul 2017 06:21:10 +0000 > > > I've recently started fuzzing GNU Emacs, using the current git sources. > During the course of that work I stumbled upon this easily reproduced bug: > > deagol ~ $ perl -e 'print "`" x ( 1024 * 1024 * 12);' > t.el > deagol ~ $ /usr/bin/emacs --batch --script ./t.el > .. > Segmentation fault (core dumped) Here it says: Re-entering top level after C stack overflow and doesn't crash. > > Most likely just a stack overflow. > > Agreed, but still I think a segfault is unexpected and could be > prevented. See above: the machinery to try and prevent it exists, but it doesn't always succeed. And it really can't be 100% reliable. So I'm unsure what did you expect, and why. Emacs generally gives you enough rope to hang yourself; it's up to you not to be tempted to do so... IOW: why would someone want to run such a silly "program"? ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-05 18:41 ` Eli Zaretskii @ 2017-07-05 18:55 ` Steve Kemp 2017-07-05 19:47 ` Eli Zaretskii 2017-07-06 15:48 ` Daniel Colascione 1 sibling, 1 reply; 25+ messages in thread From: Steve Kemp @ 2017-07-05 18:55 UTC (permalink / raw) To: 27585 > > deagol ~ $ perl -e 'print "`" x ( 1024 * 1024 * 12);' > t.el > > deagol ~ $ /usr/bin/emacs --batch --script ./t.el > > .. > > Segmentation fault (core dumped) > > Here it says: > > Re-entering top level after C stack overflow > > and doesn't crash. That's great. For me it crashes on all the versions I've tested. Sometimes with a shorter input, others need longer, but it had seemed universal. > See above: the machinery to try and prevent it exists, but it doesn't > always succeed. And it really can't be 100% reliable. So I'm unsure > what did you expect, and why. Honestly? I expect Emacs to not crash. The mechanics might be simple, or they might be complex but as a mere user I shouldn't be expected to know or care about the details. I expect evaluating lisp to not kill the editor - although I appreciate that executing unknown could code do all kinds of nasty things, from uploading my images to the internet, to running "rm -rf $HOME". The fine manual, in "54.2 When Is There a Bug", agrees. When paraphrased as "segfault == bug". > IOW: why would someone want to run such a silly "program"? In the real world? Nobody. It was just the first crash that came out of fuzz-testing. Perhaps there will be more subtle and interesting ones to report in the future when the fuzzer has ran for a few more days/weeks. Perhaps not. Either way I'd regard it as a bug that should be fixed, even if it is not a security hole, and not something that is going to surprise users in practice. Steve -- https://steve.fi/ ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-05 18:55 ` Steve Kemp @ 2017-07-05 19:47 ` Eli Zaretskii 2017-07-06 3:46 ` Steve Kemp ` (2 more replies) 0 siblings, 3 replies; 25+ messages in thread From: Eli Zaretskii @ 2017-07-05 19:47 UTC (permalink / raw) To: Steve Kemp; +Cc: 27585 > From: Steve Kemp <steve@steve.org.uk> > Date: Wed, 05 Jul 2017 18:55:31 +0000 > > > See above: the machinery to try and prevent it exists, but it doesn't > > always succeed. And it really can't be 100% reliable. So I'm unsure > > what did you expect, and why. > > Honestly? I expect Emacs to not crash. You wrote a program that triggers infinite recursion. Such programs will crash in most, if not all, languages. So your expectations are unrealistic. > I expect evaluating lisp to not kill the editor Valid Lisp, I agree. But yours isn't. Moreover, there are those among us (I'm not one of them) who thinks Emacs shouldn't even try to recover from stack overflow, they say it should crash hard right there and then. So your expectations are not necessarily shared, even as aspirations, by some developers. > > IOW: why would someone want to run such a silly "program"? > > In the real world? Nobody. Then why are we discussing this use case? Let's talk about more practical and interesting cases. ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-05 19:47 ` Eli Zaretskii @ 2017-07-06 3:46 ` Steve Kemp 2017-07-06 15:16 ` Eli Zaretskii 2017-07-06 6:46 ` Andreas Schwab 2017-07-06 15:52 ` Daniel Colascione 2 siblings, 1 reply; 25+ messages in thread From: Steve Kemp @ 2017-07-06 3:46 UTC (permalink / raw) To: 27585 > > I expect evaluating lisp to not kill the editor > > Valid Lisp, I agree. But yours isn't. Here we disagree. I enjoy reporting bugs when invalid things are tried, because I expect software to be robust, or as much as possible. If you feed invalid script to gawk, perl, emacs, etc, etc, I expect an error not a segfault. I appreciate there are often difficult cases, such as infinite recursion, division by zero, and memory exhaustion, but the idea that ones programming environment is free to crash if your code is wrong is .. unpleasant. > > In the real world? Nobody. > > Then why are we discussing this use case? Let's talk about > more practical and interesting cases. I read from this that I should not bother running any more fuzzing, after all if it does result in any crashes they're a result of bogus-coding that would never be hit in the real world. That's unfortunate, but I've no particular wish to argue in public. I will follow your suggestion. Bug left open because it crashes for me, if it fails to crash for others with a somewhat reasonable error message I guess that is good. Steve -- ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-06 3:46 ` Steve Kemp @ 2017-07-06 15:16 ` Eli Zaretskii 2017-07-06 15:33 ` Steve Kemp 0 siblings, 1 reply; 25+ messages in thread From: Eli Zaretskii @ 2017-07-06 15:16 UTC (permalink / raw) To: Steve Kemp; +Cc: 27585 > From: Steve Kemp <steve@steve.org.uk> > Date: Thu, 06 Jul 2017 03:46:35 +0000 > > I enjoy reporting bugs when invalid things are tried, because I > expect software to be robust, or as much as possible. If you feed > invalid script to gawk, perl, emacs, etc, etc, I expect an error > not a segfault. I enjoy seeing _any_ bugs reported about Emacs, because we want to make Emacs as robust as possible. Emacs tries very hard not to crash, but sometimes the techniques we use cannot work reliably. As in this case. There's a difference between "as robust as possible" and "100% robust", and expecting not to see segfault _at_all_ from a system with a full-fledged programming language built into it is unrealistic, especially when a program deliberately tries to cause Emacs to run out of memory. > I appreciate there are often difficult cases, such as infinite > recursion, division by zero, and memory exhaustion, but the idea > that ones programming environment is free to crash if your code > is wrong is .. unpleasant. Emacs is not a programming environment. Emacs is an editor and a text-processing environment with a built-in extension language. The extension language is provided for extending the editor, not for running arbitrary programs that have no relation to the editor. You can, of course, do the latter if you wish, but that is not the main use case for Emacs, and not the one for which it is optimized. Making such a marginal use case more important than it is will tax the much more important uses of Emacs as an editor and text-processing tool. Emacs is required not to crash when used in its main roles, or when it runs one of the packages provided with it. It should also try very hard not to crash in other cases as well, but it is not _required_ to do so, not at all costs anyway. What that means is that each crash should first be carefully analyzed in order to understand the underlying reasons and factors which led to the crash. Having found the reasons, if there are reasonable ways of resolving them to prevent the crash, that shall be done. A crash that happens during some use case that belongs to the main Emacs use patterns increases our motivation to seek for a solution, even if the solutions are hard to find or require complicated changes. Crashes outside of the patterns we care about don't produce such an added motivation, but are still solved if the solution is reasonably practical and doesn't adversely affects other important uses. I'm sorry I have to describe all this, which I have no doubt you understand very well. It's just that this discussion until now seems to somehow ignore these simple and clear-cut considerations, without which I feel the discussion loses its important context, and you somehow feel that this project is not interested in hearing about bugs, which is simply not true. > > > In the real world? Nobody. > > > > Then why are we discussing this use case? Let's talk about > > more practical and interesting cases. > > I read from this that I should not bother running any more > fuzzing, after all if it does result in any crashes they're a result > of bogus-coding that would never be hit in the real world. I suggested nothing of the kind. Fuzzing can uncover any number of problems of different nature. Each one of those should be analyzed first, before the decision is made whether it should be fixed and with what priority. I presume that the above is due to some offense you took from what I wrote, which is why I thought it was important to explain what I think should be the way of handling bug reports -- any bug reports -- submitted against Emacs. > That's unfortunate, but I've no particular wish to argue > in public. I will follow your suggestion. Once again, there was no suggestion from me that fuzzing will never uncover any bugs we will consider important to fix, or even unimportant but easy enough to fix. Each bug report is analyzed on its own right, and the decision whether to fix it and at what priority is made independently for each one of them. It doesn't matter what method was used to trigger the problem, the analysis and the conclusion consider the problem itself, not the method used to find it. In this case, Emacs already does everything we knew was possible with modern operating systems (and some of us think we do too much). Emacs tries to avoid stack overflow both on the Lisp level and on the C level, with some non-negligible degree of success. It is entirely clear to us that a cleverly constructed Lisp program could circumvent these defenses and cause a segfault anyway, but Emacs is not supposed to be a 100% safe environment for running such malicious programs; crashing for them is IMO way better than some other possible outcomes, like wiping out the filesystem or wedging the OS kernel. In sum, I hope you will continue trying to break Emacs and will report any "successes", so we could improve Emacs in the future. Thanks. ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-06 15:16 ` Eli Zaretskii @ 2017-07-06 15:33 ` Steve Kemp 2017-07-06 16:24 ` Eli Zaretskii 0 siblings, 1 reply; 25+ messages in thread From: Steve Kemp @ 2017-07-06 15:33 UTC (permalink / raw) To: 27585 > I presume that the above is due to some offense you > took from what I wrote, which is why I thought it was important to > explain what I think should be the way of handling bug reports -- any > bug reports -- submitted against Emacs. I appreciate the time you took to do so, but no, no offense was taken. I only thought stopping was sensible because my experience is that fuzzing tends to discover are things that are malformed, broken, and almost never the kind of things that a user would intend to do. In short your initial response to this particular case seems like it would apply to any similar issue which is liable to be discovered - they'd be genuine bugs, but they'd also be things that would never happen "in the wild", so while they wouldn't be ignored, it would be easy to push them to the back of the queue. > In sum, I hope you will continue trying to break Emacs and will report > any "successes", so we could improve Emacs in the future. THanks. I'm sitting on a couple of hundred crashing cases, just trying to simplify them and see if they share the same cause (they probably do). Steve -- https://steve.fi/ ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-06 15:33 ` Steve Kemp @ 2017-07-06 16:24 ` Eli Zaretskii 0 siblings, 0 replies; 25+ messages in thread From: Eli Zaretskii @ 2017-07-06 16:24 UTC (permalink / raw) To: Steve Kemp; +Cc: 27585 > From: Steve Kemp <steve@steve.org.uk> > Date: Thu, 06 Jul 2017 15:33:42 +0000 > > In short your initial response to this particular case seems > like it would apply to any similar issue which is liable to > be discovered - they'd be genuine bugs, but they'd also be things > that would never happen "in the wild", so while they wouldn't > be ignored, it would be easy to push them to the back of the queue. That wasn't my intent, and I apologize if my wording somehow implied that. I was only talking about the particular crash you reported. Any other crash should be analyzed separately, and the conclusion could very well be different. > THanks. I'm sitting on a couple of hundred crashing cases, just > trying to simplify them and see if they share the same cause (they > probably do). Well, I hope some of them are for different reasons. It is strange you cannot trigger the stack-overflow protection in your build, though. If you write a trivial infinite-recursion Lisp function, and then run it after lifting max-lisp-eval-depth and max-specpdl-size to the largest positive number, don't you see what I saw on my system? ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-05 19:47 ` Eli Zaretskii 2017-07-06 3:46 ` Steve Kemp @ 2017-07-06 6:46 ` Andreas Schwab 2017-07-06 15:19 ` Eli Zaretskii 2017-07-06 15:52 ` Daniel Colascione 2 siblings, 1 reply; 25+ messages in thread From: Andreas Schwab @ 2017-07-06 6:46 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Steve Kemp, 27585 On Jul 05 2017, Eli Zaretskii <eliz@gnu.org> wrote: > You wrote a program that triggers infinite recursion. This isn't infinite recursion since the input is finite. Andreas. -- Andreas Schwab, SUSE Labs, schwab@suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different." ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-06 6:46 ` Andreas Schwab @ 2017-07-06 15:19 ` Eli Zaretskii 2017-07-06 15:31 ` Andreas Schwab 0 siblings, 1 reply; 25+ messages in thread From: Eli Zaretskii @ 2017-07-06 15:19 UTC (permalink / raw) To: Andreas Schwab; +Cc: steve, 27585 > From: Andreas Schwab <schwab@suse.de> > Cc: Steve Kemp <steve@steve.org.uk>, 27585@debbugs.gnu.org > Date: Thu, 06 Jul 2017 08:46:14 +0200 > > On Jul 05 2017, Eli Zaretskii <eliz@gnu.org> wrote: > > > You wrote a program that triggers infinite recursion. > > This isn't infinite recursion since the input is finite. If we want to be pedantically accurate, then no "infinite" recursion is ever truly infinite, since it will always stop when the system is shut down, or the power fails, or the world ends, whichever happens first. So we are actually always talking about recursions deep enough to blow up the stack. ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-06 15:19 ` Eli Zaretskii @ 2017-07-06 15:31 ` Andreas Schwab 2017-07-06 15:37 ` Eli Zaretskii 0 siblings, 1 reply; 25+ messages in thread From: Andreas Schwab @ 2017-07-06 15:31 UTC (permalink / raw) To: Eli Zaretskii; +Cc: steve, 27585 On Jul 06 2017, Eli Zaretskii <eliz@gnu.org> wrote: >> From: Andreas Schwab <schwab@suse.de> >> Cc: Steve Kemp <steve@steve.org.uk>, 27585@debbugs.gnu.org >> Date: Thu, 06 Jul 2017 08:46:14 +0200 >> >> On Jul 05 2017, Eli Zaretskii <eliz@gnu.org> wrote: >> >> > You wrote a program that triggers infinite recursion. >> >> This isn't infinite recursion since the input is finite. > > If we want to be pedantically accurate, then no "infinite" recursion > is ever truly infinite, since it will always stop when the system is > shut down, or the power fails, or the world ends, whichever happens > first. This is not a useful way to categorize infinite recursion. In this case, the recursion is always bounded by the size of the input. Andreas. -- Andreas Schwab, SUSE Labs, schwab@suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different." ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-06 15:31 ` Andreas Schwab @ 2017-07-06 15:37 ` Eli Zaretskii 2017-07-06 15:41 ` Andreas Schwab 0 siblings, 1 reply; 25+ messages in thread From: Eli Zaretskii @ 2017-07-06 15:37 UTC (permalink / raw) To: Andreas Schwab; +Cc: steve, 27585 > From: Andreas Schwab <schwab@suse.de> > Cc: steve@steve.org.uk, 27585@debbugs.gnu.org > Date: Thu, 06 Jul 2017 17:31:35 +0200 > > > If we want to be pedantically accurate, then no "infinite" recursion > > is ever truly infinite, since it will always stop when the system is > > shut down, or the power fails, or the world ends, whichever happens > > first. > > This is not a useful way to categorize infinite recursion. Neither is this hair-splitting. ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-06 15:37 ` Eli Zaretskii @ 2017-07-06 15:41 ` Andreas Schwab 0 siblings, 0 replies; 25+ messages in thread From: Andreas Schwab @ 2017-07-06 15:41 UTC (permalink / raw) To: Eli Zaretskii; +Cc: steve, 27585 On Jul 06 2017, Eli Zaretskii <eliz@gnu.org> wrote: >> From: Andreas Schwab <schwab@suse.de> >> Cc: steve@steve.org.uk, 27585@debbugs.gnu.org >> Date: Thu, 06 Jul 2017 17:31:35 +0200 >> >> > If we want to be pedantically accurate, then no "infinite" recursion >> > is ever truly infinite, since it will always stop when the system is >> > shut down, or the power fails, or the world ends, whichever happens >> > first. >> >> This is not a useful way to categorize infinite recursion. > > Neither is this hair-splitting. Nothing of this is hair-splitting. Andreas. -- Andreas Schwab, SUSE Labs, schwab@suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different." ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-05 19:47 ` Eli Zaretskii 2017-07-06 3:46 ` Steve Kemp 2017-07-06 6:46 ` Andreas Schwab @ 2017-07-06 15:52 ` Daniel Colascione 2017-07-06 16:19 ` Eli Zaretskii 2 siblings, 1 reply; 25+ messages in thread From: Daniel Colascione @ 2017-07-06 15:52 UTC (permalink / raw) To: Eli Zaretskii, Steve Kemp; +Cc: 27585 On July 5, 2017 12:47:22 PM PDT, Eli Zaretskii <eliz@gnu.org> wrote: >> From: Steve Kemp <steve@steve.org.uk> >> Date: Wed, 05 Jul 2017 18:55:31 +0000 >> >> > See above: the machinery to try and prevent it exists, but it >doesn't >> > always succeed. And it really can't be 100% reliable. So I'm >unsure >> > what did you expect, and why. >> >> Honestly? I expect Emacs to not crash. > >You wrote a program that triggers infinite recursion. Such programs >will crash in most, if not all, languages. So your expectations are >unrealistic. > >> I expect evaluating lisp to not kill the editor > >Valid Lisp, I agree. But yours isn't. > >Moreover, there are those among us (I'm not one of them) who thinks >Emacs shouldn't even try to recover from stack overflow, they say it >should crash hard right there and then. Native stack? Certainly. The current approach, a signal handler that longjmps to top-level, cannot possibly work reliability, since it interrupts and abandons whatever the code is doing. If it has some kind of lock held and you try to take that lock again, you deadlock. Data structures might be in completely incoherent states. The last time we had this discussion, someone asserted that the worst that could happen might be a "memory leak". That's very wrong. This signal handler is a huge, ticking time bomb, and I completely turn it off in my Emacs. Everyone else should too. Recovering when elisp blows the stack is a different matter. > >So your expectations are not necessarily shared, even as aspirations, >by some developers. > >> > IOW: why would someone want to run such a silly "program"? >> >> In the real world? Nobody. > >Then why are we discussing this use case? Let's talk about >more practical and interesting cases. ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-06 15:52 ` Daniel Colascione @ 2017-07-06 16:19 ` Eli Zaretskii 2017-07-06 16:37 ` Daniel Colascione 0 siblings, 1 reply; 25+ messages in thread From: Eli Zaretskii @ 2017-07-06 16:19 UTC (permalink / raw) To: Daniel Colascione; +Cc: steve, 27585 > Date: Thu, 06 Jul 2017 08:52:44 -0700 > CC: 27585@debbugs.gnu.org > From: Daniel Colascione <dancol@dancol.org> > > >Moreover, there are those among us (I'm not one of them) who thinks > >Emacs shouldn't even try to recover from stack overflow, they say it > >should crash hard right there and then. > > Native stack? Certainly. Yes, this discussion is about the native stack, not the ELisp stack. > Recovering when elisp blows the stack is a different matter. I believe we already do that. ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-06 16:19 ` Eli Zaretskii @ 2017-07-06 16:37 ` Daniel Colascione 2017-07-06 17:27 ` Eli Zaretskii 0 siblings, 1 reply; 25+ messages in thread From: Daniel Colascione @ 2017-07-06 16:37 UTC (permalink / raw) To: Eli Zaretskii; +Cc: steve, 27585 On July 6, 2017 9:19:40 AM PDT, Eli Zaretskii <eliz@gnu.org> wrote: >> Date: Thu, 06 Jul 2017 08:52:44 -0700 >> CC: 27585@debbugs.gnu.org >> From: Daniel Colascione <dancol@dancol.org> >> >> >Moreover, there are those among us (I'm not one of them) who thinks >> >Emacs shouldn't even try to recover from stack overflow, they say it >> >should crash hard right there and then. >> >> Native stack? Certainly. > >Yes, this discussion is about the native stack, not the ELisp stack. Sort of --- an elisp file is driving the native code to blow its stack. I really don't think that any valid syntax should cause Emacs to segfault. In this instance, couldn't we add a hard threshold to limit recursion? > >> Recovering when elisp blows the stack is a different matter. > >I believe we already do that. We have a threshold. It's conservative, but it works most of the time. IMHO, explicit stack probing would be both less conservative and note robust. ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-06 16:37 ` Daniel Colascione @ 2017-07-06 17:27 ` Eli Zaretskii 0 siblings, 0 replies; 25+ messages in thread From: Eli Zaretskii @ 2017-07-06 17:27 UTC (permalink / raw) To: Daniel Colascione; +Cc: steve, 27585 > Date: Thu, 06 Jul 2017 09:37:30 -0700 > CC: steve@steve.org.uk,27585@debbugs.gnu.org > From: Daniel Colascione <dancol@dancol.org> > > In this instance, couldn't we add a hard threshold to limit recursion? I'm not sure I understand the proposal. Could you elaborate? > >> Recovering when elisp blows the stack is a different matter. > > > >I believe we already do that. > > We have a threshold. It's conservative, but it works most of the time. IMHO, explicit stack probing would be both less conservative and note robust. Won't it be expensive? Or maybe I don't have a clear idea what you meant by "stack probing". ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-05 18:41 ` Eli Zaretskii 2017-07-05 18:55 ` Steve Kemp @ 2017-07-06 15:48 ` Daniel Colascione 1 sibling, 0 replies; 25+ messages in thread From: Daniel Colascione @ 2017-07-06 15:48 UTC (permalink / raw) To: Eli Zaretskii, Steve Kemp; +Cc: 27585 On July 5, 2017 11:41:45 AM PDT, Eli Zaretskii <eliz@gnu.org> wrote: >> From: Steve Kemp <steve@steve.org.uk> >> Date: Wed, 05 Jul 2017 06:21:10 +0000 >> >> >> I've recently started fuzzing GNU Emacs, using the current git >sources. >> During the course of that work I stumbled upon this easily >reproduced bug: >> >> deagol ~ $ perl -e 'print "`" x ( 1024 * 1024 * 12);' > t.el >> deagol ~ $ /usr/bin/emacs --batch --script ./t.el >> .. >> Segmentation fault (core dumped) > >Here it says: > > Re-entering top level after C stack overflow > >and doesn't crash. > >> > Most likely just a stack overflow. >> >> Agreed, but still I think a segfault is unexpected and could be >> prevented. > >See above: the machinery to try and prevent it exists, but it doesn't >always succeed. And it really can't be 100% reliable. So I'm unsure >what did you expect, and why. Emacs generally gives you enough rope >to hang yourself; it's up to you not to be tempted to do so... This argument doesn't make sense to me. If we're happy letting elisp segfault, why bounds check AREF? Other managed runtimes --- Java, C# --- are perfectly capable of reliably detecting and recovering from stack exhaustion. There is absolutely no reason, aside from an implementation defect, for the elisp runtime not to do the same. Stack overflow detection could be made perfectly reliable. > >IOW: why would someone want to run such a silly "program"? ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-05 6:21 bug#27585: segfault when evaluating a file containing only backticks Steve Kemp 2017-07-05 7:51 ` Andreas Schwab 2017-07-05 18:41 ` Eli Zaretskii @ 2017-07-14 12:09 ` Paul Eggert 2017-07-14 13:30 ` Eli Zaretskii 2 siblings, 1 reply; 25+ messages in thread From: Paul Eggert @ 2017-07-14 12:09 UTC (permalink / raw) To: Steve Kemp; +Cc: 27585-done [-- Attachment #1: Type: text/plain, Size: 661 bytes --] Thanks for reporting the bug. I reproduced the problem on Fedora 26 x86-64, fixed it in master by applying the attached patch, and am boldly marking the bug as fixed. As Eli and Daniel mentioned, this area of Emacs cannot be 100% reliable and to some extent is indeed a "ticking time bomb". That being said, the problem in this particular case was that Emacs had a bad heuristic for guessing whether a segmentation violation address was due to stack overflow on GNU/Linux. This bad heuristic has been in place for years without anybody reporting it. It's good that we fixed this bug (though I hope "normal" users never notice the bug fix :-). [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-Improve-stack-overflow-heuristic-on-GNU-Linux.patch --] [-- Type: text/x-patch; name="0001-Improve-stack-overflow-heuristic-on-GNU-Linux.patch", Size: 5692 bytes --] From 9dee1c884eb50ba282eb9dd2495c5269add25963 Mon Sep 17 00:00:00 2001 From: Paul Eggert <eggert@cs.ucla.edu> 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; } -/* 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_Object *args, ptrdiff_t nargs) specpdl_ptr->bt.kind = SPECPDL_BACKTRACE; specpdl_ptr->bt.debug_on_exit = false; specpdl_ptr->bt.function = function; - specpdl_ptr->bt.args = args; + current_thread->stack_top = specpdl_ptr->bt.args = args; specpdl_ptr->bt.nargs = nargs; grow_specpdl (); 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 first_in_list) bool uninterned_symbol = false; bool multibyte; char stackbuf[MAX_ALLOCA]; + current_thread->stack_top = stackbuf; *pch = 0; 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 printcharfun, 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 = buf; maybe_quit (); /* 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 = stack_bottom; - char *top = near_C_stack_top (); + char *top = current_thread->stack_top; /* 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_set *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 = thread->stack_top; mark_specpdl (thread->m_specpdl, thread->m_specpdl_ptr); - mark_stack (thread->m_stack_bottom, thread->stack_top); + mark_stack (thread->m_stack_bottom, stack_top); - for (handler = thread->m_handlerlist; handler; handler = handler->next) + for (struct handler *handler = thread->m_handlerlist; + handler; handler = handler->next) { mark_object (handler->tag_or_ch); mark_object (handler->val); @@ -610,6 +611,7 @@ mark_one_thread (struct thread_state *thread) 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) - /* 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; struct catchtag *m_catchlist; #define catchlist (current_thread->m_catchlist) -- 2.7.4 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-14 12:09 ` Paul Eggert @ 2017-07-14 13:30 ` Eli Zaretskii 2017-07-15 5:03 ` Steve Kemp 0 siblings, 1 reply; 25+ messages in thread From: Eli Zaretskii @ 2017-07-14 13:30 UTC (permalink / raw) To: Paul Eggert; +Cc: steve, 27585 > From: Paul Eggert <eggert@cs.ucla.edu> > Date: Fri, 14 Jul 2017 05:09:34 -0700 > Cc: 27585-done@debbugs.gnu.org > > It's good that we fixed this bug (though I hope "normal" users never > notice the bug fix :-). Indeed, thanks. ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-14 13:30 ` Eli Zaretskii @ 2017-07-15 5:03 ` Steve Kemp 2017-07-15 5:12 ` Paul Eggert 0 siblings, 1 reply; 25+ messages in thread From: Steve Kemp @ 2017-07-15 5:03 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Paul Eggert, 27585 On Fri Jul 14, 2017 at 16:30:16 +0300, Eli Zaretskii wrote: > > It's good that we fixed this bug (though I hope "normal" users never > > notice the bug fix :-). > > Indeed, thanks. Thanks again. I do note one behaviour change though, which is perhaps worth noting. Previously this segfaulted: $ perl -e 'print "," x ( 1024 * 1024 * 12);' > t.el $ /tmp/emacs/bin/emacs -Q --batch --script ./t.el Now it does not, as the bug is fixed, but I'd expect the emacs process to terminate when the script is loaded. That doesn't happen though: $ /tmp/emacs/bin/emacs -Q --batch --script ./t.el Re-entering top level after C stack overflow [emacs still running] Compare that with the normal example: $ echo "(defun foo() "Test")" > t.el $ /tmp/emacs/bin/emacs -Q --batch --script ./t.el $ Perhaps not a huge problem, but it is a change I think? Steve -- https://steve.fi/ ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-15 5:03 ` Steve Kemp @ 2017-07-15 5:12 ` Paul Eggert 2017-07-15 7:15 ` Eli Zaretskii 0 siblings, 1 reply; 25+ messages in thread From: Paul Eggert @ 2017-07-15 5:12 UTC (permalink / raw) To: Steve Kemp, Eli Zaretskii; +Cc: 27585 Steve Kemp wrote: > $ /tmp/emacs/bin/emacs -Q --batch --script ./t.el > Re-entering top level after C stack overflow > [emacs still running] > > Compare that with the normal example: > > $ echo "(defun foo() "Test")" > t.el > $ /tmp/emacs/bin/emacs -Q --batch --script ./t.el > $ > > Perhaps not a huge problem, but it is a change I think? After a stack overflow, Emacs drops what it's doing and goes to the top level, regardless of its command-line arguments. Perhaps it would be better if Emacs did something else for this particular case. It's low priority, though. ^ permalink raw reply [flat|nested] 25+ messages in thread
* bug#27585: segfault when evaluating a file containing only backticks 2017-07-15 5:12 ` Paul Eggert @ 2017-07-15 7:15 ` Eli Zaretskii 0 siblings, 0 replies; 25+ messages in thread From: Eli Zaretskii @ 2017-07-15 7:15 UTC (permalink / raw) To: Paul Eggert; +Cc: steve, 27585 > Cc: 27585@debbugs.gnu.org > From: Paul Eggert <eggert@cs.ucla.edu> > Date: Fri, 14 Jul 2017 22:12:08 -0700 > > Steve Kemp wrote: > > $ /tmp/emacs/bin/emacs -Q --batch --script ./t.el > > Re-entering top level after C stack overflow > > [emacs still running] > > > > Compare that with the normal example: > > > > $ echo "(defun foo() "Test")" > t.el > > $ /tmp/emacs/bin/emacs -Q --batch --script ./t.el > > $ > > > > Perhaps not a huge problem, but it is a change I think? > > After a stack overflow, Emacs drops what it's doing and goes to the top level, > regardless of its command-line arguments. Perhaps it would be better if Emacs > did something else for this particular case. It's low priority, though. I think the idea is to let the user do whatever is necessary to end the session as quickly as possible. Granted, it is optimized for interactive usage, since the goal of the stack-overflow protection is to avoid losing unrelated edits due to some code that's gone awry, and that makes little sense in non-interactive sessions. So batch invocations might indeed do something else, like exit. I agree that the priority is not too high, because again, stack overflow is most harmful in interactive sessions. ^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2017-07-15 7:15 UTC | newest] Thread overview: 25+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-07-05 6:21 bug#27585: segfault when evaluating a file containing only backticks Steve Kemp 2017-07-05 7:51 ` Andreas Schwab 2017-07-05 8:26 ` Steve Kemp 2017-07-05 18:41 ` Eli Zaretskii 2017-07-05 18:55 ` Steve Kemp 2017-07-05 19:47 ` Eli Zaretskii 2017-07-06 3:46 ` Steve Kemp 2017-07-06 15:16 ` Eli Zaretskii 2017-07-06 15:33 ` Steve Kemp 2017-07-06 16:24 ` Eli Zaretskii 2017-07-06 6:46 ` Andreas Schwab 2017-07-06 15:19 ` Eli Zaretskii 2017-07-06 15:31 ` Andreas Schwab 2017-07-06 15:37 ` Eli Zaretskii 2017-07-06 15:41 ` Andreas Schwab 2017-07-06 15:52 ` Daniel Colascione 2017-07-06 16:19 ` Eli Zaretskii 2017-07-06 16:37 ` Daniel Colascione 2017-07-06 17:27 ` Eli Zaretskii 2017-07-06 15:48 ` Daniel Colascione 2017-07-14 12:09 ` Paul Eggert 2017-07-14 13:30 ` Eli Zaretskii 2017-07-15 5:03 ` Steve Kemp 2017-07-15 5:12 ` Paul Eggert 2017-07-15 7:15 ` Eli Zaretskii
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).