Subject: Re: bug#41122: 27.0.91; [Patch] 'Attempt to shape unibyte char' when using ligatures
From: Eli Zaretskii <[email-masked]>
To: Tom Regner <[email-masked]>
Cc: [email-masked]
Date: Thu, 07 May 2020 15:40:08 +0300
List-Id: <debbugs-submit.debbugs.gnu.org>

> Date: Thu, 07 May 2020 10:17:26 +0200
> From: Tom Regner <[email-masked]>
> 
> sometimes an emacs frame 'freezes' when a buffer with ligatures is
> created with the message 'Attempt to shape unibyte char'.  Killing
> the buffer from another frame 'unfreezes' the affected frame.

This problem is already fixed on the master branch.  (It is too late
to apply such changes to the emacs-27 release branch.)

>    if (NILP (string))
>      {
> -      if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
> -	error ("Attempt to shape unibyte text");
> -      validate_region (&from, &to);
> +     validate_region (&from, &to);
>        frompos = XFIXNAT (from);
>        topos = XFIXNAT (to);
> -      frombyte = CHAR_TO_BYTE (frompos);
> +      if (!NILP (BVAR (current_buffer, enable_multibyte_characters)))
> +	      frombyte = CHAR_TO_BYTE (frompos);
> +      else
> +      {
> +	      ptrdiff_t pos;
> +
> +	      /* fill_gstring_header below uses
> +		 FETCH_CHAR_ADVANCE_NO_CHECK that assumes the current
> +		 buffer is multibyte, but it is safe as long as it only
> +		 fetches ASCII chars.  */
> +	      for (pos = frompos; pos < topos; pos++)
> +		      if (!ASCII_BYTE_P (*(BYTE_POS_ADDR (pos))))
> +			      error ("Attempt to shape non-ASCII part of unibyte text");
> +	      frombyte = frompos;

This part is incorrect: unibyte buffers should not be subject to
character composition, even if the bytes found there happen to be
ASCII bytes.

> +      else
> +      {
> +	      ptrdiff_t pos;
> +
> +	      /* fill_gstring_header below uses
> +		 FETCH_STRING_CHAR_ADVANCE_NO_CHECK that assumes the
> +		 string is multibyte, but it is safe as long as it only
> +		 fetches ASCII chars.  */
> +	      for (pos = frompos; pos < topos; pos++)
> +		      if (!ASCII_BYTE_P (SREF (string, pos)))
> +			      error ("Attempt to shape non-ASCII part of unibyte text");
> +	      frombyte = string_char_to_byte (string, frompos);
> +      }

This part (or its moral equivalent) is already on the master branch.

Thanks.