Subject: Crash when Nformat was called with a loooooong format string specified
From: Michelle Gilliland <[email-masked]>
To: [email-masked]
Date: Mon, 11 May 2015 22:48:07 +0800
List-Id: <debbugs-submit.debbugs.gnu.org>

Emacs terminates abnormally with SIGSEGV when format function was called with a loooooong format string specified. Here is the backtrace:

~/documents $ gdb ../bin/emacs24/bin/emacs core.emacs.21473.1431355113
GNU gdb Red Hat Linux (6.3.0.0-1.96rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu"...Using host libthread_db library "/lib64/tls/libthread_db.so.1".

Reading symbols from shared object read from target memory...done.
Loaded system supplied DSO at 0x7fffb19f6000
Core was generated by `../bin/emacs24/bin/emacs emacs-24.5/src/keyboard.c'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/X11R6/lib64/libSM.so.6...done.
Loaded symbols for /usr/X11R6/lib64/libSM.so.6
Reading symbols from /usr/X11R6/lib64/libICE.so.6...done.
Loaded symbols for /usr/X11R6/lib64/libICE.so.6
Reading symbols from /usr/X11R6/lib64/libX11.so.6...done.
Loaded symbols for /usr/X11R6/lib64/libX11.so.6
Reading symbols from /usr/X11R6/lib64/libXrender.so.1...done.
Loaded symbols for /usr/X11R6/lib64/libXrender.so.1
Reading symbols from /usr/X11R6/lib64/libXft.so.2...done.
Loaded symbols for /usr/X11R6/lib64/libXft.so.2
Reading symbols from /usr/lib64/libfreetype.so.6...done.
Loaded symbols for /usr/lib64/libfreetype.so.6
Reading symbols from /usr/lib64/libfontconfig.so.1...done.
Loaded symbols for /usr/lib64/libfontconfig.so.1
Reading symbols from /lib64/libacl.so.1...done.
Loaded symbols for /lib64/libacl.so.1
Reading symbols from /lib64/tls/librt.so.1...done.
Loaded symbols for /lib64/tls/librt.so.1
Reading symbols from /usr/X11R6/lib64/libXinerama.so.1...done.
Loaded symbols for /usr/X11R6/lib64/libXinerama.so.1
Reading symbols from /usr/lib64/libgpm.so.1...done.
Loaded symbols for /usr/lib64/libgpm.so.1
Reading symbols from /usr/lib64/libncurses.so.5...done.
Loaded symbols for /usr/lib64/libncurses.so.5
Reading symbols from /lib64/libselinux.so.1...done.
Loaded symbols for /lib64/libselinux.so.1
Reading symbols from /usr/lib64/libz.so.1...done.
Loaded symbols for /usr/lib64/libz.so.1
Reading symbols from /lib64/tls/libpthread.so.0...done.
Loaded symbols for /lib64/tls/libpthread.so.0
Reading symbols from /lib64/tls/libm.so.6...done.
Loaded symbols for /lib64/tls/libm.so.6
Reading symbols from /lib64/tls/libc.so.6...done.
Loaded symbols for /lib64/tls/libc.so.6
Reading symbols from /lib64/libdl.so.2...done.
Loaded symbols for /lib64/libdl.so.2
Reading symbols from /usr/X11R6/lib64/libXext.so.6...done.
Loaded symbols for /usr/X11R6/lib64/libXext.so.6
Reading symbols from /usr/lib64/libexpat.so.0...done.
Loaded symbols for /usr/lib64/libexpat.so.0
Reading symbols from /lib64/libattr.so.1...done.
Loaded symbols for /lib64/libattr.so.1
Reading symbols from /lib64/ld-linux-x86-64.so.2...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Reading symbols from /lib64/libnss_files.so.2...done.
Loaded symbols for /lib64/libnss_files.so.2
Reading symbols from /lib64/libgcc_s.so.1...done.
Loaded symbols for /lib64/libgcc_s.so.1
#0  0x0000003f0b90c2be in raise () from /lib64/tls/libpthread.so.0
(gdb) bt
#0  0x0000003f0b90c2be in raise () from /lib64/tls/libpthread.so.0
#1  0x00000000004cbe2d in terminate_due_to_signal (sig=11, backtrace_limit=40) at emacs.c:376
#2  0x00000000004e6efe in handle_fatal_signal (sig=Variable "sig" is not available.) at sysdep.c:1630
#3  0x00000000004e67d0 in deliver_thread_signal (sig=11, handler=0x4e6ef0 <handle_fatal_signal>) at sysdep.c:1604
#4  <signal handler called>
#5  0x000000000053a036 in Fformat (nargs=1, args=0x7fffb19238a0) at editfns.c:4291
#6  0x00000000005411d8 in Ffuncall (nargs=Variable "nargs" is not available.) at lisp.h:913
#7  0x00000000005416a3 in Fapply (nargs=2, args=0x7fffb1923898) at eval.c:2297
#8  0x00000000005411d8 in Ffuncall (nargs=Variable "nargs" is not available.) at lisp.h:913
#9  0x00000000005747d8 in exec_byte_code (bytestr=Variable "bytestr" is not available.) at bytecode.c:916
#10 0x0000000000540f43 in Ffuncall (nargs=Variable "nargs" is not available.) at eval.c:2872
#11 0x00000000005747d8 in exec_byte_code (bytestr=Variable "bytestr" is not available.) at bytecode.c:916
#12 0x0000000000540aca in funcall_lambda (fun=20971805, nargs=1, arg_vector=0x7fffb1923b38) at lisp.h:1355
#13 0x0000000000540f43 in Ffuncall (nargs=Variable "nargs" is not available.) at eval.c:2872
#14 0x000000000054039f in eval_sub (form=Variable "form" is not available.) at lisp.h:913
#15 0x0000000000541bee in internal_lisp_condition_case (var=18706882, bodyform=17745174, handlers=Variable "handlers" is not available.) at eval.c:1317
#16 0x000000000057524d in exec_byte_code (bytestr=Variable "bytestr" is not available.) at bytecode.c:1162
#17 0x0000000000540aca in funcall_lambda (fun=20840245, nargs=2, arg_vector=0x7fffb1923e50) at lisp.h:1355
#18 0x0000000000540f43 in Ffuncall (nargs=Variable "nargs" is not available.) at eval.c:2872
#19 0x00000000005747d8 in exec_byte_code (bytestr=Variable "bytestr" is not available.) at bytecode.c:916
#20 0x0000000000540275 in eval_sub (form=Variable "form" is not available.) at lisp.h:913
#21 0x0000000000541bee in internal_lisp_condition_case (var=18706882, bodyform=17831366, handlers=Variable "handlers" is not available.) at eval.c:1317
#22 0x000000000057524d in exec_byte_code (bytestr=Variable "bytestr" is not available.) at bytecode.c:1162
#23 0x0000000000540aca in funcall_lambda (fun=20972317, nargs=3, arg_vector=0x7fffb1924220) at lisp.h:1355
#24 0x0000000000540f43 in Ffuncall (nargs=Variable "nargs" is not available.) at eval.c:2872
#25 0x00000000005747d8 in exec_byte_code (bytestr=Variable "bytestr" is not available.) at bytecode.c:916
#26 0x0000000000540275 in eval_sub (form=Variable "form" is not available.) at lisp.h:913
#27 0x0000000000541bee in internal_lisp_condition_case (var=18706882, bodyform=17770422, handlers=Variable "handlers" is not available.) at eval.c:1317
#28 0x000000000057524d in exec_byte_code (bytestr=Variable "bytestr" is not available.) at bytecode.c:1162
#29 0x0000000000540aca in funcall_lambda (fun=20844701, nargs=0, arg_vector=0x7fffb19246d8) at lisp.h:1355
#30 0x0000000000540f43 in Ffuncall (nargs=Variable "nargs" is not available.) at eval.c:2872
#31 0x00000000005416a3 in Fapply (nargs=2, args=0x7fffb19246d0) at eval.c:2297
#32 0x00000000005411d8 in Ffuncall (nargs=Variable "nargs" is not available.) at lisp.h:913
#33 0x00000000005747d8 in exec_byte_code (bytestr=Variable "bytestr" is not available.) at bytecode.c:916
#34 0x0000000000540275 in eval_sub (form=Variable "form" is not available.) at lisp.h:913
#35 0x0000000000541bee in internal_lisp_condition_case (var=18706882, bodyform=8745270, handlers=Variable "handlers" is not available.) at eval.c:1317
#36 0x000000000057524d in exec_byte_code (bytestr=Variable "bytestr" is not available.) at bytecode.c:1162
#37 0x0000000000540aca in funcall_lambda (fun=8744957, nargs=1, arg_vector=0x7fffb1924a98) at lisp.h:1355
#38 0x0000000000540f43 in Ffuncall (nargs=Variable "nargs" is not available.) at eval.c:2872
#39 0x00000000005413a3 in call1 (fn=Variable "fn" is not available.) at eval.c:2610
#40 0x00000000004cf794 in timer_check () at keyboard.c:4515
#41 0x00000000004cf8e9 in readable_events (flags=1) at keyboard.c:3448
#42 0x00000000004d5a87 in get_input_pending (flags=1) at lisp.h:2354
#43 0x00000000004d5c25 in swallow_events (do_display=true) at keyboard.c:4317
#44 0x000000000057c0d5 in wait_reading_process_output (time_limit=82, nsecs=0, read_kbd=-1, do_display=true, wait_for_cell=14691250, wait_proc=0x0, just_wait_proc=0) at process.c:4704
#45 0x00000000004148a8 in sit_for (timeout=328, reading=true, display_option=Variable "display_option" is not available.) at dispnew.c:5867
#46 0x00000000004d7e76 in read_char (commandflag=1, map=25957990, prev_event=14691250, used_mouse_menu=0x7fffb192b76f, end_time=0x0) at lisp.h:700
#47 0x00000000004d981e in read_key_sequence (keybuf=0x7fffb192b900, bufsize=30, prompt=14691250, dont_downcase_last=false, can_return_switch_frame=true, fix_current_buffer=true, prevent_redisplay=false) at lisp.h:2354
#48 0x00000000004db44a in command_loop_1 () at keyboard.c:1453
#49 0x000000000053db57 in internal_condition_case (bfun=0x4db250 <command_loop_1>, handlers=14742754, hfun=0x4ce070 <cmd_error>) at eval.c:1348
#50 0x00000000004ce45a in command_loop_2 (ignore=Variable "ignore" is not available.) at keyboard.c:1178
#51 0x000000000053da60 in internal_catch (tag=14738690, func=0x4ce440 <command_loop_2>, arg=14691250) at eval.c:1112
#52 0x00000000004ce2df in recursive_edit_1 () at keyboard.c:1157
#53 0x00000000004ce426 in Frecursive_edit () at keyboard.c:849
#54 0x00000000004cce22 in main (argc=2, argv=0x7fffb192bc48) at emacs.c:1642
(gdb)  

The root cause of this problem is freeing `char *discarded` in the middle of using it (editfns.c, line 4394). `discarded` and `info` were allocated with the SAFE_ALLOCA call on (editfns.c, line 3806), when format string is longer than 16K, malloc would be called and `discarded` would be allocated on the heap, thus the SAFE_FREE call on line 4394 will do the actual heap free and make the memory pointed by `discarded` inaccessible. A possible fix might look like this:

diff -u /home/kontinuation/documents/editfns.c /home/kontinuation/documents/new_editfns.c
--- /home/kontinuation/documents/editfns.c	2015-05-11 22:28:27.992501954 +0800
+++ /home/kontinuation/documents/new_editfns.c	2015-05-11 22:28:54.679014773 +0800
@@ -4390,8 +4390,6 @@
     nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf);
   val = make_specified_string (buf, nchars, p - buf, multibyte);
 
-  /* If we allocated BUF with malloc, free it too.  */
-  SAFE_FREE ();
 
   /* If the format string has text properties, or any of the string
      arguments has text properties, set up text properties of the
@@ -4498,6 +4496,9 @@
       UNGCPRO;
     }
 
+  /* If we allocated BUF with malloc, free it too.  */
+  SAFE_FREE ();
+
   return val;
 }