Subject: bug#24206: 25.1; Curly quotes generate invalid strings, leading to a segfault

From: Paul Eggert <[email-masked]>
Date: Tue, 16 Aug 2016 10:37:39 -0700

Eli Zaretskii wrote:

> I preferred to install one of the 2 patches I posted yesterday.

Let's not cut the RC now, as unfortunately that patch fails spectacularly. (I 
didn't test it yesterday; I tested your other patch, which is obviously better.) 
To reproduce the problem, run emacs -Q and "C-h f car RET"; Emacs will display 
"Wrong type argument: integer-or-marker-p, nil" instead of help.

The attached patch to emacs-25 fixes the problem. It makes the code functionally 
equivalent to the other of the 2 patches that you posted yesterday, and is 
simpler. OK to install in emacs-25?
From 36a8eec4e8f07724e5ed202b0c68233019975e85 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Tue, 16 Aug 2016 10:36:14 -0700
Subject: [PATCH] =?UTF-8?q?Fix=20=E2=80=98wrong=20type=20argument=E2=80=99?=
 =?UTF-8?q?=20bug=20with=20C-h=20f?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* src/doc.c (Fsubstitute_command_keys): Revert previous change.
Instead, to fix the core dump, first convert source string to a
multibyte temporary if it is not multibyte already.  As before,
keep the original string if there are no changes (Bug#24206).
---
 src/doc.c | 24 +++++++-----------------
 1 file changed, 7 insertions(+), 17 deletions(-)

diff --git a/src/doc.c b/src/doc.c
index 86e1e0d..4f5f7a4 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -750,7 +750,7 @@ Otherwise, return a new string.  */)
   unsigned char const *start;
   ptrdiff_t length, length_byte;
   Lisp_Object name;
-  bool multibyte, pure_ascii;
+  bool multibyte;
   ptrdiff_t nchars;
 
   if (NILP (string))
@@ -763,12 +763,9 @@ Otherwise, return a new string.  */)
 
   enum text_quoting_style quoting_style = text_quoting_style ();
 
+  Lisp_Object orig_string = string;
+  string = Fstring_make_multibyte (string);
   multibyte = STRING_MULTIBYTE (string);
-  /* Pure-ASCII unibyte input strings should produce unibyte strings
-     if substitution doesn't yield non-ASCII bytes, otherwise they
-     should produce multibyte strings.  */
-  pure_ascii = SBYTES (string) == count_size_as_multibyte (SDATA (string),
-							   SCHARS (string));
   nchars = 0;
 
   /* KEYMAP is either nil (which means search all the active keymaps)
@@ -950,11 +947,8 @@ Otherwise, return a new string.  */)
 
 	subst_string:
 	  start = SDATA (tem);
+	  length = SCHARS (tem);
 	  length_byte = SBYTES (tem);
-	  if (multibyte || pure_ascii)
-	    length = SCHARS (tem);
-	  else
-	    length = length_byte;
 	subst:
 	  nonquotes_changed = true;
 	subst_quote:
@@ -973,15 +967,11 @@ Otherwise, return a new string.  */)
 	  }
 	}
       else if ((strp[0] == '`' || strp[0] == '\'')
-	       && quoting_style == CURVE_QUOTING_STYLE
-	       && multibyte)
+	       && quoting_style == CURVE_QUOTING_STYLE)
 	{
 	  start = (unsigned char const *) (strp[0] == '`' ? uLSQM : uRSQM);
+	  length = 1;
 	  length_byte = sizeof uLSQM - 1;
-	  if (multibyte || pure_ascii)
-	    length = 1;
-	  else
-	    length = length_byte;
 	  idx = strp - SDATA (string) + 1;
 	  goto subst_quote;
 	}
@@ -1036,7 +1026,7 @@ Otherwise, return a new string.  */)
 	}
     }
   else
-    tem = string;
+    tem = orig_string;
   xfree (buf);
   return tem;
 }
-- 
2.5.5