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