[PATCH 2/2] iconvdata: Test case for bug 34556
Florian Weimer <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.alpha |
|---|---|
| Message-ID | <a84ddf0c310b16fed6898412e2409a91b57d2f65.1787307116.git.fweimer@redhat.com> |
Assisted-by: LLM
---
iconvdata/Makefile | 5 +-
iconvdata/tst-shift-jisx0213-progress.c | 118 ++++++++++++++++++++++++
2 files changed, 122 insertions(+), 1 deletion(-)
create mode 100644 iconvdata/tst-shift-jisx0213-progress.c
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
index fbb0067302..7343350a9a 100644
--- a/iconvdata/Makefile
+++ b/iconvdata/Makefile
@@ -76,7 +76,8 @@ tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \
bug-iconv13 bug-iconv14 bug-iconv15 \
- tst-iconv-iso-2022-cn-ext tst-bug33980
+ tst-iconv-iso-2022-cn-ext tst-bug33980 \
+ tst-shift-jisx0213-progress
ifeq ($(have-thread-library),yes)
tests += bug-iconv3
endif
@@ -335,6 +336,8 @@ $(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules))
$(addprefix $(objpfx),$(modules.so))
$(objpfx)tst-bug33980.out: $(addprefix $(objpfx), $(gconv-modules)) \
$(addprefix $(objpfx),$(modules.so))
+$(objpfx)tst-shift-jisx0213-progress.out: \
+ $(addprefix $(objpfx), $(gconv-modules)) $(addprefix $(objpfx),$(modules.so))
$(objpfx)iconv-test.out: run-iconv-test.sh \
$(addprefix $(objpfx), $(gconv-modules)) \
diff --git a/iconvdata/tst-shift-jisx0213-progress.c b/iconvdata/tst-shift-jisx0213-progress.c
new file mode 100644
index 0000000000..264b7141f5
--- /dev/null
+++ b/iconvdata/tst-shift-jisx0213-progress.c
@@ -0,0 +1,118 @@
+/* Test SHIFT_JISX0213 combining character conversion progress (bug 34556).
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* SHIFT_JISX0213 bytes 0x82 0xF5 map to a combining sequence:
+ U+304B (HIRAGANA LETTER KA) + U+309A (COMBINING SEMI-VOICED SOUND
+ MARK). When converting to UTF-32LE with a small output buffer, the
+ first code point is emitted and the second is queued in the
+ converter state. This test verifies that the queued code point is
+ consumed exactly once on retry, so that the conversion makes
+ progress and terminates. */
+
+#include <errno.h>
+#include <iconv.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <support/check.h>
+#include <support/support.h>
+
+static void
+test_one (size_t outbufsize)
+{
+ /* Combining sequence followed by a plain ASCII character. */
+ char input[] = { '\x82', '\xf5', 'A' };
+
+ /* Expected UTF-32 output. */
+ static const wchar_t expected[] = { 0x304b, 0x309a, 'A' };
+
+ iconv_t cd = iconv_open ("WCHAR_T", "SHIFT_JISX0213");
+ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
+
+ char result[64];
+ size_t result_len = 0;
+
+ char *inptr = input;
+ size_t inleft = sizeof (input);
+
+ char outbuf[64];
+
+ int iterations = 0;
+ while (inleft > 0)
+ {
+ char *outptr = outbuf;
+ size_t outleft = outbufsize;
+ size_t inleft_before = inleft;
+
+ size_t ret = iconv (cd, &inptr, &inleft, &outptr, &outleft);
+ size_t produced = outptr - outbuf;
+
+ TEST_VERIFY_EXIT (result_len + produced <= sizeof (result));
+ memcpy (result + result_len, outbuf, produced);
+ result_len += produced;
+
+ if (ret == (size_t) -1 && errno == E2BIG)
+ {
+ if (produced == 0 && inleft == inleft_before)
+ {
+ /* Output buffer too small for a single code point. */
+ TEST_VERIFY_EXIT (outbufsize < 4);
+ break;
+ }
+ /* Bound iterations to detect non-progress bugs. */
+ TEST_VERIFY_EXIT (++iterations < 10);
+ continue;
+ }
+ if (ret == (size_t) -1)
+ FAIL_EXIT1 ("outbufsize %zu: iconv: %m", outbufsize);
+ break;
+ }
+
+ /* Flush pending converter state. */
+ {
+ char *outptr = outbuf;
+ size_t outleft = outbufsize;
+ size_t ret = iconv (cd, NULL, NULL, &outptr, &outleft);
+ TEST_VERIFY (ret == 0);
+ size_t produced = outptr - outbuf;
+ memcpy (result + result_len, outbuf, produced);
+ result_len += produced;
+ }
+
+ if (outbufsize >= 4)
+ {
+ TEST_COMPARE (inleft, 0);
+ TEST_COMPARE_BLOB (result, result_len,
+ expected, sizeof (expected));
+ }
+
+ TEST_VERIFY_EXIT (iconv_close (cd) == 0);
+}
+
+static int
+do_test (void)
+{
+ for (size_t outbufsize = 1; outbufsize <= 16; outbufsize++)
+ {
+ printf ("info: testing output buffer size %zu\n", outbufsize);
+ test_one (outbufsize);
+ }
+ return 0;
+}
+
+#include <support/test-driver.c>
--
2.55.0