{"id":2221399,"url":"http://patchwork.ozlabs.org/api/1.2/patches/2221399/?format=json","web_url":"http://patchwork.ozlabs.org/project/glibc/patch/lhuwlygl3g6.fsf@oldenburg.str.redhat.com/","project":{"id":41,"url":"http://patchwork.ozlabs.org/api/1.2/projects/41/?format=json","name":"GNU C Library","link_name":"glibc","list_id":"libc-alpha.sourceware.org","list_email":"libc-alpha@sourceware.org","web_url":"","scm_url":"","webscm_url":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<lhuwlygl3g6.fsf@oldenburg.str.redhat.com>","list_archive_url":null,"date":"2026-04-09T12:32:09","name":"[v3] Use pending character state in IBM1390, IBM1399 character sets (CVE-2026-4046)","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"657db9bd1b164b2db1c8c0c8fa94617e2cef4286","submitter":{"id":14312,"url":"http://patchwork.ozlabs.org/api/1.2/people/14312/?format=json","name":"Florian Weimer","email":"fweimer@redhat.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/glibc/patch/lhuwlygl3g6.fsf@oldenburg.str.redhat.com/mbox/","series":[{"id":499285,"url":"http://patchwork.ozlabs.org/api/1.2/series/499285/?format=json","web_url":"http://patchwork.ozlabs.org/project/glibc/list/?series=499285","date":"2026-04-09T12:32:09","name":"[v3] Use pending character state in IBM1390, IBM1399 character sets (CVE-2026-4046)","version":3,"mbox":"http://patchwork.ozlabs.org/series/499285/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2221399/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2221399/checks/","tags":{},"related":[],"headers":{"Return-Path":"<libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org>","X-Original-To":["incoming@patchwork.ozlabs.org","libc-alpha@sourceware.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","libc-alpha@sourceware.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=YQew3I8O;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org;\n receiver=patchwork.ozlabs.org)","sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=YQew3I8O","sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","sourceware.org; spf=pass smtp.mailfrom=redhat.com","server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.133.124"],"Received":["from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4frzqV2vh9z1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 22:33:10 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 923E44BA2E09\n\tfor <incoming@patchwork.ozlabs.org>; Thu,  9 Apr 2026 12:33:08 +0000 (GMT)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by sourceware.org (Postfix) with ESMTP id 832EC4BA2E14\n for <libc-alpha@sourceware.org>; Thu,  9 Apr 2026 12:32:15 +0000 (GMT)","from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-190-o9p5LQq-MumOkEUZLVZVfw-1; Thu,\n 09 Apr 2026 08:32:13 -0400","from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id C31DE19560B4\n for <libc-alpha@sourceware.org>; Thu,  9 Apr 2026 12:32:12 +0000 (UTC)","from fweimer-oldenburg.csb.redhat.com (unknown [10.2.16.5])\n by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with\n ESMTPS\n id D2ECD195608E; Thu,  9 Apr 2026 12:32:11 +0000 (UTC)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 923E44BA2E09","OpenDKIM Filter v2.11.0 sourceware.org 832EC4BA2E14"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 832EC4BA2E14","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 832EC4BA2E14","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1775737935; cv=none;\n b=PvTSsD+8WS8EJhqhA0CJ6j5kGLdN1miqLqApTyfd9nai+qa6Ec0u5fwB3g4gWpF4FkLLOlIn7uhzQlJfNPkUEpRifkNWwNX2xTtYIq/YptN64RUByUJad5Hf5dGD8wNejA6a6zWNmWlWXDIL9/pEFYt4UG3t0y0I/GflBPBXM3A=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1775737935; c=relaxed/simple;\n bh=g7sr0ff9E2ut6iLOfPyZSZql1jZ+5AHpnnVKzCt4eSQ=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=BN1n9FTKSCcgrAbcRxUwkGizGZyrqzLPH87NXadiEszg8BjIwDn/WrUCThAkMehWVPS4PQ4hLKu06MuN34Y0oYRBnc1cGkmaku06HoSJ4bIZZGBvnK21IUvPVHZ2Y8nxPsxyNaq6me5xbykA8OB59jm0V0Cv0ygkV2d/Q+YVcSk=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1775737935;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type;\n bh=f5XTWL+20Eo3VBA+WNF+DFKk+DSKADXYskr3JvlRB0g=;\n b=YQew3I8OA5Oe/+6O+IyMeMN/BwL97yRjppHKTspZGmxRr7X+Lc0w69BhAhcV4CoQuhSJOC\n qEcdK1N+edyIT+Q62J/02XCwOk7Csc3rkg4MmMSMm4pjL1teLEmVhjHwkvZjVF8nBRupgk\n 1G2F/71lQjiLxhl3096830dajZ99YdM=","X-MC-Unique":"o9p5LQq-MumOkEUZLVZVfw-1","X-Mimecast-MFC-AGG-ID":"o9p5LQq-MumOkEUZLVZVfw_1775737933","From":"Florian Weimer <fweimer@redhat.com>","To":"libc-alpha@sourceware.org","Cc":"Carlos O'Donell <codonell@redhat.com>","Subject":"[PATCH v3] Use pending character state in IBM1390, IBM1399\n character sets (CVE-2026-4046)","Date":"Thu, 09 Apr 2026 14:32:09 +0200","Message-ID":"<lhuwlygl3g6.fsf@oldenburg.str.redhat.com>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Scanned-By":"MIMEDefang 3.0 on 10.30.177.17","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"CTRGMffghworasE1-bl346VS7rYlK-UDz2y5K5fUDyA_1775737933","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","X-BeenThere":"libc-alpha@sourceware.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Libc-alpha mailing list <libc-alpha.sourceware.org>","List-Unsubscribe":"<https://sourceware.org/mailman/options/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe>","List-Archive":"<https://sourceware.org/pipermail/libc-alpha/>","List-Post":"<mailto:libc-alpha@sourceware.org>","List-Help":"<mailto:libc-alpha-request@sourceware.org?subject=help>","List-Subscribe":"<https://sourceware.org/mailman/listinfo/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=subscribe>","Errors-To":"libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org"},"content":"Follow the example in iso-2022-jp-3.c and use the __count state\nvariable to store the pending character.  This avoids restarting\nthe conversion if the output buffer ends between two 4-byte UCS-4\ncode points, so that the assert reported in the bug can no longer\nhappen.\n\nEven though the fix is applied to ibm1364.c, the change is only\neffective for the two HAS_COMBINED codecs for IBM1390, IBM1399.\n\nThe test case was mostly auto-generated using\nclaude-4.6-opus-high-thinking, and composer-2-fast shows up in the\nlog as well.  During review, gpt-5.4-xhigh flagged that the original\nversion of the test case was not exercising the new character\nflush logic.\n\nThis fixes bug 33980.\n\n---\nv3: Fix typo in comment in test.  Avoid cast to (char **) in test case.\n\n iconvdata/Makefile       |   4 +-\n iconvdata/ibm1364.c      |  70 ++++++++++++++++++-----\n iconvdata/tst-bug33980.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 203 insertions(+), 16 deletions(-)\n\n\nbase-commit: 1b2f868fb4958fd59875695c1828d9804b116dc2","diff":"diff --git a/iconvdata/Makefile b/iconvdata/Makefile\nindex 26e888b443..fbb0067302 100644\n--- a/iconvdata/Makefile\n+++ b/iconvdata/Makefile\n@@ -76,7 +76,7 @@ tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \\\n \ttst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \\\n \tbug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \\\n \tbug-iconv13 bug-iconv14 bug-iconv15 \\\n-\ttst-iconv-iso-2022-cn-ext\n+\ttst-iconv-iso-2022-cn-ext tst-bug33980\n ifeq ($(have-thread-library),yes)\n tests += bug-iconv3\n endif\n@@ -333,6 +333,8 @@ $(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \\\n \t\t\t  $(addprefix $(objpfx),$(modules.so))\n $(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \\\n \t\t\t\t\t$(addprefix $(objpfx),$(modules.so))\n+$(objpfx)tst-bug33980.out: $(addprefix $(objpfx), $(gconv-modules)) \\\n+\t\t\t   $(addprefix $(objpfx),$(modules.so))\n \n $(objpfx)iconv-test.out: run-iconv-test.sh \\\n \t\t\t $(addprefix $(objpfx), $(gconv-modules)) \\\ndiff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c\nindex 4f41f22c12..8df66ea048 100644\n--- a/iconvdata/ibm1364.c\n+++ b/iconvdata/ibm1364.c\n@@ -67,12 +67,29 @@\n \n /* Since this is a stateful encoding we have to provide code which resets\n    the output state to the initial state.  This has to be done during the\n-   flushing.  */\n+   flushing.  For the to-internal direction (FROM_DIRECTION is true),\n+   there may be a pending character that needs flushing.  */\n #define EMIT_SHIFT_TO_INIT \\\n   if ((data->__statep->__count & ~7) != sb)\t\t\t\t      \\\n     {\t\t\t\t\t\t\t\t\t      \\\n       if (FROM_DIRECTION)\t\t\t\t\t\t      \\\n-\tdata->__statep->__count &= 7;\t\t\t\t\t      \\\n+\t{\t\t\t\t\t\t\t\t      \\\n+\t  uint32_t ch = data->__statep->__count >> 7;\t\t\t      \\\n+\t  if (__glibc_unlikely (ch != 0))\t\t\t\t      \\\n+\t    {\t\t\t\t\t\t\t\t      \\\n+\t      if (__glibc_unlikely (outend - outbuf < 4))\t\t      \\\n+\t\tstatus = __GCONV_FULL_OUTPUT;\t\t\t\t      \\\n+\t      else\t\t\t\t\t\t\t      \\\n+\t\t{\t\t\t\t\t\t\t      \\\n+\t\t  put32 (outbuf, ch);\t\t\t\t\t      \\\n+\t\t  outbuf += 4;\t\t\t\t\t\t      \\\n+\t\t  /* Clear character and db bit.  */\t\t\t      \\\n+\t\t  data->__statep->__count &= 7;\t\t\t\t      \\\n+\t\t}\t\t\t\t\t\t\t      \\\n+\t    }\t\t\t\t\t\t\t\t      \\\n+\t  else\t\t\t\t\t\t\t\t      \\\n+\t    data->__statep->__count &= 7;\t\t\t\t      \\\n+\t}\t\t\t\t\t\t\t\t      \\\n       else\t\t\t\t\t\t\t\t      \\\n \t{\t\t\t\t\t\t\t\t      \\\n \t  /* We are not in the initial state.  To switch back we have\t      \\\n@@ -99,11 +116,13 @@\n     *curcsp = save_curcs\n \n \n-/* Current codeset type.  */\n+/* Current codeset type.  The bit is stored in the __count variable of\n+   the conversion state.  If the db bit is set, bit 7 and above store\n+   a pending UCS-4 code point if non-zero.  */\n enum\n {\n-  sb = 0,\n-  db = 64\n+  sb = 0,\t\t\t/* Single byte mode.  */\n+  db = 64\t\t\t/* Double byte mode.  */\n };\n \n \n@@ -119,21 +138,29 @@ enum\n       }\t\t\t\t\t\t\t\t\t      \\\n     else\t\t\t\t\t\t\t\t      \\\n       {\t\t\t\t\t\t\t\t\t      \\\n-\t/* This is a combined character.  Make sure we have room.  */\t      \\\n-\tif (__glibc_unlikely (outptr + 8 > outend))\t\t\t      \\\n-\t  {\t\t\t\t\t\t\t\t      \\\n-\t    result = __GCONV_FULL_OUTPUT;\t\t\t\t      \\\n-\t    break;\t\t\t\t\t\t\t      \\\n-\t  }\t\t\t\t\t\t\t\t      \\\n-\t\t\t\t\t\t\t\t\t      \\\n \tconst struct divide *cmbp\t\t\t\t\t      \\\n \t  = &DB_TO_UCS4_COMB[ch - __TO_UCS4_COMBINED_MIN];\t\t      \\\n \tassert (cmbp->res1 != 0 && cmbp->res2 != 0);\t\t\t      \\\n \t\t\t\t\t\t\t\t\t      \\\n \tput32 (outptr, cmbp->res1);\t\t\t\t\t      \\\n \toutptr += 4;\t\t\t\t\t\t\t      \\\n-\tput32 (outptr, cmbp->res2);\t\t\t\t\t      \\\n-\toutptr += 4;\t\t\t\t\t\t\t      \\\n+\t\t\t\t\t\t\t\t\t      \\\n+\t/* See whether we have room for the second character.  */\t      \\\n+\tif (outend - outptr >= 4)\t\t\t\t\t      \\\n+\t  {\t\t\t\t\t\t\t\t      \\\n+\t    put32 (outptr, cmbp->res2);\t\t\t\t\t      \\\n+\t    outptr += 4;\t\t\t\t\t\t      \\\n+\t  }\t\t\t\t\t\t\t\t      \\\n+\telse\t\t\t\t\t\t\t\t      \\\n+\t  {\t\t\t\t\t\t\t\t      \\\n+\t    /* Otherwise store only the first character now, and\t      \\\n+\t       put the second one into the queue.  */\t\t\t      \\\n+\t    curcs |= cmbp->res2 << 7;\t\t\t\t\t      \\\n+\t    inptr += 2;\t\t\t\t\t\t\t      \\\n+\t    /* Tell the caller why we terminate the loop.  */\t\t      \\\n+\t    result = __GCONV_FULL_OUTPUT;\t\t\t\t      \\\n+\t    break;\t\t\t\t\t\t\t      \\\n+\t  }\t\t\t\t\t\t\t\t      \\\n       }\t\t\t\t\t\t\t\t\t      \\\n   }\n #else\n@@ -153,7 +180,20 @@ enum\n #define LOOPFCT \t\tFROM_LOOP\n #define BODY \\\n   {\t\t\t\t\t\t\t\t\t      \\\n-    uint32_t ch = *inptr;\t\t\t\t\t\t      \\\n+    uint32_t ch;\t\t\t\t\t\t\t      \\\n+\t\t\t\t\t\t\t\t\t      \\\n+    ch = curcs >> 7;\t\t\t\t\t\t\t      \\\n+    if (__glibc_unlikely (ch != 0))\t\t\t\t\t      \\\n+      {\t\t\t\t\t\t\t\t\t      \\\n+\tput32 (outptr, ch);\t\t\t\t\t\t      \\\n+\toutptr += 4;\t\t\t\t\t\t\t      \\\n+\t/* Remove the pending character, but preserve state bits.  */\t      \\\n+\tcurcs &= (1 << 7) - 1;\t\t\t\t\t\t      \\\n+\tcontinue;\t\t\t\t\t\t\t      \\\n+      }\t\t\t\t\t\t\t\t\t      \\\n+\t\t\t\t\t\t\t\t\t      \\\n+    /* Otherwise read the next input byte.  */\t\t\t\t      \\\n+    ch = *inptr;\t\t\t\t\t\t\t      \\\n \t\t\t\t\t\t\t\t\t      \\\n     if (__builtin_expect (ch, 0) == SO)\t\t\t\t\t      \\\n       {\t\t\t\t\t\t\t\t\t      \\\ndiff --git a/iconvdata/tst-bug33980.c b/iconvdata/tst-bug33980.c\nnew file mode 100644\nindex 0000000000..da8fd336e6\n--- /dev/null\n+++ b/iconvdata/tst-bug33980.c\n@@ -0,0 +1,145 @@\n+/* Test for bug 33980: combining characters in IBM1390/IBM1399.\n+   Copyright (C) 2026 Free Software Foundation, Inc.\n+   This file is part of the GNU C Library.\n+\n+   The GNU C Library is free software; you can redistribute it and/or\n+   modify it under the terms of the GNU Lesser General Public\n+   License as published by the Free Software Foundation; either\n+   version 2.1 of the License, or (at your option) any later version.\n+\n+   The GNU C Library is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+   Lesser General Public License for more details.\n+\n+   You should have received a copy of the GNU Lesser General Public\n+   License along with the GNU C Library; if not, see\n+   <https://www.gnu.org/licenses/>.  */\n+\n+#include <alloc_buffer.h>\n+#include <errno.h>\n+#include <iconv.h>\n+#include <stdbool.h>\n+#include <string.h>\n+\n+#include <support/check.h>\n+#include <support/next_to_fault.h>\n+#include <support/support.h>\n+\n+/* Run iconv in a loop with a small output buffer of OUTBUFSIZE bytes\n+   starting at OUTBUF.  OUTBUF should be right before an unmapped page\n+   so that writing past the end will fault.  Skip SHIFT bytes at the\n+   start of the input and output, to exercise different buffer\n+   alignment.  TRUNCATE indicates skipped bytes at the end of\n+   input (0 and 1 a valid).  */\n+static void\n+test_one (const char *encoding, unsigned int shift, unsigned int truncate,\n+          char *outbuf, size_t outbufsize)\n+{\n+  /* In IBM1390 and IBM1399, the DBCS code 0xECB5 expands to two\n+     Unicode code points when translated.  */\n+  static char input[] =\n+    {\n+      /* 8 letters X.  */\n+      0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,\n+      /* SO, 0xECB5, SI: shift to DBCS, special character, shift back.  */\n+      0x0e, 0xec, 0xb5, 0x0f\n+    };\n+\n+  /* Expected output after UTF-8 conversion.  */\n+  static char expected[] =\n+    {\n+      'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X',\n+      /* U+304B (HIRAGANA LETTER KA).  */\n+      0xe3, 0x81, 0x8b,\n+      /* U+309A (COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK).  */\n+      0xe3, 0x82, 0x9a\n+    };\n+\n+  iconv_t cd = iconv_open (\"UTF-8\", encoding);\n+  TEST_VERIFY_EXIT (cd != (iconv_t) -1);\n+\n+  char result_storage[64];\n+  struct alloc_buffer result_buf\n+    = alloc_buffer_create (result_storage, sizeof (result_storage));\n+\n+  char *inptr = &input[shift];\n+  size_t inleft = sizeof (input) - shift - truncate;\n+\n+  while (inleft > 0)\n+    {\n+      char *outptr = outbuf;\n+      size_t outleft = outbufsize;\n+      size_t inleft_before = inleft;\n+\n+      size_t ret = iconv (cd, &inptr, &inleft, &outptr, &outleft);\n+      size_t produced = outptr - outbuf;\n+      alloc_buffer_copy_bytes (&result_buf, outbuf, produced);\n+\n+      if (ret == (size_t) -1 && errno == E2BIG)\n+        {\n+          if (produced == 0 && inleft == inleft_before)\n+            {\n+              /* Output buffer too small to make progress.  This is\n+                 expected for very small output buffer sizes.  */\n+              TEST_VERIFY_EXIT (outbufsize < 3);\n+              break;\n+            }\n+          continue;\n+        }\n+      if (ret == (size_t) -1)\n+        FAIL_EXIT1 (\"%s (outbufsize %zu): iconv: %m\", encoding, outbufsize);\n+      break;\n+    }\n+\n+  /* Flush any pending state (e.g. a buffered combined character).  */\n+  while (true)\n+    {\n+      char *outptr = outbuf;\n+      size_t outleft = outbufsize;\n+\n+      size_t ret = iconv (cd, NULL, NULL, &outptr, &outleft);\n+      size_t produced = outptr - outbuf;\n+      alloc_buffer_copy_bytes (&result_buf, outbuf, produced);\n+\n+      if (ret == (size_t) -1 && errno == E2BIG)\n+        continue;\n+      TEST_VERIFY_EXIT (ret == 0);\n+      break;\n+    }\n+\n+  TEST_VERIFY_EXIT (!alloc_buffer_has_failed (&result_buf));\n+  size_t result_used\n+    = sizeof (result_storage) - alloc_buffer_size (&result_buf);\n+\n+  if (outbufsize >= 3)\n+    {\n+      TEST_COMPARE (inleft, 0);\n+      TEST_COMPARE (result_used, sizeof (expected) - shift);\n+      TEST_COMPARE_BLOB (result_storage, result_used,\n+                         &expected[shift], sizeof (expected) - shift);\n+    }\n+\n+  TEST_VERIFY_EXIT (iconv_close (cd) == 0);\n+}\n+\n+static int\n+do_test (void)\n+{\n+  struct support_next_to_fault ntf\n+    = support_next_to_fault_allocate (8);\n+\n+  for (int shift = 0; shift <= 8; ++shift)\n+    for (int truncate = 0; truncate < 2; ++truncate)\n+      for (size_t outbufsize = 1; outbufsize <= 8; outbufsize++)\n+        {\n+          char *outbuf = ntf.buffer + ntf.length - outbufsize;\n+          test_one (\"IBM1390\", shift, truncate, outbuf, outbufsize);\n+          test_one (\"IBM1399\", shift, truncate, outbuf, outbufsize);\n+        }\n+\n+  support_next_to_fault_free (&ntf);\n+  return 0;\n+}\n+\n+#include <support/test-driver.c>\n","prefixes":["v3"]}