aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2016-05-27 13:39:34 -0700
committerPaul Eggert2016-05-27 13:41:22 -0700
commit9d356f62b3c24d9f2b2bc3831cf19e8351860a86 (patch)
tree97241f72d0825ca2de1a203da2b9edec2a064af8 /src
parent168163434678dcc030d1e2844765ddae7b555721 (diff)
downloademacs-9d356f62b3c24d9f2b2bc3831cf19e8351860a86.tar.gz
emacs-9d356f62b3c24d9f2b2bc3831cf19e8351860a86.zip
Robustify stack-size calculation
* src/emacs.c: Include getpagesize.h. (main): Check for integer overflow when computing stack size. Round new rlim_cur to pagesize boundary on all platforms, as this is easy and would have prevented Bug#23622. If setrlimit fails, use current limit to determine re_max_failures.
Diffstat (limited to 'src')
-rw-r--r--src/emacs.c69
1 files changed, 40 insertions, 29 deletions
diff --git a/src/emacs.c b/src/emacs.c
index 3e0cf596402..bdcebbe1637 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -91,6 +91,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
91#include "systime.h" 91#include "systime.h"
92#include "puresize.h" 92#include "puresize.h"
93 93
94#include "getpagesize.h"
94#include "gnutls.h" 95#include "gnutls.h"
95 96
96#if (defined PROFILING \ 97#if (defined PROFILING \
@@ -672,9 +673,6 @@ main (int argc, char **argv)
672 bool do_initial_setlocale; 673 bool do_initial_setlocale;
673 bool dumping; 674 bool dumping;
674 int skip_args = 0; 675 int skip_args = 0;
675#ifdef HAVE_SETRLIMIT
676 struct rlimit rlim;
677#endif
678 bool no_loadup = 0; 676 bool no_loadup = 0;
679 char *junk = 0; 677 char *junk = 0;
680 char *dname_arg = 0; 678 char *dname_arg = 0;
@@ -825,38 +823,51 @@ main (int argc, char **argv)
825 is built with an 8MB stack. Moreover, the setrlimit call can 823 is built with an 8MB stack. Moreover, the setrlimit call can
826 cause problems on Cygwin 824 cause problems on Cygwin
827 (https://www.cygwin.com/ml/cygwin/2015-07/msg00096.html). */ 825 (https://www.cygwin.com/ml/cygwin/2015-07/msg00096.html). */
828 if (1 826 struct rlimit rlim;
829#ifndef CANNOT_DUMP 827 if (getrlimit (RLIMIT_STACK, &rlim) == 0
830 && (!noninteractive || initialized) 828 && 0 <= rlim.rlim_cur && rlim.rlim_cur <= LONG_MAX)
831#endif
832 && !getrlimit (RLIMIT_STACK, &rlim))
833 { 829 {
834 long newlim; 830 long lim = rlim.rlim_cur;
835 /* Approximate the amount regex.c needs per unit of re_max_failures. */ 831
832 /* Approximate the amount regex.c needs per unit of
833 re_max_failures, then add 33% to cover the size of the
834 smaller stacks that regex.c successively allocates and
835 discards on its way to the maximum. */
836 int ratio = 20 * sizeof (char *); 836 int ratio = 20 * sizeof (char *);
837 /* Then add 33% to cover the size of the smaller stacks that regex.c
838 successively allocates and discards, on its way to the maximum. */
839 ratio += ratio / 3; 837 ratio += ratio / 3;
840 /* Add in some extra to cover 838
841 what we're likely to use for other reasons. */ 839 /* Extra space to cover what we're likely to use for other reasons. */
842 newlim = re_max_failures * ratio + 200000; 840 int extra = 200000;
843#ifdef __NetBSD__ 841
844 /* NetBSD (at least NetBSD 1.2G and former) has a bug in its 842 bool try_to_grow_stack = true;
845 stack allocation routine for new process that the allocation 843#ifndef CANNOT_DUMP
846 fails if stack limit is not on page boundary. So, round up the 844 try_to_grow_stack = !noninteractive || initialized;
847 new limit to page boundary. */ 845#endif
848 newlim = (newlim + getpagesize () - 1) / getpagesize () * getpagesize (); 846
849#endif 847 if (try_to_grow_stack)
850 if (newlim > rlim.rlim_max)
851 { 848 {
852 newlim = rlim.rlim_max; 849 long newlim = re_max_failures * ratio + extra;
853 /* Don't let regex.c overflow the stack we have. */ 850
854 re_max_failures = (newlim - 200000) / ratio; 851 /* Round the new limit to a page boundary; this is needed
852 for Darwin kernel 15.4.0 (see Bug#23622) and perhaps
853 other systems. Do not shrink the stack and do not exceed
854 rlim_max. Don't worry about values like RLIM_INFINITY
855 since in practice they are so large that the code does
856 the right thing anyway. */
857 long pagesize = getpagesize ();
858 newlim = min (newlim + pagesize - 1, rlim.rlim_max);
859 newlim -= newlim % pagesize;
860
861 if (pagesize <= newlim - lim)
862 {
863 rlim.rlim_cur = newlim;
864 if (setrlimit (RLIMIT_STACK, &rlim) == 0)
865 lim = newlim;
866 }
855 } 867 }
856 if (rlim.rlim_cur < newlim)
857 rlim.rlim_cur = newlim;
858 868
859 setrlimit (RLIMIT_STACK, &rlim); 869 /* Don't let regex.c overflow the stack. */
870 re_max_failures = lim < extra ? 0 : min (lim - extra, SIZE_MAX) / ratio;
860 } 871 }
861#endif /* HAVE_SETRLIMIT and RLIMIT_STACK and not CYGWIN */ 872#endif /* HAVE_SETRLIMIT and RLIMIT_STACK and not CYGWIN */
862 873