1 /* bug 17197: check that iconv doesn't emit invalid extra shift character
2    Copyright (C) 2015-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <iconv.h>
20 #include <locale.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 
26 static int
do_test(void)27 do_test (void)
28 {
29   static const char *charsets[] =
30     { "IBM930", "IBM933", "IBM935", "IBM937", "IBM939" };
31   static const char *expects[] =
32     { "\016\x44\x4d\017", "\016\x41\x63\017", "\016\x44\x4d\017",
33       "\016\x44\x4d\017", "\016\x44\x4d\017" };
34   int ret = 0;
35 
36   for (int i = 0; i < sizeof (charsets) / sizeof (*charsets); i++)
37     {
38       const char *charset = charsets[i];
39       iconv_t cd = iconv_open (charset, "UTF-8");
40       if (cd == (iconv_t) -1)
41 	{
42 	  printf ("iconv_open failed (%s)\n", charset);
43 	  ret = 1;
44 	  continue;
45 	}
46 
47       char input[] = "\xe2\x88\x9e.";
48       const char *expect1 = expects[i];
49       const char expect2[] = "\x4b";
50       size_t input_len = sizeof (input);
51       char output[4];
52       size_t inlen = input_len;
53       size_t outlen = sizeof (output);
54       char *inptr = input;
55       char *outptr = output;
56       /* First round: expect conversion to stop before ".".  */
57       size_t r = iconv (cd, &inptr, &inlen, &outptr, &outlen);
58       if (r != -1
59 	  || errno != E2BIG
60 	  || inlen != 2
61 	  || inptr != input + input_len - 2
62 	  || outlen != 0
63 	  || memcmp (output, expect1, sizeof (output)) != 0)
64 	{
65 	  printf ("wrong first conversion (%s)", charset);
66 	  ret = 1;
67 	  goto do_close;
68 	}
69 
70       outlen = sizeof (output);
71       outptr = output;
72       r = iconv (cd, &inptr, &inlen, &outptr, &outlen);
73       if (r != 0
74 	  || inlen != 0
75 	  || outlen != sizeof (output) - sizeof (expect2)
76 	  || memcmp (output, expect2, sizeof (expect2)) != 0)
77 	{
78 	  printf ("wrong second conversion (%s)\n", charset);
79 	  ret = 1;
80 	}
81 
82     do_close:
83       if (iconv_close (cd) != 0)
84 	{
85 	  printf ("iconv_close failed (%s)\n", charset);
86 	  ret = 1;
87 	  continue;
88 	}
89     }
90   return ret;
91 }
92 
93 #define TEST_FUNCTION do_test ()
94 #include "../test-skeleton.c"
95