00db10
The commit included in this patch only incidentally fixes the problem
00db10
reported in bug 1427734: In each of the IBM9xx character sets referenced in
00db10
this patch, the removal of the "break" statement means that the subsequent
00db10
increment of "inptr" is executed instead of being skipped. This allows
00db10
conversion to progress instead of hanging.
00db10
00db10
commit 692de4b3960dc90bdcfb871513ee4d81d314cf69
00db10
Author: Martin Sebor <msebor@redhat.com>
00db10
Date:   Fri Jan 15 11:25:13 2016 -0700
00db10
00db10
    Have iconv accept redundant escape sequences in IBM900, IBM903, IBM905,
00db10
    IBM907, and IBM909.
00db10
    
00db10
    Patch for bug #17197 changes the encoder to avoid generating redundant
00db10
    shift sequences.  However, those sequences may already be present in
00db10
    data encododed by prior versions of the encoder.  This change modifies
00db10
    the decoder to also avoid rejecting redundant shift sequences.
00db10
    
00db10
            [BZ #19432]
00db10
            * iconvdata/Makefile: Add bug-iconv11.
00db10
            * iconvdata/bug-iconv11.c: New test.
00db10
            * iconvdata/ibm930.c: Do not reject redundant shift sequences.
00db10
            * iconvdata/ibm933.c: Same.
00db10
            * iconvdata/ibm935.c: Same.
00db10
            * iconvdata/ibm937.c: Same.
00db10
            * iconvdata/ibm939.c: Same.
00db10
00db10
# Conflicts:
00db10
#	iconvdata/Makefile
00db10
00db10
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
00db10
index 0ec67554ca4c29ea..c4e6c510d7abc055 100644
00db10
--- a/iconvdata/Makefile
00db10
+++ b/iconvdata/Makefile
00db10
@@ -68,7 +68,7 @@ include ../Makeconfig
00db10
 ifeq (yes,$(build-shared))
00db10
 tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
00db10
 	tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
00db10
-	bug-iconv10 bug-iconv12
00db10
+	bug-iconv10 bug-iconv11 bug-iconv12
00db10
 ifeq ($(have-thread-library),yes)
00db10
 tests += bug-iconv3
00db10
 endif
00db10
diff --git a/iconvdata/bug-iconv11.c b/iconvdata/bug-iconv11.c
00db10
new file mode 100644
00db10
index 0000000000000000..6cdc07d79883454d
00db10
--- /dev/null
00db10
+++ b/iconvdata/bug-iconv11.c
00db10
@@ -0,0 +1,114 @@
00db10
+/* bug 19432: iconv rejects redundant escape sequences in IBM903,
00db10
+              IBM905, IBM907, and IBM909
00db10
+
00db10
+   Copyright (C) 2016 Free Software Foundation, Inc.
00db10
+   This file is part of the GNU C Library.
00db10
+
00db10
+   The GNU C Library is free software; you can redistribute it and/or
00db10
+   modify it under the terms of the GNU Lesser General Public
00db10
+   License as published by the Free Software Foundation; either
00db10
+   version 2.1 of the License, or (at your option) any later version.
00db10
+
00db10
+   The GNU C Library is distributed in the hope that it will be useful,
00db10
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
00db10
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00db10
+   Lesser General Public License for more details.
00db10
+
00db10
+   You should have received a copy of the GNU Lesser General Public
00db10
+   License along with the GNU C Library; if not, see
00db10
+   <http://www.gnu.org/licenses/>.  */
00db10
+
00db10
+#include <iconv.h>
00db10
+#include <stdio.h>
00db10
+#include <stdlib.h>
00db10
+#include <string.h>
00db10
+#include <errno.h>
00db10
+
00db10
+// The longest test input sequence.
00db10
+#define MAXINBYTES    8
00db10
+#define MAXOUTBYTES   (MAXINBYTES * MB_LEN_MAX)
00db10
+
00db10
+/* Verify that a conversion of the INPUT sequence consisting of
00db10
+   INBYTESLEFT bytes in the encoding specified by the codeset
00db10
+   named by FROM_SET is successful.
00db10
+   Return 0 on success, non-zero on iconv() failure.  */
00db10
+
00db10
+static int
00db10
+test_ibm93x (const char *from_set, const char *input, size_t inbytesleft)
00db10
+{
00db10
+  const char to_set[] = "UTF-8";
00db10
+  iconv_t cd = iconv_open (to_set, from_set);
00db10
+  if (cd == (iconv_t) -1)
00db10
+    {
00db10
+      printf ("iconv_open(\"%s\", \"%s\"): %s\n",
00db10
+              from_set, to_set, strerror (errno));
00db10
+      return 1;
00db10
+    }
00db10
+
00db10
+  char output [MAXOUTBYTES];
00db10
+  size_t outbytesleft = sizeof output;
00db10
+
00db10
+  char *inbuf = (char*)input;
00db10
+  char *outbuf = output;
00db10
+
00db10
+  printf ("iconv(cd, %p, %zu, %p, %zu)\n",
00db10
+          inbuf, inbytesleft, outbuf, outbytesleft);
00db10
+
00db10
+  errno = 0;
00db10
+  size_t ret = iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
00db10
+  printf ("  ==> %td: %s\n"
00db10
+          "  inbuf%+td, inbytesleft=%zu, outbuf%+td, outbytesleft=%zu\n",
00db10
+          ret, strerror (errno),
00db10
+          inbuf - input, inbytesleft, outbuf - output, outbytesleft);
00db10
+
00db10
+  // Return 0 on success, non-zero on iconv() failure.
00db10
+  return ret == (size_t)-1 || errno;
00db10
+}
00db10
+
00db10
+static int
00db10
+do_test (void)
00db10
+{
00db10
+  // State-dependent encodings to exercise.
00db10
+  static const char* const to_code[] = {
00db10
+    "IBM930", "IBM933", "IBM935", "IBM937", "IBM939"
00db10
+  };
00db10
+
00db10
+  static const size_t ncodesets = sizeof to_code / sizeof *to_code;
00db10
+
00db10
+  static const struct {
00db10
+    char txt[MAXINBYTES];
00db10
+    size_t len;
00db10
+  } input[] = {
00db10
+#define DATA(s) { s, sizeof s - 1 }
00db10
+    /* <SI>: denotes the shift-in 1-byte escape sequence, changing
00db10
+             the encoder from a sigle-byte encoding to multibyte
00db10
+       <SO>: denotes the shift-out 1-byte escape sequence, switching
00db10
+             the encoder from a multibyte to a single-byte state  */
00db10
+
00db10
+    DATA ("\x0e"),               // <SI> (not redundant)
00db10
+    DATA ("\x0f"),               // <S0> (redundant with initial state)
00db10
+    DATA ("\x0e\x0e"),           // <SI><SI>
00db10
+    DATA ("\x0e\x0f\x0f"),       // <SI><SO><SO>
00db10
+    DATA ("\x0f\x0f"),           // <SO><SO>
00db10
+    DATA ("\x0f\x0e\x0e"),       // <SO><SI><SI>
00db10
+    DATA ("\x0e\x0f\xc7\x0f"),   // <SI><SO><G><SO>
00db10
+    DATA ("\xc7\x0f")            // <G><SO> (redundant with initial state)
00db10
+  };
00db10
+
00db10
+  static const size_t ninputs = sizeof input / sizeof *input;
00db10
+
00db10
+  int ret = 0;
00db10
+
00db10
+  size_t i, j;
00db10
+
00db10
+  /* Iterate over the IBM93x codesets above and exercise each with
00db10
+     the input sequences above.  */
00db10
+  for (i = 0; i != ncodesets; ++i)
00db10
+    for (j = 0; j != ninputs; ++j)
00db10
+      ret += test_ibm93x (to_code [i], input [i].txt, input [i].len);
00db10
+
00db10
+  return ret;
00db10
+}
00db10
+
00db10
+#define TEST_FUNCTION do_test ()
00db10
+#include "../test-skeleton.c"
00db10
diff --git a/iconvdata/ibm930.c b/iconvdata/ibm930.c
00db10
index 636141114f506985..88413ccfbabfdc35 100644
00db10
--- a/iconvdata/ibm930.c
00db10
+++ b/iconvdata/ibm930.c
00db10
@@ -105,24 +105,14 @@ enum
00db10
 									      \
00db10
     if (__builtin_expect (ch, 0) == SO)					      \
00db10
       {									      \
00db10
-	/* Shift OUT, change to DBCS converter.  */			      \
00db10
-	if (curcs == db)						      \
00db10
-	  {								      \
00db10
-	    result = __GCONV_ILLEGAL_INPUT;				      \
00db10
-	    break;							      \
00db10
-	  }								      \
00db10
+	/* Shift OUT, change to DBCS converter (redundant escape okay).  */   \
00db10
 	curcs = db;							      \
00db10
 	++inptr;							      \
00db10
 	continue;							      \
00db10
       }									      \
00db10
     else if (__builtin_expect (ch, 0) == SI)				      \
00db10
       {									      \
00db10
-	/* Shift IN, change to SBCS converter */			      \
00db10
-	if (curcs == sb)						      \
00db10
-	  {								      \
00db10
-	    result = __GCONV_ILLEGAL_INPUT;				      \
00db10
-	    break;							      \
00db10
-	  }								      \
00db10
+	/* Shift IN, change to SBCS converter (redundant escape okay).  */    \
00db10
 	curcs = sb;							      \
00db10
 	++inptr;							      \
00db10
 	continue;							      \
00db10
diff --git a/iconvdata/ibm933.c b/iconvdata/ibm933.c
00db10
index 8b9e5780a36a454a..335d385551fee86e 100644
00db10
--- a/iconvdata/ibm933.c
00db10
+++ b/iconvdata/ibm933.c
00db10
@@ -104,24 +104,14 @@ enum
00db10
 									      \
00db10
     if (__builtin_expect (ch, 0) == SO)					      \
00db10
       {									      \
00db10
-	/* Shift OUT, change to DBCS converter.  */			      \
00db10
-	if (curcs == db)						      \
00db10
-	  {								      \
00db10
-	    result = __GCONV_ILLEGAL_INPUT;				      \
00db10
-	    break;							      \
00db10
-	  }								      \
00db10
+	/* Shift OUT, change to DBCS converter (redundant escape okay).  */   \
00db10
 	curcs = db;							      \
00db10
 	++inptr;							      \
00db10
 	continue;							      \
00db10
       }									      \
00db10
     else if (__builtin_expect (ch, 0) == SI)				      \
00db10
       {									      \
00db10
-	/* Shift IN, change to SBCS converter.  */			      \
00db10
-	if (curcs == sb)						      \
00db10
-	  {								      \
00db10
-	    result = __GCONV_ILLEGAL_INPUT;				      \
00db10
-	    break;							      \
00db10
-	  }								      \
00db10
+	/* Shift IN, change to SBCS converter (redundant escape okay).  */    \
00db10
 	curcs = sb;							      \
00db10
 	++inptr;							      \
00db10
 	continue;							      \
00db10
diff --git a/iconvdata/ibm935.c b/iconvdata/ibm935.c
00db10
index 4e2d99ab56d7f0d2..520d28a4e9a690fc 100644
00db10
--- a/iconvdata/ibm935.c
00db10
+++ b/iconvdata/ibm935.c
00db10
@@ -104,24 +104,14 @@ enum
00db10
 									      \
00db10
     if (__builtin_expect(ch, 0) == SO)					      \
00db10
       {									      \
00db10
-	/* Shift OUT, change to DBCS converter.  */			      \
00db10
-	if (curcs == db)						      \
00db10
-	  {								      \
00db10
-	    result = __GCONV_ILLEGAL_INPUT;				      \
00db10
-	    break;							      \
00db10
-	  }								      \
00db10
+	/* Shift OUT, change to DBCS converter (redundant escape okay).  */   \
00db10
 	curcs = db;							      \
00db10
 	++inptr;							      \
00db10
 	continue;							      \
00db10
       }									      \
00db10
     else if (__builtin_expect (ch, 0) == SI)				      \
00db10
       {									      \
00db10
-	/* Shift IN, change to SBCS converter.  */			      \
00db10
-	if (curcs == sb)						      \
00db10
-	  {								      \
00db10
-	    result = __GCONV_ILLEGAL_INPUT;				      \
00db10
-	    break;							      \
00db10
-	  }								      \
00db10
+	/* Shift IN, change to SBCS converter (redundant escape okay).  */    \
00db10
 	curcs = sb;							      \
00db10
 	++inptr;							      \
00db10
 	continue;							      \
00db10
diff --git a/iconvdata/ibm937.c b/iconvdata/ibm937.c
00db10
index 1e468871b783e78d..64563bb8bf0441ff 100644
00db10
--- a/iconvdata/ibm937.c
00db10
+++ b/iconvdata/ibm937.c
00db10
@@ -104,24 +104,14 @@ enum
00db10
 									      \
00db10
     if (__builtin_expect (ch, 0) == SO)					      \
00db10
       {									      \
00db10
-	/* Shift OUT, change to DBCS converter.  */			      \
00db10
-	if (curcs == db)						      \
00db10
-	  {								      \
00db10
-	    result = __GCONV_ILLEGAL_INPUT;				      \
00db10
-	    break;							      \
00db10
-	  }								      \
00db10
+	/* Shift OUT, change to DBCS converter (redundant escape okay).  */   \
00db10
 	curcs = db;							      \
00db10
 	++inptr;							      \
00db10
 	continue;							      \
00db10
       }									      \
00db10
     else if (__builtin_expect (ch, 0) == SI)				      \
00db10
       {									      \
00db10
-	/* Shift IN, change to SBCS converter.  */			      \
00db10
-	if (curcs == sb)						      \
00db10
-	  {								      \
00db10
-	    result = __GCONV_ILLEGAL_INPUT;				      \
00db10
-	    break;							      \
00db10
-	  }								      \
00db10
+	/* Shift IN, change to SBCS converter (redundant escape okay).  */    \
00db10
 	curcs = sb;							      \
00db10
 	++inptr;							      \
00db10
 	continue;							      \
00db10
diff --git a/iconvdata/ibm939.c b/iconvdata/ibm939.c
00db10
index 2060b0c329df0c86..4f73e2e55c94972d 100644
00db10
--- a/iconvdata/ibm939.c
00db10
+++ b/iconvdata/ibm939.c
00db10
@@ -104,24 +104,14 @@ enum
00db10
 									      \
00db10
     if (__builtin_expect (ch, 0) == SO)					      \
00db10
       {									      \
00db10
-	/* Shift OUT, change to DBCS converter.  */			      \
00db10
-	if (curcs == db)						      \
00db10
-	  {								      \
00db10
-	    result = __GCONV_ILLEGAL_INPUT;				      \
00db10
-	    break;							      \
00db10
-	  }								      \
00db10
+	/* Shift OUT, change to DBCS converter (redundant escape okay).  */   \
00db10
 	curcs = db;							      \
00db10
 	++inptr;							      \
00db10
 	continue;							      \
00db10
       }									      \
00db10
     else if (__builtin_expect (ch, 0) == SI)				      \
00db10
       {									      \
00db10
-	/* Shift IN, change to SBCS converter.  */			      \
00db10
-	if (curcs == sb)						      \
00db10
-	  {								      \
00db10
-	    result = __GCONV_ILLEGAL_INPUT;				      \
00db10
-	    break;							      \
00db10
-	  }								      \
00db10
+	/* Shift IN, change to SBCS converter (redundant escape okay).  */    \
00db10
 	curcs = sb;							      \
00db10
 	++inptr;							      \
00db10
 	continue;							      \