commit 3e71e4379ce7b53afe51ead4c94e6bb016bc6e7a (HEAD, refs/remotes/origin/master) Author: Paul Eggert Date: Wed Jul 20 10:31:33 2016 +0200 Work around GCC bug 54561 in a better way The new approach is less selective, but also less intrusive on C code. * src/bytecode.c, src/image.c, src/keyboard.c: Ignore -Wclobbered. * src/conf_post.h (NONVOLATILE): Remove. All uses removed. diff --git a/src/bytecode.c b/src/bytecode.c index bb7922d..1b02c60 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -32,6 +32,11 @@ along with GNU Emacs. If not, see . */ #include "xterm.h" #endif +/* Work around GCC bug 54561. */ +#if GNUC_PREREQ (4, 3, 0) +# pragma GCC diagnostic ignored "-Wclobbered" +#endif + /* * define BYTE_CODE_SAFE to enable some minor sanity checking (useful for * debugging the byte compiler...) diff --git a/src/conf_post.h b/src/conf_post.h index 99aafbf..865d018 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -368,15 +368,6 @@ extern int emacs_setenv_TZ (char const *); # define FLEXIBLE_ARRAY_MEMBER #endif -/* When used in place of 'volatile', 'NONVOLATILE' is equivalent to nothing, - except it cajoles GCC into not warning incorrectly that a variable needs to - be volatile. This works around GCC bug 54561. */ -#if defined GCC_LINT || defined lint -# define NONVOLATILE volatile -#else -# define NONVOLATILE /* empty */ -#endif - /* 'int x UNINIT;' is equivalent to 'int x;', except it cajoles GCC into not warning incorrectly about use of an uninitialized variable. */ #if defined GCC_LINT || defined lint diff --git a/src/image.c b/src/image.c index 572557d..1770de7 100644 --- a/src/image.c +++ b/src/image.c @@ -56,6 +56,11 @@ along with GNU Emacs. If not, see . */ #include TERM_HEADER #endif /* HAVE_WINDOW_SYSTEM */ +/* Work around GCC bug 54561. */ +#if GNUC_PREREQ (4, 3, 0) +# pragma GCC diagnostic ignored "-Wclobbered" +#endif + #ifdef HAVE_X_WINDOWS typedef struct x_bitmap_record Bitmap_Record; #define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y) @@ -5897,9 +5902,8 @@ struct png_load_context static bool png_load_body (struct frame *f, struct image *img, struct png_load_context *c) { - Lisp_Object specified_file; - Lisp_Object NONVOLATILE specified_data; - FILE *NONVOLATILE fp = NULL; + Lisp_Object specified_file, specified_data; + FILE *fp = NULL; int x, y; ptrdiff_t i; png_struct *png_ptr; @@ -6669,8 +6673,7 @@ static bool jpeg_load_body (struct frame *f, struct image *img, struct my_jpeg_error_mgr *mgr) { - Lisp_Object specified_file; - Lisp_Object NONVOLATILE specified_data; + Lisp_Object specified_file, specified_data; FILE *volatile fp = NULL; JSAMPARRAY buffer; int row_stride, x, y; diff --git a/src/keyboard.c b/src/keyboard.c index 653f527..8901ff0 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -70,6 +70,11 @@ along with GNU Emacs. If not, see . */ #include TERM_HEADER #endif /* HAVE_WINDOW_SYSTEM */ +/* Work around GCC bug 54561. */ +#if GNUC_PREREQ (4, 3, 0) +# pragma GCC diagnostic ignored "-Wclobbered" +#endif + /* Variables for blockinput.h: */ /* Positive if interrupt input is blocked right now. */ @@ -2320,7 +2325,7 @@ read_char (int commandflag, Lisp_Object map, Lisp_Object prev_event, bool *used_mouse_menu, struct timespec *end_time) { - Lisp_Object NONVOLATILE c; + Lisp_Object c; ptrdiff_t jmpcount; sys_jmp_buf local_getcjmp; sys_jmp_buf save_jump; commit 63750fd4ed4ff8bb9b3ff8868d4e36e3422adb21 Author: Paul Eggert Date: Wed Jul 20 09:16:49 2016 +0200 Fix port to glibc 2.24 (pre-release) + ppc64 * src/callproc.c (child_setup): Use emacs_exec_file so that ASLR is enabled in the child process. * src/emacs.c: Move some personality details into sys/sysdep.c. Do not include . (main): Disable ASLR earlier, so that we don’t chdir twice. * src/lisp.h (disable_address_randomization): New decl. * src/sysdep.c (disable_address_randomization) [HAVE_PERSONALITY_ADDR_NO_RANDOMIZE]: Move personality details here from emacs.c. (emacs_exec_file): New function. diff --git a/src/callproc.c b/src/callproc.c index 9ec7893..487115d 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -1317,8 +1317,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, setpgid (0, 0); tcsetpgrp (0, pid); - execve (new_argv[0], new_argv, env); - exec_failed (new_argv[0], errno); + int errnum = emacs_exec_file (new_argv[0], new_argv, env); + exec_failed (new_argv[0], errnum); #else /* MSDOS */ pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env); diff --git a/src/emacs.c b/src/emacs.c index fa7ec01..53bcc98 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -112,10 +112,6 @@ extern void moncontrol (int mode); #include #endif -#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE -#include -#endif - static const char emacs_version[] = PACKAGE_VERSION; static const char emacs_copyright[] = COPYRIGHT; static const char emacs_bugreport[] = PACKAGE_BUGREPORT; @@ -685,6 +681,30 @@ main (int argc, char **argv) stack_base = &dummy; + dumping = !initialized && (strcmp (argv[argc - 1], "dump") == 0 + || strcmp (argv[argc - 1], "bootstrap") == 0); + + /* True if address randomization interferes with memory allocaiton. */ +# ifdef __PPC64__ + bool disable_aslr = true; +# else + bool disable_aslr = dumping; +# endif + + if (disable_aslr && disable_address_randomization ()) + { + /* Set this so the personality will be reverted before execs + after this one. */ + xputenv ("EMACS_HEAP_EXEC=true"); + + /* Address randomization was enabled, but is now disabled. + Re-execute Emacs to get a clean slate. */ + execvp (argv[0], argv); + + /* If the exec fails, warn and then try anyway. */ + perror (argv[0]); + } + #ifndef CANNOT_DUMP might_dump = !initialized; #endif @@ -793,26 +813,6 @@ main (int argc, char **argv) } } - dumping = !initialized && (strcmp (argv[argc - 1], "dump") == 0 - || strcmp (argv[argc - 1], "bootstrap") == 0); - -#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE - if (dumping) - { - int pers = personality (0xffffffff); - if (! (pers & ADDR_NO_RANDOMIZE) - && 0 <= personality (pers | ADDR_NO_RANDOMIZE)) - { - /* Address randomization was enabled, but is now disabled. - Re-execute Emacs to get a clean slate. */ - execvp (argv[0], argv); - - /* If the exec fails, warn and then try without a clean slate. */ - perror (argv[0]); - } - } -#endif - #if defined (HAVE_SETRLIMIT) && defined (RLIMIT_STACK) && !defined (CYGWIN) /* Extend the stack space available. Don't do that if dumping, since some systems (e.g. DJGPP) might define a smaller stack diff --git a/src/lisp.h b/src/lisp.h index 48c2728..39877d7 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4261,6 +4261,12 @@ struct tty_display_info; struct terminal; /* Defined in sysdep.c. */ +#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE +extern bool disable_address_randomization (void); +#else +INLINE bool disable_address_randomization (void) { return false; } +#endif +extern int emacs_exec_file (char const *, char *const *, char *const *); extern void init_standard_fds (void); extern char *emacs_get_current_dir_name (void); extern void stuff_char (char c); diff --git a/src/sysdep.c b/src/sysdep.c index 56142a5..1654173 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -129,6 +129,48 @@ static const int baud_convert[] = 1800, 2400, 4800, 9600, 19200, 38400 }; +#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE +# include + +/* Disable address randomization in the current process. Return true + if addresses were randomized but this has been disabled, false + otherwise. */ +bool +disable_address_randomization (void) +{ + bool disabled = false; + int pers = personality (0xffffffff); + disabled = (! (pers & ADDR_NO_RANDOMIZE) + && 0 <= personality (pers | ADDR_NO_RANDOMIZE)); + return disabled; +} +#endif + +/* Execute the program in FILE, with argument vector ARGV and environ + ENVP. Return an error number if unsuccessful. This is like execve + except it reenables ASLR in the executed program if necessary, and + on error it returns an error number rather than -1. */ +int +emacs_exec_file (char const *file, char *const *argv, char *const *envp) +{ +#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE + int pers = getenv ("EMACS_HEAP_EXEC") ? personality (0xffffffff) : -1; + bool change_personality = 0 <= pers && pers & ADDR_NO_RANDOMIZE; + if (change_personality) + personality (pers & ~ADDR_NO_RANDOMIZE); +#endif + + execve (file, argv, envp); + int err = errno; + +#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE + if (change_personality) + personality (pers); +#endif + + return err; +} + /* If FD is not already open, arrange for it to be open with FLAGS. */ static void force_open (int fd, int flags) commit bf5ddded70c11edaf3514b25da27fc71cfb8e965 Author: Alan Third Date: Sun Jul 17 14:44:52 2016 +0100 Prevent bar cursor overwriting next glyph (bug#16856) * src/nsterm.m (ns_draw_window_cursor): Test glyph width vs cursor width before setting final size. diff --git a/src/nsterm.m b/src/nsterm.m index a6160ed..8da2ffe 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -2861,7 +2861,10 @@ Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. { if (cursor_width < 1) cursor_width = max (FRAME_CURSOR_WIDTH (f), 1); - w->phys_cursor_width = cursor_width; + + /* The bar cursor should never be wider than the glyph. */ + if (cursor_width < w->phys_cursor_width) + w->phys_cursor_width = cursor_width; } /* If we have an HBAR, "cursor_width" MAY specify height. */ else if (cursor_type == HBAR_CURSOR) commit a80ee12a64ed84f1e4f69acb1cd54a1814c9517d Author: Paul Eggert Date: Tue Jul 19 18:51:46 2016 +0200 ; Spelling fix diff --git a/src/callproc.c b/src/callproc.c index e8d089c..9ec7893 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -1375,7 +1375,7 @@ getenv_internal (const char *var, ptrdiff_t varlen, char **value, Vprocess_environment)) return *value ? 1 : 0; - /* On Windows we make some modifications to Emacs' enviroment + /* On Windows we make some modifications to Emacs' environment without recording them in Vprocess_environment. */ #ifdef WINDOWSNT { commit 00b6647651e4276ac5c47aa33e0fec6726469bc7 Author: Eli Zaretskii Date: Tue Jul 19 18:59:41 2016 +0300 Fix 'transpose-regions' when LEAVE-MARKERS arg is non-nil * src/insdel.c (adjust_markers_bytepos): New function. * src/lisp.h (adjust_markers_bytepos): Add prototype. * src/insdel.c (replace_range, replace_range_2): * src/editfns.c (Ftranspose_regions): Call adjust_markers_bytepos. (Bug#5131) * test/src/editfns-tests.el (transpose-test-reverse-word) (transpose-test-get-byte-positions): New functions. (transpose-ascii-regions-test) (transpose-nonascii-regions-test-1) (transpose-nonascii-regions-test-2): New tests. diff --git a/src/editfns.c b/src/editfns.c index 4c8336b..aed884e 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -5058,6 +5058,14 @@ Transposing beyond buffer boundaries is an error. */) start2_byte, start2_byte + len2_byte); fix_start_end_in_overlays (start1, end2); } + else + { + /* The character positions of the markers remain intact, but we + still need to update their byte positions, because the + transposed regions might include multibyte sequences which + make some original byte positions of the markers invalid. */ + adjust_markers_bytepos (start1, start1_byte, end2, end2_byte, 0); + } signal_after_change (start1, end2 - start1, end2 - start1); return Qnil; diff --git a/src/insdel.c b/src/insdel.c index 4ad1074..ec7bbb3 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -364,6 +364,78 @@ adjust_markers_for_replace (ptrdiff_t from, ptrdiff_t from_byte, check_markers (); } +/* Starting at POS (BYTEPOS), find the byte position corresponding to + ENDPOS, which could be either before or after POS. */ +static ptrdiff_t +count_bytes (ptrdiff_t pos, ptrdiff_t bytepos, ptrdiff_t endpos) +{ + eassert (BEG_BYTE <= bytepos && bytepos <= Z_BYTE + && BEG <= endpos && endpos <= Z); + + if (pos <= endpos) + for ( ; pos < endpos; pos++) + INC_POS (bytepos); + else + for ( ; pos > endpos; pos--) + DEC_POS (bytepos); + + return bytepos; +} + +/* Adjust byte positions of markers when their character positions + didn't change. This is used in several places that replace text, + but keep the character positions of the markers unchanged -- the + byte positions could still change due to different numbers of bytes + in the new text. + + FROM (FROM_BYTE) and TO (TO_BYTE) specify the region of text where + changes have been done. TO_Z, if non-zero, means all the markers + whose positions are after TO should also be adjusted. */ +void +adjust_markers_bytepos (ptrdiff_t from, ptrdiff_t from_byte, + ptrdiff_t to, ptrdiff_t to_byte, int to_z) +{ + register struct Lisp_Marker *m; + ptrdiff_t beg = from, begbyte = from_byte; + + adjust_suspend_auto_hscroll (from, to); + + if (Z == Z_BYTE || (!to_z && to == to_byte)) + { + /* Make sure each affected marker's bytepos is equal to + its charpos. */ + for (m = BUF_MARKERS (current_buffer); m; m = m->next) + { + if (m->bytepos > from_byte + && (to_z || m->bytepos <= to_byte)) + m->bytepos = m->charpos; + } + } + else + { + for (m = BUF_MARKERS (current_buffer); m; m = m->next) + { + /* Recompute each affected marker's bytepos. */ + if (m->bytepos > from_byte + && (to_z || m->bytepos <= to_byte)) + { + if (m->charpos < beg + && beg - m->charpos > m->charpos - from) + { + beg = from; + begbyte = from_byte; + } + m->bytepos = count_bytes (beg, begbyte, m->charpos); + beg = m->charpos; + begbyte = m->bytepos; + } + } + } + + /* Make sure cached charpos/bytepos is invalid. */ + clear_charpos_cache (current_buffer); +} + void buffer_overflow (void) @@ -1397,6 +1469,16 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new, if (markers) adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del, inschars, outgoing_insbytes); + else + { + /* The character positions of the markers remain intact, but we + still need to update their byte positions, because the + deleted and the inserted text might have multibyte sequences + which make the original byte positions of the markers + invalid. */ + adjust_markers_bytepos (from, from_byte, from + inschars, + from_byte + outgoing_insbytes, 1); + } /* Adjust the overlay center as needed. This must be done after adjusting the markers that bound the overlays. */ @@ -1509,10 +1591,22 @@ replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte, eassert (GPT <= GPT_BYTE); /* Adjust markers for the deletion and the insertion. */ - if (markers - && ! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes)) - adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del, - inschars, insbytes); + if (! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes)) + { + if (markers) + adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del, + inschars, insbytes); + else + { + /* The character positions of the markers remain intact, but + we still need to update their byte positions, because the + deleted and the inserted text might have multibyte + sequences which make the original byte positions of the + markers invalid. */ + adjust_markers_bytepos (from, from_byte, from + inschars, + from_byte + insbytes, 1); + } + } /* Adjust the overlay center as needed. This must be done after adjusting the markers that bound the overlays. */ diff --git a/src/lisp.h b/src/lisp.h index e0eb52a..48c2728 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3528,6 +3528,8 @@ extern void adjust_after_insert (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t); extern void adjust_markers_for_delete (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t); +extern void adjust_markers_bytepos (ptrdiff_t, ptrdiff_t, + ptrdiff_t, ptrdiff_t, int); extern void replace_range (ptrdiff_t, ptrdiff_t, Lisp_Object, bool, bool, bool); extern void replace_range_2 (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, const char *, ptrdiff_t, ptrdiff_t, bool); diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index 507ceef..2f90d1e 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -89,3 +89,48 @@ (propertize "23" 'face 'underline) (propertize "45" 'face 'italic))) #("012345 " 0 2 (face bold) 2 4 (face underline) 4 10 (face italic))))) + +;; Tests for bug#5131. +(defun transpose-test-reverse-word (start end) + "Reverse characters in a word by transposing pairs of characters." + (let ((begm (make-marker)) + (endm (make-marker))) + (set-marker begm start) + (set-marker endm end) + (while (> endm begm) + (progn (transpose-regions begm (1+ begm) endm (1+ endm) t) + (set-marker begm (1+ begm)) + (set-marker endm (1- endm)))))) + +(defun transpose-test-get-byte-positions (len) + "Validate character position to byte position translation." + (let ((bytes '())) + (dotimes (pos len) + (setq bytes (add-to-list 'bytes (position-bytes (1+ pos)) t))) + bytes)) + +(ert-deftest transpose-ascii-regions-test () + (with-temp-buffer + (erase-buffer) + (insert "abcd") + (transpose-test-reverse-word 1 4) + (should (string= (buffer-string) "dcba")) + (should (equal (transpose-test-get-byte-positions 5) '(1 2 3 4 5))))) + +(ert-deftest transpose-nonascii-regions-test-1 () + (with-temp-buffer + (erase-buffer) + (insert "÷bcd") + (transpose-test-reverse-word 1 4) + (should (string= (buffer-string) "dcb÷")) + (should (equal (transpose-test-get-byte-positions 5) '(1 2 3 4 6))))) + +(ert-deftest transpose-nonascii-regions-test-2 () + (with-temp-buffer + (erase-buffer) + (insert "÷ab\"äé") + (transpose-test-reverse-word 1 6) + (should (string= (buffer-string) "éä\"ba÷")) + (should (equal (transpose-test-get-byte-positions 7) '(1 3 5 6 7 8 10))))) + +;;; editfns-tests.el ends here