Re: [PATCH 2/2] iconvdata: Test case for bug 34556
Carlos O'Donell <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.alpha |
|---|---|
| Organization | Red Hat, LLC. |
| Message-ID | <[email protected]> |
On 8/21/26 6:13 AM, Florian Weimer wrote: > Assisted-by: LLM OK. The test case looks correct. Reviewed-by: Carlos O'Donell <[email protected]> > --- > 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; > + } OK. Note this flush hides the newly discovered defect that a combining character can be lost without the flush (see my comments and test case on the first patch in the series). > + > + 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> -- Cheers, Carlos.