Subject: 25.1.50; server-reply-print does not avoid escape boundaries properly

From: Jason Feng <[email-masked]>
Date: Mon, 14 Dec 2015 17:45:56 -0800

When printing a large amount of data over the emacs client protocol, any
printed data with spaces or newlines or other quoted characters may get
parts of the escape sequence inserted into the decoded stream due to
splitting.

Given any current emacs server instance, the bug can be triggered by
using emacsclient -e to evaluate the following code:

  (concat (make-string (- server-msg-size (length "-print ") 3) ?a) " ")

A patched version of the function that I'm currently using in my setup
appears to solve the problem:

(defun server-reply-print (qtext proc)
    "Send a `-print QTEXT' command to client PROC.
QTEXT must be already quoted.
This handles splitting the command if it would be bigger than
`server-msg-size'."
    (let ((prefix "-print ")
          part)
      (while (> (+ (length qtext) (length prefix) 1) server-msg-size)
        ;; We have to split the string
        (setq part (substring qtext 0 (- server-msg-size (length prefix) 1)))
        ;; Don't split in the middle of a quote sequence
        (if (string-match (rx (group "&") (* (group "&&")) eol) part)
            ;; There is an uneven number of & at the end
          (setq part (substring part 0 -1)))
        (setq qtext (substring qtext (length part)))
        (server-send-string proc (concat prefix part "\n"))
        (setq prefix "-print-nonl "))
      (server-send-string proc (concat prefix qtext "\n"))))

In GNU Emacs 25.1.50.2 (x86_64-pc-linux-gnu, GTK+ Version 3.10.8)
 of 2015-12-10
Windowing system distributor 'The X.Org Foundation', version 11.0.11501000
System Description:          Ubuntu 14.04.3 LTS

Configured using:
 'configure --build=x86_64-linux-gnu --prefix=/usr
 '--includedir=${prefix}/include' '--mandir=${prefix}/share/man'
 '--infodir=${prefix}/share/info' --sysconfdir=/etc --localstatedir=/var
 '--libdir=${prefix}/lib/x86_64-linux-gnu'
 '--libexecdir=${prefix}/lib/x86_64-linux-gnu' --disable-maintainer-mode
 --disable-dependency-tracking --prefix=/usr --sharedstatedir=/var/lib
 --program-suffix=-snapshot --with-x=yes --with-x-toolkit=gtk3
 'CFLAGS=-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat
 -Werror=format-security' CPPFLAGS=-D_FORTIFY_SOURCE=2
 'LDFLAGS=-Wl,-Bsymbolic-functions -Wl,-z,relro''

Configured features:
XPM JPEG TIFF GIF PNG RSVG IMAGEMAGICK SOUND GPM DBUS GCONF GSETTINGS
NOTIFY LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT LIBOTF XFT ZLIB
TOOLKIT_SCROLL_BARS GTK3 X11

Important settings:
  value of $LANG: en_US.UTF-8
  value of $XMODIFIERS: @im=ibus
  locale-coding-system: utf-8-unix

Major mode: Emacs-Lisp

Minor modes in effect:
  shell-dirtrack-mode: t
  iswitchb-mode: t
  diff-auto-refine-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  buffer-read-only: t
  line-number-mode: t
  transient-mark-mode: t

Recent messages:
Indenting region...done
Mark set [3 times]
=> [{:left-arm [-1.8972638273399445 -1.8972638273399445], :right-arm [-1.2571756745781983 -1.2571756745781983], :left-leg [-1.8218243292336378 -1.8036620006694457], :right-leg [-1.3379306529203474 -1.3197683243561553]} {:left-arm [-1.8972638273399445 -1.8972638273399445], :right-arm [-1.2571756745781983 -1.2571756745781983], :left-leg [-1.8129101936957523 -1.3286824598940408], :right-leg [-2.133467249511094 -1.0081254040786989]} {:left-arm [-1.8972638273399445 -1.8972638273399445], :right-arm [-1.2571756745781983 -1.2571756745781983], :left-leg [-1.3379306529203474 -1.3197683243561553], :right-leg [-1.8218243292336378 -1.8036620006694457]} {:left-arm [-1.8972638273399445 -1.8972638273399445], :right-arm [-1.2571756745781983 -1.2571756745781983], :left-leg [-2.133467249511094 -1.0081254040786989], :right-leg [-1.8129101936957523 -1.3286824598940408]}]
Mark set
=> 7730
Mark set [2 times]
Type "q" in help window to delete it.
mouse-2, RET: find function's definition
uncompressing server.el.gz...done
Note: file is write protected
Quit

Load-path shadows:
/usr/share/emacs/site-lisp/dictionaries-common/ispell hides /usr/share/emacs/25.1.50/lisp/textmodes/ispell
/usr/share/emacs/site-lisp/dictionaries-common/flyspell hides /usr/share/emacs/25.1.50/lisp/textmodes/flyspell
/home/jason/elisp/ruby-mode hides /usr/share/emacs/25.1.50/lisp/progmodes/ruby-mode
/home/jason/elisp/dns hides /usr/share/emacs/25.1.50/lisp/net/dns

Features:
(shadow sort mail-extr emacsbug message rfc822 mml mml-sec mm-decode
mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader
sendmail rfc2047 rfc2045 ietf-drums mail-utils jka-compr eieio-opt
speedbar sb-image ezimage dframe conf-mode cider-hacks clojure-hacks
pkg-info lisp-mnt epl network-stream nsm starttls tls cider tramp-sh
cider-debug cider-mode cider-repl cider-eldoc cider-interaction compile
arc-mode archive-mode cider-doc org-table org org-macro org-footnote
org-pcomplete org-list org-faces org-entities noutline outline
org-version ob-emacs-lisp ob ob-tangle ob-ref ob-lob ob-table ob-exp
org-src ob-keys ob-comint ob-core ob-eval org-compat org-macs
org-loaddefs find-func cal-menu calendar cal-loaddefs cider-test
cider-stacktrace cider-client nrepl-client tramp tramp-compat
tramp-loaddefs trampver format-spec advice queue cider-util ewoc etags
xref project thingatpt dash vc vc-dispatcher ido figwheel clojure-mode
imenu jf-dired seq dired shell pcomplete comint ring character-fold
misearch multi-isearch pp extras passwords paredit iswitchb term-mods
find-stuff flashy nav window-buffer-junk git-wads vc-git diff-mode
easy-mmode jfproc doc-mods image-drag shell-mods indent-wads ansi-color
edmacro kmacro cc-styles cc-align cc-engine cc-vars cc-defs rx cl server
finder-inf clojure-mode-autoloads info geiser-autoloads
pkg-info-autoloads epl-autoloads dash-autoloads queue-autoloads
scala-mode-autoloads package epg-config url-handlers url-parse
auth-source cl-seq eieio byte-opt bytecomp byte-compile cl-extra cconv
eieio-core cl-macs gv gnus-util time-date mm-util help-fns help-mode
easymenu cl-loaddefs pcase cl-lib mail-prsvr password-cache url-vars
mule-util tooltip eldoc electric uniquify ediff-hook vc-hooks
lisp-float-type mwheel x-win term/common-win x-dnd tool-bar dnd fontset
image regexp-opt fringe tabulated-list newcomment elisp-mode lisp-mode
prog-mode register page menu-bar rfn-eshadow timer select scroll-bar
mouse jit-lock font-lock syntax facemenu font-core frame cl-generic cham
georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese charscript case-table epa-hook
jka-cmpr-hook help simple abbrev obarray minibuffer cl-preloaded nadvice
loaddefs button faces cus-face macroexp files text-properties overlay
sha1 md5 base64 format env code-pages mule custom widget
hashtable-print-readable backquote dbusbind inotify dynamic-setting
system-font-setting font-render-setting move-toolbar gtk x-toolkit x
multi-tty make-network-process emacs)

Memory information:
((conses 16 295641 26396)
 (symbols 48 36677 0)
 (miscs 40 1394 2304)
 (strings 32 69087 8909)
 (string-bytes 1 2161821)
 (vectors 16 30924)
 (vector-slots 8 689437 7213)
 (floats 8 352 591)
 (intervals 56 7101 45)
 (buffers 976 30)
 (heap 1024 57288 2916))