Subject: Re: bug#39207: WITH dgb symbols Re: bug#39207: 28.0.50; crash when sending gnus message

From: Paul Eggert <[email-masked]>
Date: Wed, 22 Jan 2020 23:52:08 -0800

On 1/22/20 1:13 PM, Andreas Schwab wrote:
> Looks like aset has been broken by commit c1b6d5c5b9 or ac121d8c8f.

Thanks for the heads-up and the test case. Sorry about the breakage. I installed 
the attached patch, which I assume fixes this.
>From 6f580542c1796d3e7ba4d1dd40b2fe73fe00e5db Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Wed, 22 Jan 2020 23:43:29 -0800
Subject: [PATCH] Fix crash when sending Gnus message (Bug#39207)

* src/alloc.c (resize_string_data): The string must be multibyte.
When not bothering to reallocate, do bother to change the byte count.
* test/src/alloc-tests.el (aset-nbytes-change) New test.
---
 src/alloc.c             | 4 +++-
 test/src/alloc-tests.el | 7 +++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/alloc.c b/src/alloc.c
index 99d5ca149d..a35b48cfb2 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -1889,7 +1889,7 @@ allocate_string_data (struct Lisp_String *s,
   tally_consing (needed);
 }
 
-/* Reallocate the data for STRING when a single character is replaced.
+/* Reallocate multibyte STRING data when a single character is replaced.
    The character is at byte offset CIDX_BYTE in the string.
    The character being replaced is CLEN bytes long,
    and the character that will replace it is NEW_CLEN bytes long.
@@ -1900,6 +1900,7 @@ unsigned char *
 resize_string_data (Lisp_Object string, ptrdiff_t cidx_byte,
 		    int clen, int new_clen)
 {
+  eassume (STRING_MULTIBYTE (string));
   sdata *old_sdata = SDATA_OF_STRING (XSTRING (string));
   ptrdiff_t nchars = SCHARS (string);
   ptrdiff_t nbytes = SBYTES (string);
@@ -1911,6 +1912,7 @@ resize_string_data (Lisp_Object string, ptrdiff_t cidx_byte,
     {
       /* No need to reallocate, as the size change falls within the
 	 alignment slop.  */
+      XSTRING (string)->u.s.size_byte = new_nbytes;
       new_charaddr = data + cidx_byte;
       memmove (new_charaddr + new_clen, new_charaddr + clen,
 	       nbytes - (cidx_byte + (clen - 1)));
diff --git a/test/src/alloc-tests.el b/test/src/alloc-tests.el
index 4eb776a055..aa1ab1648f 100644
--- a/test/src/alloc-tests.el
+++ b/test/src/alloc-tests.el
@@ -51,3 +51,10 @@
     (should-not (eq x y))
     (dotimes (i 4)
       (should (eql (aref x i) (aref y i))))))
+
+;; Bug#39207
+(ert-deftest aset-nbytes-change ()
+  (let ((s (make-string 1 ?a)))
+    (dolist (c (list 10003 ?b 128 ?c ?d (max-char) ?e))
+      (aset s 0 c)
+      (should (equal s (make-string 1 c))))))
-- 
2.17.1