head 1.8; access; symbols netbsd-9:1.8.0.6 netbsd-10:1.8.0.4 netbsd-11:1.8.0.2; locks; strict; comment @ * @; 1.8 date 2026.06.30.23.17.31; author riastradh; state Exp; branches 1.8.2.1 1.8.4.1 1.8.6.1; next 1.7; commitid GLq16YyjoahVtSLG; 1.7 date 2026.06.30.23.17.14; author riastradh; state Exp; branches; next 1.6; commitid exLfYVQDwg9PtSLG; 1.6 date 2026.06.30.23.16.53; author riastradh; state Exp; branches; next 1.5; commitid tLcn45JCWmXHtSLG; 1.5 date 2026.06.30.23.16.34; author riastradh; state Exp; branches; next 1.4; commitid iXtkor3ZIEIAtSLG; 1.4 date 2026.06.30.23.16.08; author riastradh; state Exp; branches; next 1.3; commitid KdxNOXsfvyvrtSLG; 1.3 date 2026.06.30.23.15.52; author riastradh; state Exp; branches; next 1.2; commitid XWZH6ktRDbWltSLG; 1.2 date 2026.06.30.23.15.31; author riastradh; state Exp; branches; next 1.1; commitid Pv4xBtfcdZwetSLG; 1.1 date 2026.06.30.23.14.39; author riastradh; state Exp; branches; next ; commitid zZNqQJ5xqZlEsSLG; 1.8.2.1 date 2026.06.30.23.17.31; author martin; state dead; branches; next 1.8.2.2; commitid bdjUWN4PKPzMDeMG; 1.8.2.2 date 2026.07.03.18.02.14; author martin; state Exp; branches; next ; commitid bdjUWN4PKPzMDeMG; 1.8.4.1 date 2026.06.30.23.17.31; author martin; state dead; branches; next 1.8.4.2; commitid QCyGtmZxl3CpFeMG; 1.8.4.2 date 2026.07.03.18.06.57; author martin; state Exp; branches; next ; commitid QCyGtmZxl3CpFeMG; 1.8.6.1 date 2026.06.30.23.17.31; author martin; state dead; branches; next 1.8.6.2; commitid nVEWpFqb844BHeMG; 1.8.6.2 date 2026.07.03.18.13.19; author martin; state Exp; branches; next ; commitid nVEWpFqb844BHeMG; desc @@ 1.8 log @iconv(3): Fix printing bytes on test failure. Don't sign-extend to a 32-bit quantity causing the left to be padded with f's; just print the 8-bit quantity. PR 59019: various iconv issues @ text @/* $NetBSD: t_iconv.c,v 1.7 2026/06/30 23:17:14 riastradh Exp $ */ /*- * Copyright (c) 2025 The NetBSD Foundation, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * iconv(3) */ #include __RCSID("$NetBSD: t_iconv.c,v 1.7 2026/06/30 23:17:14 riastradh Exp $"); #include #include #include #include #include #include #include #include "h_macros.h" static const struct sample { const char *src_codeset; size_t nsrc; const char *src; const char *dst_codeset; size_t ndst; const char *dst; size_t ninval; size_t ninval_rev; const char *xfail; #define IRREVERSIBLE ((size_t)-1) } samples[] = { [0] = { "us-ascii", 6, "hello", "us-ascii", 6, "hello", 0, 0, NULL }, /* LATIN SMALL LETTER E WITH ACUTE ACCENT */ [1] = { "iso-8859-1", 1, (const char[1]){0xe9}, "UTF-8", 2, (const char[2]){0xc3,0xa9}, 0, 0, NULL }, /* LEFT CURLY BRACKET */ [2] = { "UTF-8", 2, (const char[2]){0x00,0x7b}, "ZW", 6, (const char[6]){0x00,0x7a,0x57,0x20,0x7b,0x0a}, 0, 0, NULL }, /* LATIN SMALL LETTER O, TILDE */ [3] = { "UTF-8", 2, (const char[2]){0x4f,0x7e}, "VIQR", 3, (const char[3]){0x4f,0x5c,0x7e}, 0, 0, NULL }, /* LEFT CURLY BRACKET (optionally encoded in UTF-7) */ [4] = { "UTF-7", 1, (const char[1]){0x7b}, "UTF-8", 1, (const char[1]){0x7b}, 0, IRREVERSIBLE, NULL }, [5] = { "UTF-7", 4, "+AHs-", "UTF-8", 1, (const char[1]){0x7b}, 0, 0, NULL }, /* éclair */ [6] = { "UTF-7", 10, "+AOk-clair", "UTF-8", 7, (const char[7]){ 0xc3,0xa9,0x63,0x6c,0x61,0x69,0x72, }, 0, 0, NULL }, [7] = { "HZ", 55, /* RFC 1843, Sec. 4, Example 1 */ "The next sentence is in GB.~{<:Ky2;S{#,NpJ)l6HK!#~}Bye.", "UTF-8", 61, (const char[61]) { 0x54,0x68,0x65,0x20, 0x6e,0x65,0x78,0x74, 0x20,0x73,0x65,0x6e, 0x74,0x65,0x6e,0x63, 0x65,0x20,0x69,0x73, 0x20,0x69,0x6e,0x20, 0x47,0x42,0x2e,0xe5, 0xb7,0xb1,0xe6,0x89, 0x80,0xe4,0xb8,0x8d, 0xe6,0xac,0xb2,0xef, 0xbc,0x8c,0xe5,0x8b, 0xbf,0xe6,0x96,0xbd, 0xe6,0x96,0xbc,0xe4, 0xba,0xba,0xe3,0x80, 0x82,0x42,0x79,0x65, 0x2e }, 0, 0, NULL }, /* Same as above but with HZ8 instead of HZ. */ [8] = { "HZ8", 55, (const char[55]) { 0x54,0x68,0x65,0x20,0x6e,0x65,0x78,0x74, 0x20,0x73,0x65,0x6e,0x74,0x65,0x6e,0x63, 0x65,0x20,0x69,0x73,0x20,0x69,0x6e,0x20, 0x47,0x42,0x2e,0x7e,0x7b,0xbc,0xba,0xcb, 0xf9,0xb2,0xbb,0xd3,0xfb,0xa3,0xac,0xce, 0xf0,0xca,0xa9,0xec,0xb6,0xc8,0xcb,0xa1, 0xa3,0x7e,0x7d,0x42,0x79,0x65,0x2e }, "UTF-8", 61, (const char[61]) { 0x54,0x68,0x65,0x20, 0x6e,0x65,0x78,0x74, 0x20,0x73,0x65,0x6e, 0x74,0x65,0x6e,0x63, 0x65,0x20,0x69,0x73, 0x20,0x69,0x6e,0x20, 0x47,0x42,0x2e,0xe5, 0xb7,0xb1,0xe6,0x89, 0x80,0xe4,0xb8,0x8d, 0xe6,0xac,0xb2,0xef, 0xbc,0x8c,0xe5,0x8b, 0xbf,0xe6,0x96,0xbd, 0xe6,0x96,0xbc,0xe4, 0xba,0xba,0xe3,0x80, 0x82,0x42,0x79,0x65, 0x2e }, 0, 0, NULL }, /* 馬 from CNS 11643-1 */ [9] = { "UTF-8", 3, (const char[3]){0xe9,0xa6,0xac}, "ISO-2022-CN", 8, (const char[8]){0x1b,0x24,0x29,0x47,0x0e,0x58,0x6b,0x0f}, 0, 0, NULL }, /* 馬毦 shifting from CNS 11643-1 to CNS 11643-2 */ [10] = { "UTF-8", 6, (const char[6]){0xe9,0xa6,0xac,0xe6,0xaf,0xa6}, "ISO-2022-CN", 16, (const char[16]){ /* ESC $ ) G (shift G1 to CNS 11643 plane 1) */ 0x1b,0x24,0x29,0x47, 0x0e, /* GL is G1 from now on */ 0x58,0x6b, /* 馬 */ /* ESC $ * H (shift G2 to CNS 11643 plane 2) */ 0x1b,0x24,0x2a,0x48, 0x1b,0x4e, /* GL is G2 for next char */ 0x30,0x21, /* 毦 */ 0x0f, /* GL is G0 from now on */ }, 0, 0, "PR lib/59019: various iconv issues ([case 10: ISO-2022-CN to UTF-8 14/6] iconv: Illegal byte sequence (85))" }, }; #define MIN(x, y) ((x) < (y) ? (x) : (y)) static void test_sample_bounded(const char *title, const struct sample *S, size_t nsrc, size_t ndst) { char inbuf[4096], inguard = arc4random(); char outbuf[4096], outguard = arc4random(); iconv_t C; char *src0, *src, *dst0, *dst; size_t srcleft0, srcleft, dstleft0, dstleft; size_t ninval; int error; ATF_REQUIRE_MSG(S->nsrc < sizeof(inbuf) - 2, "[%s]", title); ATF_REQUIRE_MSG(S->ndst < sizeof(outbuf) - 2, "[%s]", title); memset(inbuf, inguard, sizeof(inbuf)); memset(outbuf, outguard, sizeof(outbuf)); src = src0 = inbuf + 1; memcpy(src, S->src, nsrc); dst = dst0 = outbuf + 1; srcleft = srcleft0 = nsrc; dstleft = dstleft0 = ndst; C = iconv_open(S->dst_codeset, S->src_codeset); if (C == (iconv_t)-1) { error = errno; atf_tc_fail_nonfatal("[%s] iconv_open: %s (%d)", title, strerror(error), error); return; } ninval = iconv(C, &src, &srcleft, &dst, &dstleft); if (ninval == (size_t)-1) { error = errno; /* * Incomplete input manifests as EINVAL -- ignore that, * unless we're trying the full-size input. * * Truncated output manifests as E2BIG -- ignore that, * unless we're trying the full-size output. */ if ((error != EINVAL || nsrc == S->nsrc) && (error != E2BIG || ndst == S->ndst)) { atf_tc_fail_nonfatal("[%s] iconv: %s (%d)", title, strerror(error), error); goto next; } } else if (ninval != S->ninval) { error = errno; atf_tc_fail_nonfatal("[%s] iconv:" " %zu invalid, expected %zu", title, ninval, S->ninval); } ATF_CHECK_MSG(src0 <= src && src <= src0 + srcleft0, "[%s] iconv:" " src went from %p to %p, expected [%p,%p]", title, src0, src, src0, src0 + srcleft0); ATF_CHECK_MSG(srcleft <= srcleft0, "[%s] iconv:" " srcleft went from %zu to %zu", title, srcleft0, srcleft); ATF_CHECK_MSG(dst0 <= dst && dst <= dst0 + dstleft0, "[%s] iconv:" " dst went from %p to %p, expected [%p,%p]", title, dst0, dst, dst0, dst0 + dstleft0); ATF_CHECK_MSG(dstleft <= dstleft0, "[%s] iconv:" " dstleft went from %zu to %zu", title, dstleft0, dstleft); if (memcmp(dst0, S->dst, MIN(ndst, dstleft0 - dstleft)) != 0) { size_t k; atf_tc_fail_nonfatal("[%s] iconv: bad conv", title); fprintf(stderr, "[%s] input: ", title); for (k = 0; k < nsrc; k++) fprintf(stderr, " %02x", (unsigned char)S->src[k]); fprintf(stderr, "\n"); fprintf(stderr, "[%s] expected: ", title); for (k = 0; k < ndst; k++) fprintf(stderr, " %02x", (unsigned char)S->dst[k]); fprintf(stderr, "\n"); fprintf(stderr, "[%s] got: ", title); for (k = 0; k < ndst; k++) fprintf(stderr, " %02x", (unsigned char)dst0[k]); fprintf(stderr, "\n"); } next: if (dst0[-1] != outguard) { atf_tc_fail_nonfatal("[%s] iconv overran before buffer:" " dst0[-1] = 0x%02x, expected 0x%02x", title, dst0[-1], outguard); } if (dst0[ndst] != outguard) { atf_tc_fail_nonfatal("[%s] iconv overran after buffer:" " dst0[ndst=%zu] = 0x%02x, expected 0x%02x", title, ndst, dst0[ndst], outguard); } if (dst[0] != outguard) { atf_tc_fail_nonfatal("[%s] iconv overran past updated dst:" " dst[0] = 0x%02x, expected 0x%02x", title, dst[0], outguard); } if (iconv_close(C) == -1) { error = errno; atf_tc_fail_nonfatal("[%s] iconv_close: %s (%d)", title, strerror(error), error); } } static void test_sample(const char *title, const struct sample *S) { char buf[128]; size_t nsrc, ndst; fprintf(stderr, "test %s from %s to %s\n", title, S->src_codeset, S->dst_codeset); for (nsrc = 0; nsrc <= S->nsrc; nsrc++) { snprintf(buf, sizeof(buf), "%s %zu/%zu", title, nsrc, S->ndst); test_sample_bounded(buf, S, nsrc, S->ndst); } for (ndst = 0; ndst <= S->ndst; ndst++) { snprintf(buf, sizeof(buf), "%s %zu/%zu", title, S->nsrc, ndst); test_sample_bounded(buf, S, S->nsrc, ndst); } } ATF_TC(iconv_samples); ATF_TC_HEAD(iconv_samples, tc) { atf_tc_set_md_var(tc, "descr", "Test iconv on various fixed samples"); } ATF_TC_BODY(iconv_samples, tc) { unsigned i; for (i = 0; i < __arraycount(samples); i++) { const struct sample *S = &samples[i]; struct sample reverse = { .src_codeset = S->dst_codeset, .dst_codeset = S->src_codeset, .nsrc = S->ndst, .src = S->dst, .ndst = S->nsrc, .dst = S->src, .ninval = S->ninval_rev, }; char buf[128]; if (S->xfail) atf_tc_expect_fail("%s", S->xfail); snprintf(buf, sizeof(buf), "case %u: %s to %s", i, S->src_codeset, S->dst_codeset); test_sample(buf, S); if (S->ninval_rev != IRREVERSIBLE) { snprintf(buf, sizeof(buf), "case %u: %s to %s", i, S->dst_codeset, S->src_codeset); test_sample(buf, &reverse); } if (S->xfail) atf_tc_expect_pass(); } } ATF_TC(iconv_pr59019_hz8); ATF_TC_HEAD(iconv_pr59019_hz8, tc) { atf_tc_set_md_var(tc, "descr", "Truncated HZ8 input from PR 59019"); } ATF_TC_BODY(iconv_pr59019_hz8, tc) { const char title[] = "iconv_pr59019_hz8"; char in[4] = "\x7e\x7b\x7e\x7e"; /* ~{~~ */ char out[4096], guard = arc4random(); char *src0, *src, *dst0, *dst; size_t srcleft0, srcleft, dstleft0, dstleft; iconv_t C; size_t ninval; memset(out, guard, sizeof(out)); REQUIRE_LIBC((C = iconv_open(/*to*/"UTF-8", /*from*/"HZ8")), (iconv_t)-1); src = src0 = in; srcleft = srcleft0 = sizeof(in); dst = dst0 = out + 1; dstleft = dstleft0 = sizeof(out) - 2; ninval = iconv(C, &src, &srcleft, &dst, &dstleft); /* * XXX Not actually 100% sure this is the correct result -- I * can't find a reference for the HZ8 encoding. */ ATF_CHECK_EQ_MSG(ninval, (size_t)-1, "[%s] iconv: ninval=%zu", title, ninval); ATF_CHECK_MSG(src0 <= src && src <= src0 + srcleft0, "[%s] iconv:" " src went from %p to %p, expected [%p,%p)", title, src0, src, src0, src0 + srcleft0); ATF_CHECK_MSG(srcleft <= srcleft0, "[%s] iconv:" " srcleft went from %zu to %zu", title, srcleft0, srcleft); ATF_CHECK_MSG(dst0 <= dst && dst <= dst0 + dstleft0, "[%s] iconv:" " dst went from %p to %p, expected [%p,%p)", title, dst0, dst, dst0, dst0 + dstleft0); ATF_CHECK_MSG(dstleft <= dstleft0, "[%s] iconv:" " dstleft went from %zu to %zu", title, dstleft0, dstleft); ATF_CHECK_EQ(dst0[-1], guard); ATF_CHECK_EQ(dst0[dstleft0], guard); RL(iconv_close(C)); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, iconv_pr59019_hz8); ATF_TP_ADD_TC(tp, iconv_samples); return atf_no_error(); } @ 1.8.6.1 log @file t_iconv.c was added on branch netbsd-9 on 2026-07-03 18:13:19 +0000 @ text @d1 372 @ 1.8.6.2 log @Pull up following revision(s) (requested by riastradh in ticket #2030): lib/libc/citrus/modules/citrus_hz.c: revision 1.5 tests/lib/libc/locale/Makefile: revision 1.19 tests/lib/libc/locale/t_iconv.c: revision 1.1 distrib/sets/lists/tests/mi: revision 1.1423 tests/lib/libc/locale/t_iconv.c: revision 1.2 tests/lib/libc/locale/t_iconv.c: revision 1.3 tests/lib/libc/locale/t_iconv.c: revision 1.4 tests/lib/libc/locale/t_iconv.c: revision 1.5 tests/lib/libc/locale/t_iconv.c: revision 1.6 tests/lib/libc/locale/t_iconv.c: revision 1.7 tests/lib/libc/locale/t_iconv.c: revision 1.8 lib/libc/citrus/modules/citrus_utf7.c: revision 1.8 distrib/sets/lists/debug/mi: revision 1.515 lib/libc/citrus/modules/citrus_zw.c: revision 1.7 lib/libc/citrus/modules/citrus_viqr.c: revision 1.7 (all via patch) iconv(3): Draft some automatic tests. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Fix null pointer dereference with HZ8 encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Fix buffer overrun in UTF-7 encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Fix buffer overrun in VIQR encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Fix buffer overrun in ZW encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Add a test case for ISO-2022-CN. From Mark Johnston of FreeBSD. PR 59019: various iconv issues iconv(3): Expand ISO-2022-CN tests a little. This one is broken for a partial input case, not yet sure why. PR 59019: various iconv issues iconv(3): Fix printing bytes on test failure. Don't sign-extend to a 32-bit quantity causing the left to be padded with f's; just print the 8-bit quantity. PR 59019: various iconv issues @ text @a0 374 /* $NetBSD: t_iconv.c,v 1.8 2026/06/30 23:17:31 riastradh Exp $ */ /*- * Copyright (c) 2025 The NetBSD Foundation, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * iconv(3) */ #include __RCSID("$NetBSD: t_iconv.c,v 1.8 2026/06/30 23:17:31 riastradh Exp $"); #include #include #include #include #include #include #include #include "h_macros.h" static const struct sample { const char *src_codeset; size_t nsrc; const char *src; const char *dst_codeset; size_t ndst; const char *dst; size_t ninval; size_t ninval_rev; const char *xfail; #define IRREVERSIBLE ((size_t)-1) } samples[] = { [0] = { "us-ascii", 6, "hello", "us-ascii", 6, "hello", 0, 0, NULL }, /* LATIN SMALL LETTER E WITH ACUTE ACCENT */ [1] = { "iso-8859-1", 1, (const char[1]){0xe9}, "UTF-8", 2, (const char[2]){0xc3,0xa9}, 0, 0, NULL }, /* LEFT CURLY BRACKET */ [2] = { "UTF-8", 2, (const char[2]){0x00,0x7b}, "ZW", 6, (const char[6]){0x00,0x7a,0x57,0x20,0x7b,0x0a}, 0, 0, NULL }, /* LATIN SMALL LETTER O, TILDE */ [3] = { "UTF-8", 2, (const char[2]){0x4f,0x7e}, "VIQR", 3, (const char[3]){0x4f,0x5c,0x7e}, 0, 0, NULL }, /* LEFT CURLY BRACKET (optionally encoded in UTF-7) */ [4] = { "UTF-7", 1, (const char[1]){0x7b}, "UTF-8", 1, (const char[1]){0x7b}, 0, IRREVERSIBLE, NULL }, [5] = { "UTF-7", 4, "+AHs-", "UTF-8", 1, (const char[1]){0x7b}, 0, 0, NULL }, /* éclair */ [6] = { "UTF-7", 10, "+AOk-clair", "UTF-8", 7, (const char[7]){ 0xc3,0xa9,0x63,0x6c,0x61,0x69,0x72, }, 0, 0, NULL }, [7] = { "HZ", 55, /* RFC 1843, Sec. 4, Example 1 */ "The next sentence is in GB.~{<:Ky2;S{#,NpJ)l6HK!#~}Bye.", "UTF-8", 61, (const char[61]) { 0x54,0x68,0x65,0x20, 0x6e,0x65,0x78,0x74, 0x20,0x73,0x65,0x6e, 0x74,0x65,0x6e,0x63, 0x65,0x20,0x69,0x73, 0x20,0x69,0x6e,0x20, 0x47,0x42,0x2e,0xe5, 0xb7,0xb1,0xe6,0x89, 0x80,0xe4,0xb8,0x8d, 0xe6,0xac,0xb2,0xef, 0xbc,0x8c,0xe5,0x8b, 0xbf,0xe6,0x96,0xbd, 0xe6,0x96,0xbc,0xe4, 0xba,0xba,0xe3,0x80, 0x82,0x42,0x79,0x65, 0x2e }, 0, 0, NULL }, /* Same as above but with HZ8 instead of HZ. */ [8] = { "HZ8", 55, (const char[55]) { 0x54,0x68,0x65,0x20,0x6e,0x65,0x78,0x74, 0x20,0x73,0x65,0x6e,0x74,0x65,0x6e,0x63, 0x65,0x20,0x69,0x73,0x20,0x69,0x6e,0x20, 0x47,0x42,0x2e,0x7e,0x7b,0xbc,0xba,0xcb, 0xf9,0xb2,0xbb,0xd3,0xfb,0xa3,0xac,0xce, 0xf0,0xca,0xa9,0xec,0xb6,0xc8,0xcb,0xa1, 0xa3,0x7e,0x7d,0x42,0x79,0x65,0x2e }, "UTF-8", 61, (const char[61]) { 0x54,0x68,0x65,0x20, 0x6e,0x65,0x78,0x74, 0x20,0x73,0x65,0x6e, 0x74,0x65,0x6e,0x63, 0x65,0x20,0x69,0x73, 0x20,0x69,0x6e,0x20, 0x47,0x42,0x2e,0xe5, 0xb7,0xb1,0xe6,0x89, 0x80,0xe4,0xb8,0x8d, 0xe6,0xac,0xb2,0xef, 0xbc,0x8c,0xe5,0x8b, 0xbf,0xe6,0x96,0xbd, 0xe6,0x96,0xbc,0xe4, 0xba,0xba,0xe3,0x80, 0x82,0x42,0x79,0x65, 0x2e }, 0, 0, NULL }, /* 馬 from CNS 11643-1 */ [9] = { "UTF-8", 3, (const char[3]){0xe9,0xa6,0xac}, "ISO-2022-CN", 8, (const char[8]){0x1b,0x24,0x29,0x47,0x0e,0x58,0x6b,0x0f}, 0, 0, NULL }, /* 馬毦 shifting from CNS 11643-1 to CNS 11643-2 */ [10] = { "UTF-8", 6, (const char[6]){0xe9,0xa6,0xac,0xe6,0xaf,0xa6}, "ISO-2022-CN", 16, (const char[16]){ /* ESC $ ) G (shift G1 to CNS 11643 plane 1) */ 0x1b,0x24,0x29,0x47, 0x0e, /* GL is G1 from now on */ 0x58,0x6b, /* 馬 */ /* ESC $ * H (shift G2 to CNS 11643 plane 2) */ 0x1b,0x24,0x2a,0x48, 0x1b,0x4e, /* GL is G2 for next char */ 0x30,0x21, /* 毦 */ 0x0f, /* GL is G0 from now on */ }, 0, 0, "PR lib/59019: various iconv issues ([case 10: ISO-2022-CN to UTF-8 14/6] iconv: Illegal byte sequence (85))" }, }; #define MIN(x, y) ((x) < (y) ? (x) : (y)) static void test_sample_bounded(const char *title, const struct sample *S, size_t nsrc, size_t ndst) { char inbuf[4096], inguard = arc4random(); char outbuf[4096], outguard = arc4random(); iconv_t C; const char *src0, *src; char *dst0, *dst; size_t srcleft0, srcleft, dstleft0, dstleft; size_t ninval; int error; ATF_REQUIRE_MSG(S->nsrc < sizeof(inbuf) - 2, "[%s]", title); ATF_REQUIRE_MSG(S->ndst < sizeof(outbuf) - 2, "[%s]", title); memset(inbuf, inguard, sizeof(inbuf)); memset(outbuf, outguard, sizeof(outbuf)); src = src0 = inbuf + 1; memcpy(inbuf + 1, S->src, nsrc); dst = dst0 = outbuf + 1; srcleft = srcleft0 = nsrc; dstleft = dstleft0 = ndst; C = iconv_open(S->dst_codeset, S->src_codeset); if (C == (iconv_t)-1) { error = errno; atf_tc_fail_nonfatal("[%s] iconv_open: %s (%d)", title, strerror(error), error); return; } ninval = iconv(C, &src, &srcleft, &dst, &dstleft); if (ninval == (size_t)-1) { error = errno; /* * Incomplete input manifests as EINVAL -- ignore that, * unless we're trying the full-size input. * * Truncated output manifests as E2BIG -- ignore that, * unless we're trying the full-size output. */ if ((error != EINVAL || nsrc == S->nsrc) && (error != E2BIG || ndst == S->ndst)) { atf_tc_fail_nonfatal("[%s] iconv: %s (%d)", title, strerror(error), error); goto next; } } else if (ninval != S->ninval) { error = errno; atf_tc_fail_nonfatal("[%s] iconv:" " %zu invalid, expected %zu", title, ninval, S->ninval); } ATF_CHECK_MSG(src0 <= src && src <= src0 + srcleft0, "[%s] iconv:" " src went from %p to %p, expected [%p,%p]", title, src0, src, src0, src0 + srcleft0); ATF_CHECK_MSG(srcleft <= srcleft0, "[%s] iconv:" " srcleft went from %zu to %zu", title, srcleft0, srcleft); ATF_CHECK_MSG(dst0 <= dst && dst <= dst0 + dstleft0, "[%s] iconv:" " dst went from %p to %p, expected [%p,%p]", title, dst0, dst, dst0, dst0 + dstleft0); ATF_CHECK_MSG(dstleft <= dstleft0, "[%s] iconv:" " dstleft went from %zu to %zu", title, dstleft0, dstleft); if (memcmp(dst0, S->dst, MIN(ndst, dstleft0 - dstleft)) != 0) { size_t k; atf_tc_fail_nonfatal("[%s] iconv: bad conv", title); fprintf(stderr, "[%s] input: ", title); for (k = 0; k < nsrc; k++) fprintf(stderr, " %02x", (unsigned char)S->src[k]); fprintf(stderr, "\n"); fprintf(stderr, "[%s] expected: ", title); for (k = 0; k < ndst; k++) fprintf(stderr, " %02x", (unsigned char)S->dst[k]); fprintf(stderr, "\n"); fprintf(stderr, "[%s] got: ", title); for (k = 0; k < ndst; k++) fprintf(stderr, " %02x", (unsigned char)dst0[k]); fprintf(stderr, "\n"); } next: if (dst0[-1] != outguard) { atf_tc_fail_nonfatal("[%s] iconv overran before buffer:" " dst0[-1] = 0x%02x, expected 0x%02x", title, dst0[-1], outguard); } if (dst0[ndst] != outguard) { atf_tc_fail_nonfatal("[%s] iconv overran after buffer:" " dst0[ndst=%zu] = 0x%02x, expected 0x%02x", title, ndst, dst0[ndst], outguard); } if (dst[0] != outguard) { atf_tc_fail_nonfatal("[%s] iconv overran past updated dst:" " dst[0] = 0x%02x, expected 0x%02x", title, dst[0], outguard); } if (iconv_close(C) == -1) { error = errno; atf_tc_fail_nonfatal("[%s] iconv_close: %s (%d)", title, strerror(error), error); } } static void test_sample(const char *title, const struct sample *S) { char buf[128]; size_t nsrc, ndst; fprintf(stderr, "test %s from %s to %s\n", title, S->src_codeset, S->dst_codeset); for (nsrc = 0; nsrc <= S->nsrc; nsrc++) { snprintf(buf, sizeof(buf), "%s %zu/%zu", title, nsrc, S->ndst); test_sample_bounded(buf, S, nsrc, S->ndst); } for (ndst = 0; ndst <= S->ndst; ndst++) { snprintf(buf, sizeof(buf), "%s %zu/%zu", title, S->nsrc, ndst); test_sample_bounded(buf, S, S->nsrc, ndst); } } ATF_TC(iconv_samples); ATF_TC_HEAD(iconv_samples, tc) { atf_tc_set_md_var(tc, "descr", "Test iconv on various fixed samples"); } ATF_TC_BODY(iconv_samples, tc) { unsigned i; for (i = 0; i < __arraycount(samples); i++) { const struct sample *S = &samples[i]; struct sample reverse = { .src_codeset = S->dst_codeset, .dst_codeset = S->src_codeset, .nsrc = S->ndst, .src = S->dst, .ndst = S->nsrc, .dst = S->src, .ninval = S->ninval_rev, }; char buf[128]; if (S->xfail) atf_tc_expect_fail("%s", S->xfail); snprintf(buf, sizeof(buf), "case %u: %s to %s", i, S->src_codeset, S->dst_codeset); test_sample(buf, S); if (S->ninval_rev != IRREVERSIBLE) { snprintf(buf, sizeof(buf), "case %u: %s to %s", i, S->dst_codeset, S->src_codeset); test_sample(buf, &reverse); } if (S->xfail) atf_tc_expect_pass(); } } ATF_TC(iconv_pr59019_hz8); ATF_TC_HEAD(iconv_pr59019_hz8, tc) { atf_tc_set_md_var(tc, "descr", "Truncated HZ8 input from PR 59019"); } ATF_TC_BODY(iconv_pr59019_hz8, tc) { const char title[] = "iconv_pr59019_hz8"; char in[4] = "\x7e\x7b\x7e\x7e"; /* ~{~~ */ char out[4096], guard = arc4random(); const char *src0, *src; char *dst0, *dst; size_t srcleft0, srcleft, dstleft0, dstleft; iconv_t C; size_t ninval; memset(out, guard, sizeof(out)); REQUIRE_LIBC((C = iconv_open(/*to*/"UTF-8", /*from*/"HZ8")), (iconv_t)-1); src = src0 = in; srcleft = srcleft0 = sizeof(in); dst = dst0 = out + 1; dstleft = dstleft0 = sizeof(out) - 2; ninval = iconv(C, &src, &srcleft, &dst, &dstleft); /* * XXX Not actually 100% sure this is the correct result -- I * can't find a reference for the HZ8 encoding. */ ATF_CHECK_EQ_MSG(ninval, (size_t)-1, "[%s] iconv: ninval=%zu", title, ninval); ATF_CHECK_MSG(src0 <= src && src <= src0 + srcleft0, "[%s] iconv:" " src went from %p to %p, expected [%p,%p)", title, src0, src, src0, src0 + srcleft0); ATF_CHECK_MSG(srcleft <= srcleft0, "[%s] iconv:" " srcleft went from %zu to %zu", title, srcleft0, srcleft); ATF_CHECK_MSG(dst0 <= dst && dst <= dst0 + dstleft0, "[%s] iconv:" " dst went from %p to %p, expected [%p,%p)", title, dst0, dst, dst0, dst0 + dstleft0); ATF_CHECK_MSG(dstleft <= dstleft0, "[%s] iconv:" " dstleft went from %zu to %zu", title, dstleft0, dstleft); ATF_CHECK_EQ(dst0[-1], guard); ATF_CHECK_EQ(dst0[dstleft0], guard); RL(iconv_close(C)); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, iconv_pr59019_hz8); ATF_TP_ADD_TC(tp, iconv_samples); return atf_no_error(); } @ 1.8.4.1 log @file t_iconv.c was added on branch netbsd-10 on 2026-07-03 18:06:57 +0000 @ text @d1 372 @ 1.8.4.2 log @Pull up following revision(s) (requested by riastradh in ticket #1301): lib/libc/citrus/modules/citrus_hz.c: revision 1.5 tests/lib/libc/locale/Makefile: revision 1.19 tests/lib/libc/locale/t_iconv.c: revision 1.1 distrib/sets/lists/tests/mi: revision 1.1423 tests/lib/libc/locale/t_iconv.c: revision 1.2 tests/lib/libc/locale/t_iconv.c: revision 1.3 tests/lib/libc/locale/t_iconv.c: revision 1.4 tests/lib/libc/locale/t_iconv.c: revision 1.5 tests/lib/libc/locale/t_iconv.c: revision 1.6 tests/lib/libc/locale/t_iconv.c: revision 1.7 tests/lib/libc/locale/t_iconv.c: revision 1.8 lib/libc/citrus/modules/citrus_utf7.c: revision 1.8 distrib/sets/lists/debug/mi: revision 1.515 lib/libc/citrus/modules/citrus_zw.c: revision 1.7 lib/libc/citrus/modules/citrus_viqr.c: revision 1.7 iconv(3): Draft some automatic tests. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Fix null pointer dereference with HZ8 encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Fix buffer overrun in UTF-7 encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Fix buffer overrun in VIQR encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Fix buffer overrun in ZW encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Add a test case for ISO-2022-CN. From Mark Johnston of FreeBSD. PR 59019: various iconv issues iconv(3): Expand ISO-2022-CN tests a little. This one is broken for a partial input case, not yet sure why. PR 59019: various iconv issues iconv(3): Fix printing bytes on test failure. Don't sign-extend to a 32-bit quantity causing the left to be padded with f's; just print the 8-bit quantity. PR 59019: various iconv issues @ text @a0 372 /* $NetBSD: t_iconv.c,v 1.1 2026/06/30 23:14:39 riastradh Exp $ */ /*- * Copyright (c) 2025 The NetBSD Foundation, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * iconv(3) */ #include __RCSID("$NetBSD: t_iconv.c,v 1.1 2026/06/30 23:14:39 riastradh Exp $"); #include #include #include #include #include #include #include #include "h_macros.h" static const struct sample { const char *src_codeset; size_t nsrc; const char *src; const char *dst_codeset; size_t ndst; const char *dst; size_t ninval; size_t ninval_rev; const char *xfail; #define IRREVERSIBLE ((size_t)-1) } samples[] = { [0] = { "us-ascii", 6, "hello", "us-ascii", 6, "hello", 0, 0, NULL }, /* LATIN SMALL LETTER E WITH ACUTE ACCENT */ [1] = { "iso-8859-1", 1, (const char[1]){0xe9}, "UTF-8", 2, (const char[2]){0xc3,0xa9}, 0, 0, NULL }, /* LEFT CURLY BRACKET */ [2] = { "UTF-8", 2, (const char[2]){0x00,0x7b}, "ZW", 6, (const char[6]){0x00,0x7a,0x57,0x20,0x7b,0x0a}, 0, 0, NULL }, /* LATIN SMALL LETTER O, TILDE */ [3] = { "UTF-8", 2, (const char[2]){0x4f,0x7e}, "VIQR", 3, (const char[3]){0x4f,0x5c,0x7e}, 0, 0, NULL }, /* LEFT CURLY BRACKET (optionally encoded in UTF-7) */ [4] = { "UTF-7", 1, (const char[1]){0x7b}, "UTF-8", 1, (const char[1]){0x7b}, 0, IRREVERSIBLE, NULL }, [5] = { "UTF-7", 4, "+AHs-", "UTF-8", 1, (const char[1]){0x7b}, 0, 0, NULL }, /* éclair */ [6] = { "UTF-7", 10, "+AOk-clair", "UTF-8", 7, (const char[7]){ 0xc3,0xa9,0x63,0x6c,0x61,0x69,0x72, }, 0, 0, NULL }, [7] = { "HZ", 55, /* RFC 1843, Sec. 4, Example 1 */ "The next sentence is in GB.~{<:Ky2;S{#,NpJ)l6HK!#~}Bye.", "UTF-8", 61, (const char[61]) { 0x54,0x68,0x65,0x20, 0x6e,0x65,0x78,0x74, 0x20,0x73,0x65,0x6e, 0x74,0x65,0x6e,0x63, 0x65,0x20,0x69,0x73, 0x20,0x69,0x6e,0x20, 0x47,0x42,0x2e,0xe5, 0xb7,0xb1,0xe6,0x89, 0x80,0xe4,0xb8,0x8d, 0xe6,0xac,0xb2,0xef, 0xbc,0x8c,0xe5,0x8b, 0xbf,0xe6,0x96,0xbd, 0xe6,0x96,0xbc,0xe4, 0xba,0xba,0xe3,0x80, 0x82,0x42,0x79,0x65, 0x2e }, 0, 0, NULL }, /* Same as above but with HZ8 instead of HZ. */ [8] = { "HZ8", 55, (const char[55]) { 0x54,0x68,0x65,0x20,0x6e,0x65,0x78,0x74, 0x20,0x73,0x65,0x6e,0x74,0x65,0x6e,0x63, 0x65,0x20,0x69,0x73,0x20,0x69,0x6e,0x20, 0x47,0x42,0x2e,0x7e,0x7b,0xbc,0xba,0xcb, 0xf9,0xb2,0xbb,0xd3,0xfb,0xa3,0xac,0xce, 0xf0,0xca,0xa9,0xec,0xb6,0xc8,0xcb,0xa1, 0xa3,0x7e,0x7d,0x42,0x79,0x65,0x2e }, "UTF-8", 61, (const char[61]) { 0x54,0x68,0x65,0x20, 0x6e,0x65,0x78,0x74, 0x20,0x73,0x65,0x6e, 0x74,0x65,0x6e,0x63, 0x65,0x20,0x69,0x73, 0x20,0x69,0x6e,0x20, 0x47,0x42,0x2e,0xe5, 0xb7,0xb1,0xe6,0x89, 0x80,0xe4,0xb8,0x8d, 0xe6,0xac,0xb2,0xef, 0xbc,0x8c,0xe5,0x8b, 0xbf,0xe6,0x96,0xbd, 0xe6,0x96,0xbc,0xe4, 0xba,0xba,0xe3,0x80, 0x82,0x42,0x79,0x65, 0x2e }, 0, 0, NULL }, /* 馬 from CNS 11643-1 */ [9] = { "UTF-8", 3, (const char[3]){0xe9,0xa6,0xac}, "ISO-2022-CN", 8, (const char[8]){0x1b,0x24,0x29,0x47,0x0e,0x58,0x6b,0x0f}, 0, 0, NULL }, /* 馬毦 shifting from CNS 11643-1 to CNS 11643-2 */ [10] = { "UTF-8", 6, (const char[6]){0xe9,0xa6,0xac,0xe6,0xaf,0xa6}, "ISO-2022-CN", 16, (const char[16]){ /* ESC $ ) G (shift G1 to CNS 11643 plane 1) */ 0x1b,0x24,0x29,0x47, 0x0e, /* GL is G1 from now on */ 0x58,0x6b, /* 馬 */ /* ESC $ * H (shift G2 to CNS 11643 plane 2) */ 0x1b,0x24,0x2a,0x48, 0x1b,0x4e, /* GL is G2 for next char */ 0x30,0x21, /* 毦 */ 0x0f, /* GL is G0 from now on */ }, 0, 0, "PR lib/59019: various iconv issues ([case 10: ISO-2022-CN to UTF-8 14/6] iconv: Illegal byte sequence (85))" }, }; #define MIN(x, y) ((x) < (y) ? (x) : (y)) static void test_sample_bounded(const char *title, const struct sample *S, size_t nsrc, size_t ndst) { char inbuf[4096], inguard = arc4random(); char outbuf[4096], outguard = arc4random(); iconv_t C; char *src0, *src, *dst0, *dst; size_t srcleft0, srcleft, dstleft0, dstleft; size_t ninval; int error; ATF_REQUIRE_MSG(S->nsrc < sizeof(inbuf) - 2, "[%s]", title); ATF_REQUIRE_MSG(S->ndst < sizeof(outbuf) - 2, "[%s]", title); memset(inbuf, inguard, sizeof(inbuf)); memset(outbuf, outguard, sizeof(outbuf)); src = src0 = inbuf + 1; memcpy(src, S->src, nsrc); dst = dst0 = outbuf + 1; srcleft = srcleft0 = nsrc; dstleft = dstleft0 = ndst; C = iconv_open(S->dst_codeset, S->src_codeset); if (C == (iconv_t)-1) { error = errno; atf_tc_fail_nonfatal("[%s] iconv_open: %s (%d)", title, strerror(error), error); return; } ninval = iconv(C, &src, &srcleft, &dst, &dstleft); if (ninval == (size_t)-1) { error = errno; /* * Incomplete input manifests as EINVAL -- ignore that, * unless we're trying the full-size input. * * Truncated output manifests as E2BIG -- ignore that, * unless we're trying the full-size output. */ if ((error != EINVAL || nsrc == S->nsrc) && (error != E2BIG || ndst == S->ndst)) { atf_tc_fail_nonfatal("[%s] iconv: %s (%d)", title, strerror(error), error); goto next; } } else if (ninval != S->ninval) { error = errno; atf_tc_fail_nonfatal("[%s] iconv:" " %zu invalid, expected %zu", title, ninval, S->ninval); } ATF_CHECK_MSG(src0 <= src && src <= src0 + srcleft0, "[%s] iconv:" " src went from %p to %p, expected [%p,%p]", title, src0, src, src0, src0 + srcleft0); ATF_CHECK_MSG(srcleft <= srcleft0, "[%s] iconv:" " srcleft went from %zu to %zu", title, srcleft0, srcleft); ATF_CHECK_MSG(dst0 <= dst && dst <= dst0 + dstleft0, "[%s] iconv:" " dst went from %p to %p, expected [%p,%p]", title, dst0, dst, dst0, dst0 + dstleft0); ATF_CHECK_MSG(dstleft <= dstleft0, "[%s] iconv:" " dstleft went from %zu to %zu", title, dstleft0, dstleft); if (memcmp(dst0, S->dst, MIN(ndst, dstleft0 - dstleft)) != 0) { size_t k; atf_tc_fail_nonfatal("[%s] iconv: bad conv", title); fprintf(stderr, "[%s] input: ", title); for (k = 0; k < nsrc; k++) fprintf(stderr, " %02x", (unsigned char)S->src[k]); fprintf(stderr, "\n"); fprintf(stderr, "[%s] expected: ", title); for (k = 0; k < ndst; k++) fprintf(stderr, " %02x", (unsigned char)S->dst[k]); fprintf(stderr, "\n"); fprintf(stderr, "[%s] got: ", title); for (k = 0; k < ndst; k++) fprintf(stderr, " %02x", (unsigned char)dst0[k]); fprintf(stderr, "\n"); } next: if (dst0[-1] != outguard) { atf_tc_fail_nonfatal("[%s] iconv overran before buffer:" " dst0[-1] = 0x%02x, expected 0x%02x", title, dst0[-1], outguard); } if (dst0[ndst] != outguard) { atf_tc_fail_nonfatal("[%s] iconv overran after buffer:" " dst0[ndst=%zu] = 0x%02x, expected 0x%02x", title, ndst, dst0[ndst], outguard); } if (dst[0] != outguard) { atf_tc_fail_nonfatal("[%s] iconv overran past updated dst:" " dst[0] = 0x%02x, expected 0x%02x", title, dst[0], outguard); } if (iconv_close(C) == -1) { error = errno; atf_tc_fail_nonfatal("[%s] iconv_close: %s (%d)", title, strerror(error), error); } } static void test_sample(const char *title, const struct sample *S) { char buf[128]; size_t nsrc, ndst; fprintf(stderr, "test %s from %s to %s\n", title, S->src_codeset, S->dst_codeset); for (nsrc = 0; nsrc <= S->nsrc; nsrc++) { snprintf(buf, sizeof(buf), "%s %zu/%zu", title, nsrc, S->ndst); test_sample_bounded(buf, S, nsrc, S->ndst); } for (ndst = 0; ndst <= S->ndst; ndst++) { snprintf(buf, sizeof(buf), "%s %zu/%zu", title, S->nsrc, ndst); test_sample_bounded(buf, S, S->nsrc, ndst); } } ATF_TC(iconv_samples); ATF_TC_HEAD(iconv_samples, tc) { atf_tc_set_md_var(tc, "descr", "Test iconv on various fixed samples"); } ATF_TC_BODY(iconv_samples, tc) { unsigned i; for (i = 0; i < __arraycount(samples); i++) { const struct sample *S = &samples[i]; struct sample reverse = { .src_codeset = S->dst_codeset, .dst_codeset = S->src_codeset, .nsrc = S->ndst, .src = S->dst, .ndst = S->nsrc, .dst = S->src, .ninval = S->ninval_rev, }; char buf[128]; if (S->xfail) atf_tc_expect_fail("%s", S->xfail); snprintf(buf, sizeof(buf), "case %u: %s to %s", i, S->src_codeset, S->dst_codeset); test_sample(buf, S); if (S->ninval_rev != IRREVERSIBLE) { snprintf(buf, sizeof(buf), "case %u: %s to %s", i, S->dst_codeset, S->src_codeset); test_sample(buf, &reverse); } if (S->xfail) atf_tc_expect_pass(); } } ATF_TC(iconv_pr59019_hz8); ATF_TC_HEAD(iconv_pr59019_hz8, tc) { atf_tc_set_md_var(tc, "descr", "Truncated HZ8 input from PR 59019"); } ATF_TC_BODY(iconv_pr59019_hz8, tc) { const char title[] = "iconv_pr59019_hz8"; char in[4] = "\x7e\x7b\x7e\x7e"; /* ~{~~ */ char out[4096], guard = arc4random(); char *src0, *src, *dst0, *dst; size_t srcleft0, srcleft, dstleft0, dstleft; iconv_t C; size_t ninval; memset(out, guard, sizeof(out)); REQUIRE_LIBC((C = iconv_open(/*to*/"UTF-8", /*from*/"HZ8")), (iconv_t)-1); src = src0 = in; srcleft = srcleft0 = sizeof(in); dst = dst0 = out + 1; dstleft = dstleft0 = sizeof(out) - 2; ninval = iconv(C, &src, &srcleft, &dst, &dstleft); /* * XXX Not actually 100% sure this is the correct result -- I * can't find a reference for the HZ8 encoding. */ ATF_CHECK_EQ_MSG(ninval, (size_t)-1, "[%s] iconv: ninval=%zu", title, ninval); ATF_CHECK_MSG(src0 <= src && src <= src0 + srcleft0, "[%s] iconv:" " src went from %p to %p, expected [%p,%p)", title, src0, src, src0, src0 + srcleft0); ATF_CHECK_MSG(srcleft <= srcleft0, "[%s] iconv:" " srcleft went from %zu to %zu", title, srcleft0, srcleft); ATF_CHECK_MSG(dst0 <= dst && dst <= dst0 + dstleft0, "[%s] iconv:" " dst went from %p to %p, expected [%p,%p)", title, dst0, dst, dst0, dst0 + dstleft0); ATF_CHECK_MSG(dstleft <= dstleft0, "[%s] iconv:" " dstleft went from %zu to %zu", title, dstleft0, dstleft); ATF_CHECK_EQ(dst0[-1], guard); ATF_CHECK_EQ(dst0[dstleft0], guard); RL(iconv_close(C)); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, iconv_pr59019_hz8); ATF_TP_ADD_TC(tp, iconv_samples); return atf_no_error(); } @ 1.8.2.1 log @file t_iconv.c was added on branch netbsd-11 on 2026-07-03 18:02:14 +0000 @ text @d1 372 @ 1.8.2.2 log @Pull up following revision(s) (requested by riastradh in ticket #361): lib/libc/citrus/modules/citrus_hz.c: revision 1.5 tests/lib/libc/locale/Makefile: revision 1.19 tests/lib/libc/locale/t_iconv.c: revision 1.1 distrib/sets/lists/tests/mi: revision 1.1423 tests/lib/libc/locale/t_iconv.c: revision 1.2 tests/lib/libc/locale/t_iconv.c: revision 1.3 tests/lib/libc/locale/t_iconv.c: revision 1.4 tests/lib/libc/locale/t_iconv.c: revision 1.5 tests/lib/libc/locale/t_iconv.c: revision 1.6 tests/lib/libc/locale/t_iconv.c: revision 1.7 tests/lib/libc/locale/t_iconv.c: revision 1.8 lib/libc/citrus/modules/citrus_utf7.c: revision 1.8 distrib/sets/lists/debug/mi: revision 1.515 lib/libc/citrus/modules/citrus_zw.c: revision 1.7 lib/libc/citrus/modules/citrus_viqr.c: revision 1.7 iconv(3): Draft some automatic tests. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Fix null pointer dereference with HZ8 encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Fix buffer overrun in UTF-7 encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Fix buffer overrun in VIQR encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Fix buffer overrun in ZW encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues iconv(3): Add a test case for ISO-2022-CN. From Mark Johnston of FreeBSD. PR 59019: various iconv issues iconv(3): Expand ISO-2022-CN tests a little. This one is broken for a partial input case, not yet sure why. PR 59019: various iconv issues iconv(3): Fix printing bytes on test failure. Don't sign-extend to a 32-bit quantity causing the left to be padded with f's; just print the 8-bit quantity. PR 59019: various iconv issues @ text @a0 372 /* $NetBSD: t_iconv.c,v 1.1 2026/06/30 23:14:39 riastradh Exp $ */ /*- * Copyright (c) 2025 The NetBSD Foundation, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * iconv(3) */ #include __RCSID("$NetBSD: t_iconv.c,v 1.1 2026/06/30 23:14:39 riastradh Exp $"); #include #include #include #include #include #include #include #include "h_macros.h" static const struct sample { const char *src_codeset; size_t nsrc; const char *src; const char *dst_codeset; size_t ndst; const char *dst; size_t ninval; size_t ninval_rev; const char *xfail; #define IRREVERSIBLE ((size_t)-1) } samples[] = { [0] = { "us-ascii", 6, "hello", "us-ascii", 6, "hello", 0, 0, NULL }, /* LATIN SMALL LETTER E WITH ACUTE ACCENT */ [1] = { "iso-8859-1", 1, (const char[1]){0xe9}, "UTF-8", 2, (const char[2]){0xc3,0xa9}, 0, 0, NULL }, /* LEFT CURLY BRACKET */ [2] = { "UTF-8", 2, (const char[2]){0x00,0x7b}, "ZW", 6, (const char[6]){0x00,0x7a,0x57,0x20,0x7b,0x0a}, 0, 0, NULL }, /* LATIN SMALL LETTER O, TILDE */ [3] = { "UTF-8", 2, (const char[2]){0x4f,0x7e}, "VIQR", 3, (const char[3]){0x4f,0x5c,0x7e}, 0, 0, NULL }, /* LEFT CURLY BRACKET (optionally encoded in UTF-7) */ [4] = { "UTF-7", 1, (const char[1]){0x7b}, "UTF-8", 1, (const char[1]){0x7b}, 0, IRREVERSIBLE, NULL }, [5] = { "UTF-7", 4, "+AHs-", "UTF-8", 1, (const char[1]){0x7b}, 0, 0, NULL }, /* éclair */ [6] = { "UTF-7", 10, "+AOk-clair", "UTF-8", 7, (const char[7]){ 0xc3,0xa9,0x63,0x6c,0x61,0x69,0x72, }, 0, 0, NULL }, [7] = { "HZ", 55, /* RFC 1843, Sec. 4, Example 1 */ "The next sentence is in GB.~{<:Ky2;S{#,NpJ)l6HK!#~}Bye.", "UTF-8", 61, (const char[61]) { 0x54,0x68,0x65,0x20, 0x6e,0x65,0x78,0x74, 0x20,0x73,0x65,0x6e, 0x74,0x65,0x6e,0x63, 0x65,0x20,0x69,0x73, 0x20,0x69,0x6e,0x20, 0x47,0x42,0x2e,0xe5, 0xb7,0xb1,0xe6,0x89, 0x80,0xe4,0xb8,0x8d, 0xe6,0xac,0xb2,0xef, 0xbc,0x8c,0xe5,0x8b, 0xbf,0xe6,0x96,0xbd, 0xe6,0x96,0xbc,0xe4, 0xba,0xba,0xe3,0x80, 0x82,0x42,0x79,0x65, 0x2e }, 0, 0, NULL }, /* Same as above but with HZ8 instead of HZ. */ [8] = { "HZ8", 55, (const char[55]) { 0x54,0x68,0x65,0x20,0x6e,0x65,0x78,0x74, 0x20,0x73,0x65,0x6e,0x74,0x65,0x6e,0x63, 0x65,0x20,0x69,0x73,0x20,0x69,0x6e,0x20, 0x47,0x42,0x2e,0x7e,0x7b,0xbc,0xba,0xcb, 0xf9,0xb2,0xbb,0xd3,0xfb,0xa3,0xac,0xce, 0xf0,0xca,0xa9,0xec,0xb6,0xc8,0xcb,0xa1, 0xa3,0x7e,0x7d,0x42,0x79,0x65,0x2e }, "UTF-8", 61, (const char[61]) { 0x54,0x68,0x65,0x20, 0x6e,0x65,0x78,0x74, 0x20,0x73,0x65,0x6e, 0x74,0x65,0x6e,0x63, 0x65,0x20,0x69,0x73, 0x20,0x69,0x6e,0x20, 0x47,0x42,0x2e,0xe5, 0xb7,0xb1,0xe6,0x89, 0x80,0xe4,0xb8,0x8d, 0xe6,0xac,0xb2,0xef, 0xbc,0x8c,0xe5,0x8b, 0xbf,0xe6,0x96,0xbd, 0xe6,0x96,0xbc,0xe4, 0xba,0xba,0xe3,0x80, 0x82,0x42,0x79,0x65, 0x2e }, 0, 0, NULL }, /* 馬 from CNS 11643-1 */ [9] = { "UTF-8", 3, (const char[3]){0xe9,0xa6,0xac}, "ISO-2022-CN", 8, (const char[8]){0x1b,0x24,0x29,0x47,0x0e,0x58,0x6b,0x0f}, 0, 0, NULL }, /* 馬毦 shifting from CNS 11643-1 to CNS 11643-2 */ [10] = { "UTF-8", 6, (const char[6]){0xe9,0xa6,0xac,0xe6,0xaf,0xa6}, "ISO-2022-CN", 16, (const char[16]){ /* ESC $ ) G (shift G1 to CNS 11643 plane 1) */ 0x1b,0x24,0x29,0x47, 0x0e, /* GL is G1 from now on */ 0x58,0x6b, /* 馬 */ /* ESC $ * H (shift G2 to CNS 11643 plane 2) */ 0x1b,0x24,0x2a,0x48, 0x1b,0x4e, /* GL is G2 for next char */ 0x30,0x21, /* 毦 */ 0x0f, /* GL is G0 from now on */ }, 0, 0, "PR lib/59019: various iconv issues ([case 10: ISO-2022-CN to UTF-8 14/6] iconv: Illegal byte sequence (85))" }, }; #define MIN(x, y) ((x) < (y) ? (x) : (y)) static void test_sample_bounded(const char *title, const struct sample *S, size_t nsrc, size_t ndst) { char inbuf[4096], inguard = arc4random(); char outbuf[4096], outguard = arc4random(); iconv_t C; char *src0, *src, *dst0, *dst; size_t srcleft0, srcleft, dstleft0, dstleft; size_t ninval; int error; ATF_REQUIRE_MSG(S->nsrc < sizeof(inbuf) - 2, "[%s]", title); ATF_REQUIRE_MSG(S->ndst < sizeof(outbuf) - 2, "[%s]", title); memset(inbuf, inguard, sizeof(inbuf)); memset(outbuf, outguard, sizeof(outbuf)); src = src0 = inbuf + 1; memcpy(src, S->src, nsrc); dst = dst0 = outbuf + 1; srcleft = srcleft0 = nsrc; dstleft = dstleft0 = ndst; C = iconv_open(S->dst_codeset, S->src_codeset); if (C == (iconv_t)-1) { error = errno; atf_tc_fail_nonfatal("[%s] iconv_open: %s (%d)", title, strerror(error), error); return; } ninval = iconv(C, &src, &srcleft, &dst, &dstleft); if (ninval == (size_t)-1) { error = errno; /* * Incomplete input manifests as EINVAL -- ignore that, * unless we're trying the full-size input. * * Truncated output manifests as E2BIG -- ignore that, * unless we're trying the full-size output. */ if ((error != EINVAL || nsrc == S->nsrc) && (error != E2BIG || ndst == S->ndst)) { atf_tc_fail_nonfatal("[%s] iconv: %s (%d)", title, strerror(error), error); goto next; } } else if (ninval != S->ninval) { error = errno; atf_tc_fail_nonfatal("[%s] iconv:" " %zu invalid, expected %zu", title, ninval, S->ninval); } ATF_CHECK_MSG(src0 <= src && src <= src0 + srcleft0, "[%s] iconv:" " src went from %p to %p, expected [%p,%p]", title, src0, src, src0, src0 + srcleft0); ATF_CHECK_MSG(srcleft <= srcleft0, "[%s] iconv:" " srcleft went from %zu to %zu", title, srcleft0, srcleft); ATF_CHECK_MSG(dst0 <= dst && dst <= dst0 + dstleft0, "[%s] iconv:" " dst went from %p to %p, expected [%p,%p]", title, dst0, dst, dst0, dst0 + dstleft0); ATF_CHECK_MSG(dstleft <= dstleft0, "[%s] iconv:" " dstleft went from %zu to %zu", title, dstleft0, dstleft); if (memcmp(dst0, S->dst, MIN(ndst, dstleft0 - dstleft)) != 0) { size_t k; atf_tc_fail_nonfatal("[%s] iconv: bad conv", title); fprintf(stderr, "[%s] input: ", title); for (k = 0; k < nsrc; k++) fprintf(stderr, " %02x", (unsigned char)S->src[k]); fprintf(stderr, "\n"); fprintf(stderr, "[%s] expected: ", title); for (k = 0; k < ndst; k++) fprintf(stderr, " %02x", (unsigned char)S->dst[k]); fprintf(stderr, "\n"); fprintf(stderr, "[%s] got: ", title); for (k = 0; k < ndst; k++) fprintf(stderr, " %02x", (unsigned char)dst0[k]); fprintf(stderr, "\n"); } next: if (dst0[-1] != outguard) { atf_tc_fail_nonfatal("[%s] iconv overran before buffer:" " dst0[-1] = 0x%02x, expected 0x%02x", title, dst0[-1], outguard); } if (dst0[ndst] != outguard) { atf_tc_fail_nonfatal("[%s] iconv overran after buffer:" " dst0[ndst=%zu] = 0x%02x, expected 0x%02x", title, ndst, dst0[ndst], outguard); } if (dst[0] != outguard) { atf_tc_fail_nonfatal("[%s] iconv overran past updated dst:" " dst[0] = 0x%02x, expected 0x%02x", title, dst[0], outguard); } if (iconv_close(C) == -1) { error = errno; atf_tc_fail_nonfatal("[%s] iconv_close: %s (%d)", title, strerror(error), error); } } static void test_sample(const char *title, const struct sample *S) { char buf[128]; size_t nsrc, ndst; fprintf(stderr, "test %s from %s to %s\n", title, S->src_codeset, S->dst_codeset); for (nsrc = 0; nsrc <= S->nsrc; nsrc++) { snprintf(buf, sizeof(buf), "%s %zu/%zu", title, nsrc, S->ndst); test_sample_bounded(buf, S, nsrc, S->ndst); } for (ndst = 0; ndst <= S->ndst; ndst++) { snprintf(buf, sizeof(buf), "%s %zu/%zu", title, S->nsrc, ndst); test_sample_bounded(buf, S, S->nsrc, ndst); } } ATF_TC(iconv_samples); ATF_TC_HEAD(iconv_samples, tc) { atf_tc_set_md_var(tc, "descr", "Test iconv on various fixed samples"); } ATF_TC_BODY(iconv_samples, tc) { unsigned i; for (i = 0; i < __arraycount(samples); i++) { const struct sample *S = &samples[i]; struct sample reverse = { .src_codeset = S->dst_codeset, .dst_codeset = S->src_codeset, .nsrc = S->ndst, .src = S->dst, .ndst = S->nsrc, .dst = S->src, .ninval = S->ninval_rev, }; char buf[128]; if (S->xfail) atf_tc_expect_fail("%s", S->xfail); snprintf(buf, sizeof(buf), "case %u: %s to %s", i, S->src_codeset, S->dst_codeset); test_sample(buf, S); if (S->ninval_rev != IRREVERSIBLE) { snprintf(buf, sizeof(buf), "case %u: %s to %s", i, S->dst_codeset, S->src_codeset); test_sample(buf, &reverse); } if (S->xfail) atf_tc_expect_pass(); } } ATF_TC(iconv_pr59019_hz8); ATF_TC_HEAD(iconv_pr59019_hz8, tc) { atf_tc_set_md_var(tc, "descr", "Truncated HZ8 input from PR 59019"); } ATF_TC_BODY(iconv_pr59019_hz8, tc) { const char title[] = "iconv_pr59019_hz8"; char in[4] = "\x7e\x7b\x7e\x7e"; /* ~{~~ */ char out[4096], guard = arc4random(); char *src0, *src, *dst0, *dst; size_t srcleft0, srcleft, dstleft0, dstleft; iconv_t C; size_t ninval; memset(out, guard, sizeof(out)); REQUIRE_LIBC((C = iconv_open(/*to*/"UTF-8", /*from*/"HZ8")), (iconv_t)-1); src = src0 = in; srcleft = srcleft0 = sizeof(in); dst = dst0 = out + 1; dstleft = dstleft0 = sizeof(out) - 2; ninval = iconv(C, &src, &srcleft, &dst, &dstleft); /* * XXX Not actually 100% sure this is the correct result -- I * can't find a reference for the HZ8 encoding. */ ATF_CHECK_EQ_MSG(ninval, (size_t)-1, "[%s] iconv: ninval=%zu", title, ninval); ATF_CHECK_MSG(src0 <= src && src <= src0 + srcleft0, "[%s] iconv:" " src went from %p to %p, expected [%p,%p)", title, src0, src, src0, src0 + srcleft0); ATF_CHECK_MSG(srcleft <= srcleft0, "[%s] iconv:" " srcleft went from %zu to %zu", title, srcleft0, srcleft); ATF_CHECK_MSG(dst0 <= dst && dst <= dst0 + dstleft0, "[%s] iconv:" " dst went from %p to %p, expected [%p,%p)", title, dst0, dst, dst0, dst0 + dstleft0); ATF_CHECK_MSG(dstleft <= dstleft0, "[%s] iconv:" " dstleft went from %zu to %zu", title, dstleft0, dstleft); ATF_CHECK_EQ(dst0[-1], guard); ATF_CHECK_EQ(dst0[dstleft0], guard); RL(iconv_close(C)); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, iconv_pr59019_hz8); ATF_TP_ADD_TC(tp, iconv_samples); return atf_no_error(); } @ 1.7 log @iconv(3): Expand ISO-2022-CN tests a little. This one is broken for a partial input case, not yet sure why. PR 59019: various iconv issues @ text @d1 1 a1 1 /* $NetBSD: t_iconv.c,v 1.6 2026/06/30 23:16:53 riastradh Exp $ */ d34 1 a34 1 __RCSID("$NetBSD: t_iconv.c,v 1.6 2026/06/30 23:16:53 riastradh Exp $"); d216 1 a216 1 fprintf(stderr, " %02x", S->src[k]); d220 1 a220 1 fprintf(stderr, " %02x", S->dst[k]); d224 1 a224 1 fprintf(stderr, " %02x", dst0[k]); @ 1.6 log @iconv(3): Add a test case for ISO-2022-CN. From Mark Johnston of FreeBSD. PR 59019: various iconv issues @ text @d1 1 a1 1 /* $NetBSD: t_iconv.c,v 1.5 2026/06/30 23:16:34 riastradh Exp $ */ d34 1 a34 1 __RCSID("$NetBSD: t_iconv.c,v 1.5 2026/06/30 23:16:34 riastradh Exp $"); d122 2 a123 2 "ISO-2022-CN", 7, (const char[7]){0x1b,0x24,0x29,0x47,0x0e,0x58,0x6b}, d125 15 @ 1.5 log @iconv(3): Fix buffer overrun in ZW encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues @ text @d1 1 a1 1 /* $NetBSD: t_iconv.c,v 1.4 2026/06/30 23:16:08 riastradh Exp $ */ d34 1 a34 1 __RCSID("$NetBSD: t_iconv.c,v 1.4 2026/06/30 23:16:08 riastradh Exp $"); d120 5 @ 1.4 log @iconv(3): Fix buffer overrun in VIQR encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues @ text @d1 1 a1 1 /* $NetBSD: t_iconv.c,v 1.3 2026/06/30 23:15:52 riastradh Exp $ */ d34 1 a34 1 __RCSID("$NetBSD: t_iconv.c,v 1.3 2026/06/30 23:15:52 riastradh Exp $"); d68 1 a68 1 0, 0, "PR 59019: various libiconv issues" }, @ 1.3 log @iconv(3): Fix buffer overrun in UTF-7 encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues @ text @d1 1 a1 1 /* $NetBSD: t_iconv.c,v 1.2 2026/06/30 23:15:31 riastradh Exp $ */ d34 1 a34 1 __RCSID("$NetBSD: t_iconv.c,v 1.2 2026/06/30 23:15:31 riastradh Exp $"); d72 1 a72 1 0, 0, "PR 59019: various libiconv issues" }, @ 1.2 log @iconv(3): Fix null pointer dereference with HZ8 encoding. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues @ text @d1 1 a1 1 /* $NetBSD: t_iconv.c,v 1.1 2026/06/30 23:14:39 riastradh Exp $ */ d34 1 a34 1 __RCSID("$NetBSD: t_iconv.c,v 1.1 2026/06/30 23:14:39 riastradh Exp $"); d76 1 a76 1 0, IRREVERSIBLE, "PR 59019: various libiconv issues" }, d79 1 a79 1 0, 0, "PR 59019: various libiconv issues" }, d85 1 a85 1 0, 0, "PR 59019: various libiconv issues" }, @ 1.1 log @iconv(3): Draft some automatic tests. Based on a report by Nick Wellnhofer. PR 59019: various iconv issues @ text @d1 1 a1 1 /* $NetBSD$ */ d34 1 a34 1 __RCSID("$NetBSD: t_mbrtoc8.c,v 1.3 2024/08/20 17:43:09 riastradh Exp $"); a316 1 atf_tc_expect_signal(SIGSEGV, "PR 59019: various libiconv issues"); a317 1 atf_tc_expect_pass(); @