changeset 107321:9b814b3ee348

Fix bug in decoding emacs-mule encoding. coding.c (decode_coding_emacs_mule): Fixup pointers to buffer text that could be relocated inside the call to emacs_mule_char. (emacs_mule_char): Use CODING_DECODE_CHAR instead of DECODE_CHAR. (CODING_DECODE_CHAR): Add a comment describing its purpose.
author Eli Zaretskii <eliz@gnu.org>
date Tue, 02 Mar 2010 22:35:44 +0200
parents d2bfe26756ed
children f220632d1439
files src/ChangeLog src/coding.c
diffstat 2 files changed, 26 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Tue Mar 02 10:32:45 2010 +0100
+++ b/src/ChangeLog	Tue Mar 02 22:35:44 2010 +0200
@@ -1,3 +1,10 @@
+2010-03-02  Eli Zaretskii  <eliz@gnu.org>
+
+	* coding.c (decode_coding_emacs_mule): Fixup pointers to buffer
+	text that could be relocated inside the call to emacs_mule_char.
+	(emacs_mule_char): Use CODING_DECODE_CHAR instead of DECODE_CHAR.
+	(CODING_DECODE_CHAR): Add a comment describing its purpose.
+
 2010-03-02  Kenichi Handa  <handa@m17n.org>
 
 	* character.c (parse_str_as_multibyte): Fix handling of the
--- a/src/coding.c	Tue Mar 02 10:32:45 2010 +0100
+++ b/src/coding.c	Tue Mar 02 22:35:44 2010 +0200
@@ -1005,6 +1005,10 @@
     }
 }
 
+/* This wrapper macro is used to preserve validity of pointers into
+   buffer text across calls to decode_char, which could cause
+   relocation of buffers if it loads a charset map, because loading a
+   charset map allocates large structures.  */
 #define CODING_DECODE_CHAR(coding, src, src_base, src_end, charset, code, c) \
   do {									     \
     charset_map_loaded = 0;						     \
@@ -2178,7 +2182,7 @@
 	default:
 	  abort ();
 	}
-      c = DECODE_CHAR (charset, code);
+      CODING_DECODE_CHAR (coding, src, src_base, src_end, charset, code, c);
       if (c < 0)
 	goto invalid_code;
     }
@@ -2525,9 +2529,23 @@
       else
 	{
 	  int nchars, nbytes;
+	  /* emacs_mule_char can load a charset map from a file, which
+	     allocates a large structure and might cause buffer text
+	     to be relocated as result.  Thus, we need to remember the
+	     original pointer to buffer text, and fixup all related
+	     pointers after the call.  */
+	  const unsigned char *orig = coding->source;
+	  EMACS_INT offset;
 
 	  c = emacs_mule_char (coding, src_base, &nbytes, &nchars, &id,
 			       cmp_status);
+	  offset = coding->source - orig;
+	  if (offset)
+	    {
+	      src += offset;
+	      src_base += offset;
+	      src_end += offset;
+	    }
 	  if (c < 0)
 	    {
 	      if (c == -1)